app开发者平台在数字化时代的重要性与发展趋势解析
1507
2022-11-21
FFmpeg源代码:avcodec_send_packet
avcodec_send_packet() 函数的主要功能是发送libx264等packet到解码队列中
/** * Supply raw packet data as input to a decoder. * * Internally, this call will copy relevant AVCodecContext fields, which can * influence decoding per-packet, and apply them when the packet is actually * decoded. (For example AVCodecContext.skip_frame, which might direct the * decoder to drop the frame contained by the packet sent with this function.) * * @warning The input buffer, avpkt->data must be AV_INPUT_BUFFER_PADDING_SIZE * larger than the actual read bytes because some optimized bitstream * readers read 32 or 64 bits at once and could read over the end. * * @note The AVCodecContext MUST have been opened with @ref avcodec_open2() * before packets may be fed to the decoder. * * @param avctx codec context * @param[in] avpkt The input AVPacket. Usually, this will be a single video * frame, or several complete audio frames. * Ownership of the packet remains with the caller, and the * decoder will not write to the packet. The decoder may create * a reference to the packet data (or copy it if the packet is * not reference-counted). * Unlike with older APIs, the packet is always fully consumed, * and if it contains multiple frames (e.g. some audio codecs), * will require you to call avcodec_receive_frame() multiple * times afterwards before you can send a new packet. * It can be NULL (or an AVPacket with data set to NULL and * size set to 0); in this case, it is considered a flush * packet, which signals the end of the stream. Sending the * first flush packet will return success. Subsequent ones are * unnecessary and will return AVERROR_EOF. If the decoder * still has frames buffered, it will return them after sending * a flush packet. * * @return 0 on success, otherwise negative error code: * AVERROR(EAGAIN): input is not accepted in the current state - user * must read output with avcodec_receive_frame() (once * all output is read, the packet should be resent, and * the call will not fail with EAGAIN). * AVERROR_EOF: the decoder has been flushed, and no new packets can * be sent to it (also returned if more than 1 flush * packet is sent) * AVERROR(EINVAL): codec not opened, it is an encoder, or requires flush * AVERROR(ENOMEM): failed to add packet to internal queue, or similar * other errors: legitimate decoding errors */int avcodec_send_packet(AVCodecContext *avctx, const AVPacket *avpkt);
该函数的使用方法在注释中写的比较清楚,用中文简单描述下参数:
avpkt: 输入的AVPakcet, 通常情况下,可能是一个视频帧或者几个完整的音频帧。解码器不会写入该packet。解码器会创建对该数据包数据的引用(或者拷贝,如果该packet 不是引用计数的话)。不像旧的api, 该packet 数据总是被完全消费,如果该packet包含多个帧(比如多个音频帧),在发送新的packet之前,必须调用多次avcodec_receive_frame()。 如果设置为NULL的话,默认为是一个刷新packet avctx: 在发送packet之前,AVCodecContext必须使用avcodec_open2()打开
返回错误码:
0 : success AVERROR(EAGAIN):当前状态下不接受输入, 用户必须使用avcodec_receive_frame()读取输出(一旦所有的output被读取, 应该重新发送packet, 而且该接口不会返回EAGAIN) AVERROR_EOF: 解码器已经被刷新,不能再发送新的packet给解码器 AVERROR(EINVAL): 解码器没有被打开,或者是一个编码器,或者需要刷新 AVERROR(ENOMEM): 无法将数据包添加到内部队列或类似队列
avcodec_send_packet()的定义位于ffmpeg/libavcodec/decode.c, 如下:
int attribute_align_arg avcodec_send_packet(AVCodecContext *avctx, const AVPacket *avpkt){ AVCodecInternal *avci = avctx->internal; int ret; //编解码器是否打开 //是否为decoder, 非0:是; 0:不是 if (!avcodec_is_open(avctx) || !av_codec_is_decoder(avctx->codec)) return AVERROR(EINVAL); //int AVCodecInternal::draining //检查API使用情况, 在编解码器draining 的时候(个人理解是编解码数据都处理完了), 需要执行刷新codec 操作 //这边的目的是判断编解码是否结束 if (avctx->internal->draining) return AVERROR_EOF; //判断编码packet是否有数据 if (avpkt && !avpkt->size && avpkt->data) return AVERROR(EINVAL); // 总的来说,就是清除buffer_pkt 中旧的数据,建立新的packet avpkt 的索引或者拷贝avpkt中的数据到buffer_pkt av_packet_unref(avci->buffer_pkt); if (avpkt && (avpkt->data || avpkt->side_data_elems)) { ret = av_packet_ref(avci->buffer_pkt, avpkt); if (ret < 0) return ret; } //提交一个包进行过滤, 不解码, bsf: bitstream filter ret = av_bsf_send_packet(avci->bsf, avci->buffer_pkt); if (ret < 0) { av_packet_unref(avci->buffer_pkt); return ret; } if (!avci->buffer_frame->buf[0]) { //实际的解码入口 ret = decode_receive_frame_internal(avctx, avci->buffer_frame); if (ret < 0 && ret != AVERROR(EAGAIN) && ret != AVERROR_EOF) return ret; } return 0;}
版权声明:本文内容由网络用户投稿,版权归原作者所有,本站不拥有其著作权,亦不承担相应法律责任。如果您发现本站中有涉嫌抄袭或描述失实的内容,请联系我们jiasou666@gmail.com 处理,核实后本网站将在24小时内删除侵权内容。
发表评论
暂时没有评论,来抢沙发吧~