FFmpeg 编码详细流程
介绍
- FFmpeg的 libavcodec 模块完成音视频多媒体的编解码模块。
- FFmpeg 本身不具有音视频编码的功能和底层能力,只是对各类第三方的编码器API 进行封装调用。
- 老版本的 FFmpeg 将avcodec_encode_video2()作为视频的解码函数 API,将avcodec_encode_audio2()作为音频的解码函数 API;从 3.4版本开始已经将二者标记为废弃过时 API(attribute_deprecated)。
- 新版本 FFmpeg 将 avcodec_send_frame() 与 avcodec_receive_packet() 作为音视频的解码函数 API,但同时仍然保留了对老接口的兼容,通过avcodec_encode_video2()、avcodec_encode_audio2()调用 compat_decode()完成对新 API 的封装。
//具体可以参考 FFmpeg 中 doc/APIchanges 中的记录.2016-04-21 - 7fc329e - lavc 57.37.100 - avcodec.hAdd a new audio/video encoding and decoding API with decoupled inputand output -- avcodec_send_packet(), avcodec_receive_frame(),avcodec_send_frame() and avcodec_receive_packet().
- 可以通过命令行ffmpeg configure -encoders查看支持哪些编码器格式;但是好像configure 里说明的和源码不完全一致,源码里有支持 kvazaar 编码器(一种符合h265编码标准的开源编码器),但 configure 并没有体现出来。
Encoders:V..... = VideoA..... = AudioS..... = Subtitle.F.... = Frame-level multithreading..S... = Slice-level multithreading...X.. = Codec is experimental....B. = Supports draw_horiz_band.....D = Supports direct rendering method 1------V....D a64multi Multicolor charset for Commodore 64 (codec a64_multi)V....D a64multi5 Multicolor charset for Commodore 64, extended with 5th color (colram) (codec a64_multi5)V....D alias_pix Alias/Wavefront PIX imageV..... amv AMV VideoV....D apng APNG (Animated Portable Network Graphics) imageV....D asv1 ASUS V1V....D asv2 ASUS V2V....D libaom-av1 libaom AV1 (codec av1)V....D librav1e librav1e AV1 (codec av1)V..... libsvtav1 SVT-AV1(Scalable Video Technology for AV1) encoder (codec av1)V....D avrp Avid 1:1 10-bit RGB PackerV..X.D avui Avid Meridien UncompressedV....D ayuv Uncompressed packed MS 4:4:4:4VF...D bitpacked BitpackedV....D bmp BMP (Windows and OS/2 bitmap)VF...D cfhd GoPro CineForm HDV....D cinepak CinepakV....D cljr Cirrus Logic AccuPakV.S..D vc2 SMPTE VC-2 (codec dirac)VFS..D dnxhd VC3/DNxHDV....D dpx DPX (Digital Picture Exchange) imageVFS..D dvvideo DV (Digital Video)VF...D exr OpenEXR imageV.S..D ffv1 FFmpeg video codec #1VF...D ffvhuff Huffyuv FFmpeg variantV....D fits Flexible Image Transport SystemV....D flashsv Flash Screen VideoV....D flashsv2 Flash Screen Video Version 2V..... flv FLV / Sorenson Spark / Sorenson H.263 (Flash Video) (codec flv1)V....D gif GIF (Graphics Interchange Format)V..... h261 H.261V..... h263 H.263 / H.263-1996V.S... h263p H.263+ / H.263-1998 / H.263 version 2V....D libx264 libx264 H.264 / AVC / MPEG-4 AVC / MPEG-4 part 10 (codec h264)V....D libx264rgb libx264 H.264 / AVC / MPEG-4 AVC / MPEG-4 part 10 RGB (codec h264)V....D h264_videotoolbox VideoToolbox H.264 Encoder (codec h264)V.S..D hap Vidvox HapVF...D hdr HDR (Radiance RGBE format) imageV....D libx265 libx265 H.265 / HEVC (codec hevc)V....D hevc_videotoolbox VideoToolbox H.265 Encoder (codec hevc)VF...D huffyuv Huffyuv / HuffYUVV....D jpeg2000 JPEG 2000VF.... libopenjpeg OpenJPEG JPEG 2000 (codec jpeg2000)VF...D jpegls JPEG-LSVF...D ljpeg Lossless JPEGVF...D magicyuv MagicYUV videoVFS... mjpeg MJPEG (Motion JPEG)V.S... mpeg1video MPEG-1 videoV.S... mpeg2video MPEG-2 videoV.S... mpeg4 MPEG-4 part 2V....D libxvid libxvidcore MPEG-4 part 2 (codec mpeg4)V..... msmpeg4v2 MPEG-4 part 2 Microsoft variant version 2V..... msmpeg4 MPEG-4 part 2 Microsoft variant version 3 (codec msmpeg4v3)V..... msvideo1 Microsoft Video-1V....D pam PAM (Portable AnyMap) imageV....D pbm PBM (Portable BitMap) imageV....D pcx PC Paintbrush PCX imageV....D pfm PFM (Portable FloatMap) imageV....D pgm PGM (Portable GrayMap) imageV....D pgmyuv PGMYUV (Portable GrayMap YUV) imageV....D phm PHM (Portable HalfFloatMap) imageVF...D png PNG (Portable Network Graphics) imageV....D ppm PPM (Portable PixelMap) imageVF...D prores Apple ProResVF...D prores_aw Apple ProRes (codec prores)VFS... prores_ks Apple ProRes (iCodec Pro) (codec prores)V....D prores_videotoolbox VideoToolbox ProRes Encoder (codec prores)VF...D qoi QOI (Quite OK Image format) imageV....D qtrle QuickTime Animation (RLE) videoV....D r10k AJA Kona 10-bit RGB CodecV....D r210 Uncompressed RGB 10-bitVF...D rawvideo raw videoV....D roqvideo id RoQ video (codec roq)V....D rpza QuickTime video (RPZA)V..... rv10 RealVideo 1.0V..... rv20 RealVideo 2.0V....D sgi SGI imageV....D smc QuickTime Graphics (SMC)V....D snow SnowV..... speedhq NewTek SpeedHQV....D sunrast Sun Rasterfile imageV....D svq1 Sorenson Vector Quantizer 1 / Sorenson Video 1 / SVQ1V....D targa Truevision Targa imageV....D libtheora libtheora Theora (codec theora)VF...D tiff TIFF imageVF...D utvideo Ut VideoVF...D v210 Uncompressed 4:2:2 10-bitV....D v308 Uncompressed packed 4:4:4V....D v408 Uncompressed packed QT 4:4:4:4V....D v410 Uncompressed 4:4:4 10-bitV.S..D vbn Vizrt Binary ImageV..... vnull null videoV....D libvpx libvpx VP8 (codec vp8)V....D libvpx-vp9 libvpx VP9 (codec vp9)VF...D wbmp WBMP (Wireless Application Protocol Bitmap) imageV....D libwebp_anim libwebp WebP image (codec webp)V....D libwebp libwebp WebP image (codec webp)V..... wmv1 Windows Media Video 7V..... wmv2 Windows Media Video 8V..... wrapped_avframe AVFrame to AVPacket passthroughV....D xbm XBM (X BitMap) imageV....D xface X-face imageV....D xwd XWD (X Window Dump) imageV....D y41p Uncompressed YUV 4:1:1 12-bitV....D yuv4 Uncompressed packed 4:2:0VF...D zlib LCL (LossLess Codec Library) ZLIBV....D zmbv Zip Motion Blocks VideoA....D aac AAC (Advanced Audio Coding)A..... aac_at aac (AudioToolbox) (codec aac)A....D ac3 ATSC A/52A (AC-3)A....D ac3_fixed ATSC A/52A (AC-3) (codec ac3)A....D adpcm_adx SEGA CRI ADX ADPCMA....D adpcm_argo ADPCM Argonaut GamesA....D g722 G.722 ADPCM (codec adpcm_g722)A....D g726 G.726 ADPCM (codec adpcm_g726)A....D g726le G.726 little endian ADPCM ("right-justified") (codec adpcm_g726le)A....D adpcm_ima_alp ADPCM IMA High Voltage Software ALPA....D adpcm_ima_amv ADPCM IMA AMVA....D adpcm_ima_apm ADPCM IMA Ubisoft APMA....D adpcm_ima_qt ADPCM IMA QuickTimeA....D adpcm_ima_ssi ADPCM IMA Simon & Schuster InteractiveA....D adpcm_ima_wav ADPCM IMA WAVA....D adpcm_ima_ws ADPCM IMA WestwoodA....D adpcm_ms ADPCM MicrosoftA....D adpcm_swf ADPCM Shockwave FlashA....D adpcm_yamaha ADPCM YamahaA....D alac ALAC (Apple Lossless Audio Codec)A..... alac_at alac (AudioToolbox) (codec alac)A....D libopencore_amrnb OpenCORE AMR-NB (Adaptive Multi-Rate Narrow-Band) (codec amr_nb)A..... anull null audioA....D aptx aptX (Audio Processing Technology for Bluetooth)A....D aptx_hd aptX HD (Audio Processing Technology for Bluetooth)A....D comfortnoise RFC 3389 comfort noise generatorA....D dfpwm DFPWM1a audioA..X.D dca DCA (DTS Coherent Acoustics) (codec dts)A....D eac3 ATSC A/52 E-AC-3A....D flac FLAC (Free Lossless Audio Codec)A....D g723_1 G.723.1A..... ilbc_at ilbc (AudioToolbox) (codec ilbc)A..X.D mlp MLP (Meridian Lossless Packing)A....D mp2 MP2 (MPEG audio layer 2)A....D mp2fixed MP2 fixed point (MPEG audio layer 2) (codec mp2)A....D libmp3lame libmp3lame MP3 (MPEG audio layer 3) (codec mp3)A....D nellymoser Nellymoser AsaoA..X.D opus OpusA....D libopus libopus Opus (codec opus)A....D pcm_alaw PCM A-law / G.711 A-lawA..... pcm_alaw_at pcm_alaw (AudioToolbox) (codec pcm_alaw)A....D pcm_bluray PCM signed 16|20|24-bit big-endian for Blu-ray mediaA....D pcm_dvd PCM signed 16|20|24-bit big-endian for DVD mediaA....D pcm_f32be PCM 32-bit floating point big-endianA....D pcm_f32le PCM 32-bit floating point little-endianA....D pcm_f64be PCM 64-bit floating point big-endianA....D pcm_f64le PCM 64-bit floating point little-endianA....D pcm_mulaw PCM mu-law / G.711 mu-lawA..... pcm_mulaw_at pcm_mulaw (AudioToolbox) (codec pcm_mulaw)A....D pcm_s16be PCM signed 16-bit big-endianA....D pcm_s16be_planar PCM signed 16-bit big-endian planarA....D pcm_s16le PCM signed 16-bit little-endianA....D pcm_s16le_planar PCM signed 16-bit little-endian planarA....D pcm_s24be PCM signed 24-bit big-endianA....D pcm_s24daud PCM D-Cinema audio signed 24-bitA....D pcm_s24le PCM signed 24-bit little-endianA....D pcm_s24le_planar PCM signed 24-bit little-endian planarA....D pcm_s32be PCM signed 32-bit big-endianA....D pcm_s32le PCM signed 32-bit little-endianA....D pcm_s32le_planar PCM signed 32-bit little-endian planarA....D pcm_s64be PCM signed 64-bit big-endianA....D pcm_s64le PCM signed 64-bit little-endianA....D pcm_s8 PCM signed 8-bitA....D pcm_s8_planar PCM signed 8-bit planarA....D pcm_u16be PCM unsigned 16-bit big-endianA....D pcm_u16le PCM unsigned 16-bit little-endianA....D pcm_u24be PCM unsigned 24-bit big-endianA....D pcm_u24le PCM unsigned 24-bit little-endianA....D pcm_u32be PCM unsigned 32-bit big-endianA....D pcm_u32le PCM unsigned 32-bit little-endianA....D pcm_u8 PCM unsigned 8-bitA....D pcm_vidc PCM Archimedes VIDCA....D real_144 RealAudio 1.0 (14.4K) (codec ra_144)A....D roq_dpcm id RoQ DPCMA..X.D s302m SMPTE 302MA....D sbc SBC (low-complexity subband codec)A..X.D sonic SonicA..X.D sonicls Sonic losslessA....D libspeex libspeex Speex (codec speex)A..X.D truehd TrueHDA....D tta TTA (True Audio)A..X.D vorbis VorbisA....D libvorbis libvorbis (codec vorbis)A....D wavpack WavPackA....D wmav1 Windows Media Audio 1A....D wmav2 Windows Media Audio 2S..... ssa ASS (Advanced SubStation Alpha) subtitle (codec ass)S..... ass ASS (Advanced SubStation Alpha) subtitleS..... dvbsub DVB subtitles (codec dvb_subtitle)S..... dvdsub DVD subtitles (codec dvd_subtitle)S..... mov_text 3GPP Timed Text subtitleS..... srt SubRip subtitle (codec subrip)S..... subrip SubRip subtitleS..... text Raw text subtitleS..... ttml TTML subtitleS..... webvtt WebVTT subtitleS..... xsub DivX subtitles (XSUB)
视频编码详细流程
- 从流程可以看到,完成编码的核心函数就是 do_video_out();里面实现编码的核心 API 就是 avcodec_send_frame() 和 avcodec_receive_packet() 两个函数;两个函数有点类似状态机,收到帧frame 到输出包 packet,通过判断 buffer 中是否有数据完成编码。
编码核心 API 介绍
avcodec_send_frame()
- API申明介绍
/*** 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, refcounted_frames not set, 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);
- 定义分析
avcodec_send_frame()内部调用encode_send_frame_internal() 来检查 frame buffer 里是否有数据,当 buffer_pkt中没有数据时,调用encode_receive_packet_internal() 是完成编码的核心函数;
在encode_receive_packet_internal()中主要调用encode_simple_receive_packet() 完成视频编码;
在encode_simple_receive_packet()调用encode_simple_internal() 完成视频编码;
在encode_simple_internal()主要利用函数指针 (*encode2)() 对各类第三方的编码器的调用;此外若涉及到多线程编码,则会通过ff_thread_video_encode_frame()来完成。
- (*encode2)()
通过该函数指针指向不同的编码器,完成具体的编码过程;比如 x264、openh264、x265、avs2、videotoolbox 等等;
AVCodec ff_libx264_encoder = {.name = "libx264",.long_name = NULL_IF_CONFIG_SMALL("libx264 H.264 / AVC / MPEG-4 AVC / MPEG-4 part 10"),.type = AVMEDIA_TYPE_VIDEO,.id = AV_CODEC_ID_H264,.priv_data_size = sizeof(X264Context),.init = X264_init,.encode2 = X264_frame,.close = X264_close,.capabilities = AV_CODEC_CAP_DELAY | AV_CODEC_CAP_AUTO_THREADS |AV_CODEC_CAP_ENCODER_REORDERED_OPAQUE,.priv_class = &x264_class,.defaults = x264_defaults,.init_static_data = X264_init_static,
#if X264_BUILD >= 158.caps_internal = FF_CODEC_CAP_INIT_CLEANUP | FF_CODEC_CAP_INIT_THREADSAFE,
#else.caps_internal = FF_CODEC_CAP_INIT_CLEANUP,
#endif.wrapper_name = "libx264",
};
AVCodec ff_libx265_encoder = {.name = "libx265",.long_name = NULL_IF_CONFIG_SMALL("libx265 H.265 / HEVC"),.type = AVMEDIA_TYPE_VIDEO,.id = AV_CODEC_ID_HEVC,.init = libx265_encode_init,.init_static_data = libx265_encode_init_csp,.encode2 = libx265_encode_frame,.close = libx265_encode_close,.priv_data_size = sizeof(libx265Context),.priv_class = &class,.defaults = x265_defaults,.capabilities = AV_CODEC_CAP_DELAY | AV_CODEC_CAP_AUTO_THREADS |AV_CODEC_CAP_ENCODER_REORDERED_OPAQUE,.wrapper_name = "libx265",
};
AVCodec ff_libopenh264_encoder = {.name = "libopenh264",.long_name = NULL_IF_CONFIG_SMALL("OpenH264 H.264 / AVC / MPEG-4 AVC / MPEG-4 part 10"),.type = AVMEDIA_TYPE_VIDEO,.id = AV_CODEC_ID_H264,.priv_data_size = sizeof(SVCContext),.init = svc_encode_init,.encode2 = svc_encode_frame,.close = svc_encode_close,.capabilities = AV_CODEC_CAP_AUTO_THREADS,.caps_internal = FF_CODEC_CAP_INIT_THREADSAFE | FF_CODEC_CAP_INIT_CLEANUP,.pix_fmts = (const enum AVPixelFormat[]){ AV_PIX_FMT_YUV420P,AV_PIX_FMT_NONE },.defaults = svc_enc_defaults,.priv_class = &class,.wrapper_name = "libopenh264",
};
AVCodec ff_h264_videotoolbox_encoder = {.name = "h264_videotoolbox",.long_name = NULL_IF_CONFIG_SMALL("VideoToolbox H.264 Encoder"),.type = AVMEDIA_TYPE_VIDEO,.id = AV_CODEC_ID_H264,.priv_data_size = sizeof(VTEncContext),.pix_fmts = avc_pix_fmts,.init = vtenc_init,.encode2 = vtenc_frame,.close = vtenc_close,.capabilities = AV_CODEC_CAP_DELAY,.priv_class = &h264_videotoolbox_class,.caps_internal = FF_CODEC_CAP_INIT_THREADSAFE |FF_CODEC_CAP_INIT_CLEANUP,
};
AVCodec ff_hevc_videotoolbox_encoder = {.name = "hevc_videotoolbox",.long_name = NULL_IF_CONFIG_SMALL("VideoToolbox H.265 Encoder"),.type = AVMEDIA_TYPE_VIDEO,.id = AV_CODEC_ID_HEVC,.priv_data_size = sizeof(VTEncContext),.pix_fmts = hevc_pix_fmts,.init = vtenc_init,.encode2 = vtenc_frame,.close = vtenc_close,.capabilities = AV_CODEC_CAP_DELAY | AV_CODEC_CAP_HARDWARE,.priv_class = &hevc_videotoolbox_class,.caps_internal = FF_CODEC_CAP_INIT_THREADSAFE |FF_CODEC_CAP_INIT_CLEANUP,.wrapper_name = "videotoolbox",
};
AVCodec ff_libxavs_encoder = {.name = "libxavs",.long_name = NULL_IF_CONFIG_SMALL("libxavs Chinese AVS (Audio Video Standard)"),.type = AVMEDIA_TYPE_VIDEO,.id = AV_CODEC_ID_CAVS,.priv_data_size = sizeof(XavsContext),.init = XAVS_init,.encode2 = XAVS_frame,.close = XAVS_close,.capabilities = AV_CODEC_CAP_DELAY | AV_CODEC_CAP_AUTO_THREADS,.pix_fmts = (const enum AVPixelFormat[]) { AV_PIX_FMT_YUV420P, AV_PIX_FMT_NONE },.priv_class = &xavs_class,.defaults = xavs_defaults,.wrapper_name = "libxavs",
};
AVCodec ff_libxavs2_encoder = {.name = "libxavs2",.long_name = NULL_IF_CONFIG_SMALL("libxavs2 AVS2-P2/IEEE1857.4"),.type = AVMEDIA_TYPE_VIDEO,.id = AV_CODEC_ID_AVS2,.priv_data_size = sizeof(XAVS2EContext),.init = xavs2_init,.encode2 = xavs2_encode_frame,.close = xavs2_close,.capabilities = AV_CODEC_CAP_DELAY | AV_CODEC_CAP_AUTO_THREADS,.pix_fmts = (const enum AVPixelFormat[]) { AV_PIX_FMT_YUV420P,AV_PIX_FMT_NONE },.priv_class = &libxavs2,.defaults = xavs2_defaults,.wrapper_name = "libxavs2",
} ;
AVCodec ff_libvpx_vp8_encoder = {.name = "libvpx",.long_name = NULL_IF_CONFIG_SMALL("libvpx VP8"),.type = AVMEDIA_TYPE_VIDEO,.id = AV_CODEC_ID_VP8,.priv_data_size = sizeof(VPxContext),.init = vp8_init,.encode2 = vpx_encode,.close = vpx_free,.capabilities = AV_CODEC_CAP_DELAY | AV_CODEC_CAP_AUTO_THREADS,.pix_fmts = (const enum AVPixelFormat[]){ AV_PIX_FMT_YUV420P, AV_PIX_FMT_YUVA420P, AV_PIX_FMT_NONE },.priv_class = &class_vp8,.defaults = defaults,.wrapper_name = "libvpx",
};
AVCodec ff_libvpx_vp9_encoder = {.name = "libvpx-vp9",.long_name = NULL_IF_CONFIG_SMALL("libvpx VP9"),.type = AVMEDIA_TYPE_VIDEO,.id = AV_CODEC_ID_VP9,.priv_data_size = sizeof(VPxContext),.init = vp9_init,.encode2 = vpx_encode,.close = vpx_free,.capabilities = AV_CODEC_CAP_DELAY | AV_CODEC_CAP_AUTO_THREADS,.profiles = NULL_IF_CONFIG_SMALL(ff_vp9_profiles),.priv_class = &class_vp9,.defaults = defaults,.init_static_data = ff_vp9_init_static,.wrapper_name = "libvpx",
};
AVCodec ff_libxvid_encoder = {.name = "libxvid",.long_name = NULL_IF_CONFIG_SMALL("libxvidcore MPEG-4 part 2"),.type = AVMEDIA_TYPE_VIDEO,.id = AV_CODEC_ID_MPEG4,.priv_data_size = sizeof(struct xvid_context),.init = xvid_encode_init,.encode2 = xvid_encode_frame,.close = xvid_encode_close,.pix_fmts = (const enum AVPixelFormat[]) { AV_PIX_FMT_YUV420P, AV_PIX_FMT_NONE },.priv_class = &xvid_class,.caps_internal = FF_CODEC_CAP_INIT_THREADSAFE |FF_CODEC_CAP_INIT_CLEANUP,.wrapper_name = "libxvid",
};
avcodec_receive_packet()
- API 申明介绍
/*** 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);
- 定义分析
从 avcode_receive_packet()函数内部实现逻辑可以看到,首先判断buffer_pkt是否有数据,如果有,则调用 av_packet_move_ref() 函数完成数据包 packet 的拷贝过程;如果buffer_pak里没有数据,则需要调用 encode_receive_packet_internal() 来完成编码,此过程跟 send frame 模块中相同。
官方编码实例
/** Copyright (c) 2001 Fabrice Bellard** Permission is hereby granted, free of charge, to any person obtaining a copy* of this software and associated documentation files (the "Software"), to deal* in the Software without restriction, including without limitation the rights* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell* copies of the Software, and to permit persons to whom the Software is* furnished to do so, subject to the following conditions:** The above copyright notice and this permission notice shall be included in* all copies or substantial portions of the Software.** THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN* THE SOFTWARE.*//*** @file* video encoding with libavcodec API example** @example encode_video.c*/#include <stdio.h>
#include <stdlib.h>
#include <string.h>#include <libavcodec/avcodec.h>#include <libavutil/opt.h>
#include <libavutil/imgutils.h>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 %3"PRId64"\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 %3"PRId64" (size=%5d)\n", pkt->pts, pkt->size);fwrite(pkt->data, 1, pkt->size, outfile);av_packet_unref(pkt);}
}int main(int argc, char **argv)
{const char *filename, *codec_name;const AVCodec *codec;AVCodecContext *c= NULL;int i, ret, x, y;FILE *f;AVFrame *frame;AVPacket *pkt;uint8_t endcode[] = { 0, 0, 1, 0xb7 };if (argc <= 2) {fprintf(stderr, "Usage: %s <output file> <codec name>\n", argv[0]);exit(0);}filename = argv[1];codec_name = argv[2];/* find the mpeg1video encoder */codec = avcodec_find_encoder_by_name(codec_name);if (!codec) {fprintf(stderr, "Codec '%s' not found\n", codec_name);exit(1);}c = avcodec_alloc_context3(codec);if (!c) {fprintf(stderr, "Could not allocate video codec context\n");exit(1);}pkt = av_packet_alloc();if (!pkt)exit(1);/* put sample parameters */c->bit_rate = 400000;/* resolution must be a multiple of two */c->width = 352;c->height = 288;/* frames per second */c->time_base = (AVRational){1, 25};c->framerate = (AVRational){25, 1};/* emit one intra frame every ten frames* check frame pict_type before passing frame* to encoder, if frame->pict_type is AV_PICTURE_TYPE_I* then gop_size is ignored and the output of encoder* will always be I frame irrespective to gop_size*/c->gop_size = 10;c->max_b_frames = 1;c->pix_fmt = AV_PIX_FMT_YUV420P;if (codec->id == AV_CODEC_ID_H264)av_opt_set(c->priv_data, "preset", "slow", 0);/* open it */ret = avcodec_open2(c, codec, NULL);if (ret < 0) {fprintf(stderr, "Could not open codec: %s\n", av_err2str(ret));exit(1);}f = fopen(filename, "wb");if (!f) {fprintf(stderr, "Could not open %s\n", filename);exit(1);}frame = av_frame_alloc();if (!frame) {fprintf(stderr, "Could not allocate video frame\n");exit(1);}frame->format = c->pix_fmt;frame->width = c->width;frame->height = c->height;ret = av_frame_get_buffer(frame, 0);if (ret < 0) {fprintf(stderr, "Could not allocate the video frame data\n");exit(1);}/* encode 1 second of video */for (i = 0; i < 25; i++) {fflush(stdout);/* make sure the frame data is writable */ret = av_frame_make_writable(frame);if (ret < 0)exit(1);/* prepare a dummy image *//* Y */for (y = 0; y < c->height; y++) {for (x = 0; x < c->width; x++) {frame->data[0][y * frame->linesize[0] + x] = x + y + i * 3;}}/* Cb and Cr */for (y = 0; y < c->height/2; y++) {for (x = 0; x < c->width/2; x++) {frame->data[1][y * frame->linesize[1] + x] = 128 + y + i * 2;frame->data[2][y * frame->linesize[2] + x] = 64 + x + i * 5;}}frame->pts = i;/* encode the image */encode(c, frame, pkt, f);}/* flush the encoder */encode(c, NULL, pkt, f);/* add sequence end code to have a real MPEG file */if (codec->id == AV_CODEC_ID_MPEG1VIDEO || codec->id == AV_CODEC_ID_MPEG2VIDEO)fwrite(endcode, 1, sizeof(endcode), f);fclose(f);avcodec_free_context(&c);av_frame_free(&frame);av_packet_free(&pkt);return 0;
}
参考
- http://ffmpeg.org/
相关文章:

FFmpeg 编码详细流程
介绍 FFmpeg的 libavcodec 模块完成音视频多媒体的编解码模块。FFmpeg 本身不具有音视频编码的功能和底层能力,只是对各类第三方的编码器API 进行封装调用。老版本的 FFmpeg 将avcodec_encode_video2()作为视频的解码函数 API,将avcodec_encode_audio2(…...
05如何做微服务架构设计
一句话导读 微服务架构设计方法有:领域驱动设计DDD(Domain-Driven-Design)、12因素应用(12-Factor App)、事件驱动架构EDA(Event-Driven Architecture)等等,但是他们都必须遵守微服务…...

安卓开发问题记录:需要常量表达式
问题原因 写代码过程中爆出这个错误:需要常量表达式,定位到switch。 解决方法:把switch case,改成if else 错误源代码: public void onClick(View view) {switch (view.getId()) {case R.id.iv_code:RxCaptcha.build(…...

回归预测 | MATLAB实现基于SVM-RFE-BP支持向量机递归特征消除特征选择算法结合BP神经网络的多输入单输出回归预测
回归预测 | MATLAB实现基于SVM-RFE-BP支持向量机递归特征消除特征选择算法结合BP神经网络的多输入单输出回归预测 目录 回归预测 | MATLAB实现基于SVM-RFE-BP支持向量机递归特征消除特征选择算法结合BP神经网络的多输入单输出回归预测预测效果基本介绍研究内容程序设计参考资料…...

配置root账户ssh免密登录并使用docker-machine构建docker服务
简介 Docker Machine是一种可以在多种平台上快速安装和维护docker运行环境,并支持多种平台,让用户可以在很短时间内在本地或云环境中搭建一套docker主机集群的工具。 使用docker-machine命令,可以启动、审查、停止、重启托管的docker 也可以…...
【力扣周赛】第357场周赛
【力扣周赛】第357场周赛 2810. 故障键盘题目描述解题思路 2811. 判断是否能拆分数组题目描述解题思路 2810. 故障键盘 题目描述 描述:你的笔记本键盘存在故障,每当你在上面输入字符 ‘i’ 时,它会反转你所写的字符串。而输入其他字符则可以…...

多线程案例(4)-线程池
文章目录 多线程案例四四、线程池 大家好,我是晓星航。今天为大家带来的是 多线程案例-线程池 相关的讲解!😀 多线程案例四 四、线程池 线程池是什么 虽然创建线程 / 销毁线程 的开销 想象这么一个场景: 在学校附近新开了一家…...

【数据结构OJ题】轮转数组
原题链接:https://leetcode.cn/problems/rotate-array/ 目录 1. 题目描述 2. 思路分析 3. 代码实现 1. 题目描述 2. 思路分析 1. 方法一:暴力求解,将数组的第一个元素用临时变量tmp存起来,再将数组其他元素往右挪动一步&…...

现代C++中的从头开始深度学习:【4/8】梯度下降
一、说明 在本系列中,我们将学习如何仅使用普通和现代C编写必须知道的深度学习算法,例如卷积、反向传播、激活函数、优化器、深度神经网络等。 在这个故事中,我们将通过引入梯度下降算法来介绍数据中 2D 卷积核的拟合。我们将使用卷积和上一个…...

Yolov5缺陷检测/目标检测 Jetson nx部署Triton server
使用AI目标检测进行缺陷检测时,部署到Jetson上即小巧算力还高,将训练好的模型转为tensorRT再部署到Jetson 上供http或GRPC调用。1 Jetson nx 刷机 找个ubuntu 系统NVIDIA官网下载安装Jetson 的sdkmanager一步步刷机即可。 本文刷的是JetPack 5.1, 其中包…...

MobaXterm 中文乱码, 及pojie
中文解决方法: 把“连字”去掉! MobaXterm网页,可以生成一个授权文件Custom.mxtpro。放在安装目录就可以了 MobaXterm Keygen (husbin.top)http://b70.husbin.top:5000/...

java: 程序包sun.misc不存在
启动失败,rebuild时也报错:java: 程序包sun.misc不存在 问题出在JDK版本上,这个包在JDK9的时候已经被弃用了,这里改回JDK8即可 步骤如下:...
WSL2Linux 子系统(五)
WLS2Linux 子系统编译 Android 上一篇文章中讲解 《WLS2Linux 子系统迁移/恢复》,从C盘迁移到D盘。既可以防止C盘爆红,又可以释放磁盘空间。有更大存储空间意味大有可为,比如说编译Android系统。本文则以开源 firefly Android10代码为例简单…...

java 企业工程管理系统软件源码 自主研发 工程行业适用 em
工程项目管理软件(工程项目管理系统)对建设工程项目管理组织建设、项目策划决策、规划设计、施工建设到竣工交付、总结评估、运维运营,全过程、全方位的对项目进行综合管理 工程项目各模块及其功能点清单 一、系统管理 1、数据字典&#…...
IPO观察丨困于门店扩张的KK集团,还能讲好增长故事吗?
KK集团发起了其IPO之路上的第三次冲击。 近日,KK集团更新了招股书,继续推进港交所上市进程,此前两次上市搁置后终于有了新动向。从更新内容来看,KK集团招股书披露了公司截至2023年一季度的最新业绩,交出一份不错的“成…...

【iOS】RunLoop
前言-什么是RunLoop? 什么是RunLoop? 跑圈?字面上理解确实是这样的。 Apple官方文档这样解释RunLoop RunLoop是与线程息息相关的基本结构的一部分。RunLoop是一个调度任务和处理任务的事件循环。RunLoop的目的是为了在有工作的时候让线程忙起来&#…...

数据包传输方式:单播、多播、广播、组播、泛播
数据包传输方式 单播、多播、广播、组播、泛播 网络中假设X代表所有的机器,Y代表X中的一部分机器,Z代表一组机器,1代表一台机器,那么 1:1 那就是单播;1:Y 那就是多播;1࿱…...

WebRTC基础知识
文章目录 基础概念NAT (Network Address Translation) 打洞STUN(Session Traversal Utilities for NAT)基于STUN协议的DDoS反射攻击 # TODO TURN(Traversal Using Relays around NAT)ICE(Interactive Connectivity Est…...

积累常见的有针对性的python面试题---python面试题001
1.考点列表的.remove方法的参数是传入的对应的元素的值,而不是下标 然后再看remove这里,注意这个是,删除写的那个值,比如这里写3,就是删除3, 而不是下标. remove不是下标删除,而是内容删除. 2.元组操作,元组不支持修改,某个下标的内容 可以问他如何修改元组的某个元素 3.…...
在springboot使用websocket时mapper无法注入
直接上代码 package cn.ujoined.combined.utils;import org.springframework.beans.BeansException; import org.springframework.context.ApplicationContext; import org.springframework.context.ApplicationContextAware; import org.springframework.stereotype.Componen…...

第2篇:BLE 广播与扫描机制详解
本文是《BLE 协议从入门到专家》专栏第二篇,专注于解析 BLE 广播(Advertising)与扫描(Scanning)机制。我们将从协议层结构、广播包格式、设备发现流程、控制器行为、开发者 API、广播冲突与多设备调度等方面,全面拆解这一 BLE 最基础也是最关键的通信机制。 一、什么是 B…...

MQTT协议:物联网时代的通信基石
MQTT协议:物联网时代的通信基石 在当今快速发展的物联网(IoT)时代,设备之间的通信变得尤为重要。MQTT(Message Queuing Telemetry Transport)协议作为一种轻量级的消息传输协议,正逐渐成为物联…...

基于FPGA的超声波显示水位距离,通过蓝牙传输水位数据到手机,同时支持RAM存储水位数据,读取数据。
基于FPGA的超声波显示水位距离 前言一、整体框架二、代码架构1.超声波测距模块2.蓝牙数据发送模块3.数码管数据切换模块4.数码管驱动模块6.串口驱动7.顶层模块8.RAM ip核 仿真相关截图 前言 随着工业化进程的加速和环境保护意识的提升,对水资源管理和水位监测的需求…...
Android 线性布局中常见的冲突属性总结
1. gravity vs layout_gravity 冲突原因:两者作用对象不同,混用会导致行为异常。 区别: android:gravity:父容器的属性,控制子元素在容器内的对齐方式。android:layout_gravity:子元素的属性,控…...
「数据分析 - NumPy 函数与方法全集」【数据分析全栈攻略:爬虫+处理+可视化+报告】
- 第 104 篇 - Date: 2025 - 06 - 05 Author: 郑龙浩/仟墨 NumPy 函数与方法全集 文章目录 NumPy 函数与方法全集1. 数组创建与初始化基础创建序列生成特殊数组 2. 数组操作形状操作合并与分割 3. 数学运算基础运算统计运算 4. 随机数生成基础随机分布函数 5. 文件IO文件读写 …...
C++11 Token Bucket (令牌桶)算法的锁无实现及应用
Token Bucket(令牌桶)算法是一种在流量控制和资源分配领域被广泛应用的技术。它通过约束数据传输速率或任务执行频率,确保系统在资源有限的情况下,能够稳定、高效地运行,避免因突发流量或任务积压而导致的性能下降甚至…...

LLMs 系列科普文(8)
八、模型的自我认知 接下来我们聊聊另一种问题,即模型的自我认知。 网上经常经常可以看到人们会问大语言模型一些关于认知方面的问题,比如“你是什么模型?谁创造了你?” 说实话,其实这个问题有点无厘头。 之所以这么…...

2024 CKA题库+详尽解析| 15、备份还原Etcd
目录 免费获取题库配套 CKA_v1.31_模拟系统 15、 备份还原Etcd 题目: 开始操作: 1)、切换集群 2)、登录master并提权 3)、备份Etcd现有数据 4)、验证备份数据快照 5)、查看节点和Pod状态 6&am…...
Oracle数据库学习笔记 - 创建、备份和恢复
Oracle数据库学习笔记 创建,备份和恢复 Oracle 版本基于11g 尽量不使用图形界面方式,操作适用于linux和windows 创建数据库 创建实例 # 步骤1:设置环境变量 export ORACLE_SIDmyorcl export ORACLE_HOME/u01/app/oracle/product/19.0.0/dbh…...

怎么解决cesium加载模型太黑,程序崩溃,不显示,位置不对模型太大,Cesium加载gltf/glb模型后变暗
有时候咱们cesium加载模型时候型太黑,程序崩溃,不显示,位置不对模型太大怎么办 需要处理 可以联系Q:424081801 谢谢 需要处理 可以联系Q:424081801 谢谢...