郑州 网站建设 东区,赵艳红网站建设规划,网站广告收费标准,建设网站的新闻参考链接
FFmpeg源代码简单分析#xff1a;avcodec_encode_video()_雷霄骅的博客-CSDN博客_avcodec_encode_video2
avcodec_encode_video()
该函数用于编码一帧视频数据。函数已被弃用参考链接#xff1a;FFmpeg 新旧版本编码 API 的区别_zouzhiheng的博客-CSDN博客
send_f…参考链接
FFmpeg源代码简单分析avcodec_encode_video()_雷霄骅的博客-CSDN博客_avcodec_encode_video2
avcodec_encode_video()
该函数用于编码一帧视频数据。函数已被弃用参考链接FFmpeg 新旧版本编码 API 的区别_zouzhiheng的博客-CSDN博客
send_frame 和 receive_packet 例子
static void encode(AVCodecContext *enc_ctx, AVFrame *frame, AVPacket *pkt,FILE *outfile)
{int ret;/* send the frame to the encoder */if (frame)printf(Send frame %3PRId64\n, frame-pts);ret avcodec_send_frame(enc_ctx, frame);if (ret 0) {fprintf(stderr, Error sending a frame for encoding\n);exit(1);}while (ret 0) {ret avcodec_receive_packet(enc_ctx, pkt);if (ret AVERROR(EAGAIN) || ret AVERROR_EOF)return;else if (ret 0) {fprintf(stderr, Error during encoding\n);exit(1);}printf(Write packet %3PRId64 (size%5d)\n, pkt-pts, pkt-size);fwrite(pkt-data, 1, pkt-size, outfile);av_packet_unref(pkt);}
}avcodec_encode_video一个函数即可完成编码操作编码成功后可直接使用压缩后的数据。新版 API 需要两个函数一起使用一个 send一个 receive分别用于发送原始视频数据、获取编码后的数据具体在哪里完成了编码动作暂时未知。avcodec_encode_video 一次编码动作对应 0 个或 1 个 AVFrame 和 0 个或 1 个 AVPacket。新本 API 一次编码动作对应 0 个或 1 个 AVFrame 和 0 个或多个 AVPacket。
avcodec_send_frame
avcodec_send_frame 的声明如下
/*** Supply a raw video or audio frame to the encoder. Use avcodec_receive_packet()* to retrieve buffered output packets.** param avctx codec context* param[in] frame AVFrame containing the raw audio or video frame to be encoded.* Ownership of the frame remains with the caller, and the* encoder will not write to the frame. The encoder may create* a reference to the frame data (or copy it if the frame is* not reference-counted).* It can be NULL, in which case it is considered a flush* packet. This signals the end of the stream. If the encoder* still has packets buffered, it will return them after this* call. Once flushing mode has been entered, additional flush* packets are ignored, and sending frames will return* AVERROR_EOF.** For audio:* If AV_CODEC_CAP_VARIABLE_FRAME_SIZE is set, then each frame* can have any number of samples.* If it is not set, frame-nb_samples must be equal to* avctx-frame_size for all frames except the last.* The final frame may be smaller than avctx-frame_size.* 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_packet() (once* all output is read, the packet should be resent, and* the call will not fail with EAGAIN).* AVERROR_EOF: the encoder has been flushed, and no new frames can* be sent to it* AVERROR(EINVAL): codec not opened, it is a decoder, or requires flush* AVERROR(ENOMEM): failed to add packet to internal queue, or similar* other errors: legitimate encoding errors*/
int avcodec_send_frame(AVCodecContext *avctx, const AVFrame *frame); 从注释中可以看出这个函数用于发送原始的视频/音频数据给编码器编码参数 AVFrame 同样可以为 NULL 以刷新编码器。
int attribute_align_arg avcodec_send_frame(AVCodecContext *avctx, const AVFrame *frame)
{AVCodecInternal *avci avctx-internal;int ret;if (!avcodec_is_open(avctx) || !av_codec_is_encoder(avctx-codec))return AVERROR(EINVAL);if (avci-draining)return AVERROR_EOF;if (avci-buffer_frame-buf[0])return AVERROR(EAGAIN);if (!frame) {avci-draining 1;} else {ret encode_send_frame_internal(avctx, frame);if (ret 0)return ret;}if (!avci-buffer_pkt-data !avci-buffer_pkt-side_data) {ret encode_receive_packet_internal(avctx, avci-buffer_pkt);if (ret 0 ret ! AVERROR(EAGAIN) ret ! AVERROR_EOF)return ret;}avctx-frame_number;return 0;
}avcodec_receive_packet
avcodec_receive_packet 则用于获取编码后的视频/音频数据。它的声明如下
/*** Read encoded data from the encoder.** param avctx codec context* param avpkt This will be set to a reference-counted packet allocated by the* encoder. Note that the function will always call* av_packet_unref(avpkt) before doing anything else.* return 0 on success, otherwise negative error code:* AVERROR(EAGAIN): output is not available in the current state - user* must try to send input* AVERROR_EOF: the encoder has been fully flushed, and there will be* no more output packets* AVERROR(EINVAL): codec not opened, or it is a decoder* other errors: legitimate encoding errors*/
int avcodec_receive_packet(AVCodecContext *avctx, AVPacket *avpkt);
int attribute_align_arg avcodec_receive_packet(AVCodecContext *avctx, AVPacket *avpkt)
{AVCodecInternal *avci avctx-internal;int ret;av_packet_unref(avpkt);if (!avcodec_is_open(avctx) || !av_codec_is_encoder(avctx-codec))return AVERROR(EINVAL);if (avci-buffer_pkt-data || avci-buffer_pkt-side_data) {av_packet_move_ref(avpkt, avci-buffer_pkt);} else {ret encode_receive_packet_internal(avctx, avpkt);if (ret 0)return ret;}return 0;
}注意事项
旧版本视频编码使用 avcodec_encode_video2音频编码使用 avcodec_encode_audio2新版本音视频编码统一使用 avcodec_send_frame 和 avcodec_receive_packet旧版本 API 内部直接调用了 AVCodec 的函数指针 encode2新版本 API 首先会判断编码器是否实现了函数指针 send_frame 和 receive_packet如果实现了优先使用send_frame 和 receive_packet否则使用旧版本的 encode2 未找到代码证明每个版本之间差异较大目前仅发现编码器 ff_hevc_nvenc_encoder 实现了新版本的 APIsend_frame 和 receive_packetlibx264、AAC 等编码器依然使用了旧版本的 APIencode2请使用手机扫一扫x