seo网站排名优化案例,站长之家网站建设,怀化市住房和城乡建设局网站,wordpress qqworld一、需求
在某些情况下#xff0c;可能需要直接使用H264/H265等原始数据流进行解码#xff0c;比较常用的udp下的h264/h265。这时需要 av_parser_parse2 来组AVPacket,但对于视频的信息#xff1a;宽高、格式等#xff0c;可以根据 AVCodecParserContext 来获取#xff0…一、需求
在某些情况下可能需要直接使用H264/H265等原始数据流进行解码比较常用的udp下的h264/h265。这时需要 av_parser_parse2 来组AVPacket,但对于视频的信息宽高、格式等可以根据 AVCodecParserContext 来获取也可以直接提取sps/pps/sei这些原始数据extradata 本文讲如何从原始数据流(AVPacket)中找出 extradata 信息
二、ffmpeg5.0版本以下
在旧版本的ffmpeg中 AVCodecParserContext 内部有个 split 函数可以直接返回 extradata 在数据流中的位置 AVCodecParserContext* m_parser nullptr;// 初始化 m_parser // ........//// m_ctx : AVCodecContext*// pkt : AVPacket*// 其中第一个参数 m_ctx 可以不设置,直接设置为nullptr也可auto re m_parser-parser-split(m_ctx, pkt-data, pkt-size);if (re 0) {if (m_ctx-extradata_size 0 m_ctx-extradata nullptr) {//存放于解码器的上下文中,,在m_ctx释放的时候会自动释放m_ctx-extradata_size re;m_ctx-extradata (uint8_t*) av_malloc(m_ctx-extradata_size AV_INPUT_BUFFER_PADDING_SIZE);memcpy(m_ctx-extradata, pkt-data, m_ctx-extradata_size);}}
三、ffmpeg5.0版本以上
ffmpeg5.0后 AVCodecParserContext 的 split 函数已删除 但可以使用 av_bsf_get_by_name(extract_extradata) 以下代码可供参考
bool VideoStreamUdpH26X::setupExtraData(const AVCodecParserContext* parser,
AVCodecContext* ctx,
AVPacket* pkt)
{bool need false;// 检查输入参数及必要信息if (!parser || !pkt || !ctx)return need;if (parser-width 0 || parser-height 0)return need;// 获取 extract_extradata BSFconst AVBitStreamFilter* bsf av_bsf_get_by_name(extract_extradata);if (!bsf) {LOG_DEBUG() extract_extradata BSF not found;return need;}AVBSFContext* bsf_ctx nullptr;auto ret av_bsf_alloc(bsf, bsf_ctx);if (ret 0) {LOG_DEBUG() Failed to allocate BSF context, ret ret;return need;}// 设置 BSF 的输入参数使用 parser 的部分信息bsf_ctx-par_in-codec_id (AVCodecID) parser-parser-codec_ids[0];bsf_ctx-par_in-codec_type AVMEDIA_TYPE_VIDEO;bsf_ctx-par_in-width parser-width;bsf_ctx-par_in-height parser-height;ret av_bsf_init(bsf_ctx);if (ret 0) {LOG_DEBUG() Failed to initialize BSF context, ret ret;av_bsf_free(bsf_ctx);return need;}// 将包送入 BSF 提取 extradataret av_bsf_send_packet(bsf_ctx, pkt);if (ret 0) {LOG_DEBUG() Failed to send packet to BSF, ret ret printError(ret);av_bsf_free(bsf_ctx);return need;}// 从 BSF 中取出过滤后的包ret av_bsf_receive_packet(bsf_ctx, pkt);if (ret 0 ret ! AVERROR(EAGAIN) ret ! AVERROR_EOF) {LOG_DEBUG() Failed to receive packet from BSF, ret ret printError(ret);av_bsf_free(bsf_ctx);return need;}size_t extradata_size 0;uint8_t* side_extradata av_packet_get_side_data(pkt,AV_PKT_DATA_NEW_EXTRADATA,extradata_size);if (side_extradata extradata_size 0) {// 更新 extradataif (ctx-extradata_size ! extradata_size) {if (ctx-extradata) {av_freep(ctx-extradata);ctx-extradata_size 0;}ctx-extradata (uint8_t*) av_malloc(extradata_size AV_INPUT_BUFFER_PADDING_SIZE);if (!ctx-extradata) {LOG_DEBUG() Failed to allocate memory for extradata;av_bsf_free(bsf_ctx);return need;}ctx-extradata_size extradata_size;memcpy(ctx-extradata, side_extradata, ctx-extradata_size);LOG_DEBUG() Extracted extradata: QByteArray((char*) ctx-extradata, ctx-extradata_size).toHex();}need true;}av_bsf_free(bsf_ctx);return need;
}