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…...
前端加密与解密的几种方式
1.base64加密方式 1. base64是什么? Base64,顾名思义,就是包括小写字母a-z、大写字母A-Z、数字0-9、符号""、"/"一共64个字符的字符集,(另加一个“”,实际是65个字符,至于…...
详解Spring Bean的生命周期
详解Spring Bean的生命周期 Spring Bean的生命周期包括以下阶段: 1. 实例化Bean 对于BeanFactory容器,当客户向容器请求一个尚未初始化的bean时,或初始化bean的时候需要注入另一个尚未初始化的依赖时,容器就会调用createBean进…...
详解Shell 脚本中 “$” 符号的多种用法
通常情况下,在工作中用的最多的有如下几项: $0:Shell 的命令本身 1到9:表示 Shell 的第几个参数 $? :显示最后命令的执行情况 $#:传递到脚本的参数个数 $$:脚本运行的当前进程 ID 号 $*&#…...
Redis如何实现Session存储
在Redis中实现Session存储,主要有两种方式:使用Spring Session和手动存储。 使用Spring Session:Spring Session是Spring框架提供的一个模块,用于简化Session管理,并将Session数据存储到外部数据存储中,如Redis。使用Spring Session,你只需要在Spring Boot项目中添加相应…...
安防视频监控汇聚EasyCVR平台接入Ehome告警,公网快照不显示的原因排查
智能视频监控汇聚平台TSINGSEE青犀视频EasyCVR可拓展性强、视频能力灵活、部署轻快,可支持的主流标准协议有国标GB28181、RTSP/Onvif、RTMP等,以及支持厂家私有协议与SDK接入,包括海康Ehome、海大宇等设备的SDK等,视频监控管理平台…...
【Springboot】@ComponentScan 详解
文章目录 ComponentScanComponentScan ANNOTATION 和 REGEXComponentScan CUSTOMComponentScan ASSIGNABLE_TYPE ComponentScan ComponentScan 是 Spring 框架中的一个注解,用于自动扫描和注册容器中的组件。 使用 ComponentScan 注解可以告诉 Spring 在指定的包或…...
flask-----信号
安装: flask中的信号使用的是一个第三方插件,叫做blinker。通过pip list看一下,如果没有安装,通过以下命令即可安装blinker: pip install blinker flask其中有内置的信号 template_rendered _signals.signal(temp…...
10_Vue3 其它的组合式API(Composition API)
Vue3 中的其它组合式API 1.shallowReactive 与 shallowRef 2. readonly 与 shallowReadonly 3.toRaw 与 markRaw 4.customRef 5.provide 与 inject 6.响应式数据的判断...
COCOS项目运行的时候图片模糊的原因
1、首先。用X坐标来分析,如果size*Anchor Position有小数,如上图57*0.5667695.5。这样就会导致x模糊。如果y同样计算结果包含小数,那么y也会模糊。xy同时模糊的情况是最模糊的。 2、如果当前node没有问题,那么就要检查上级node是…...
Python中搭建IP代理池的妙招
在Python的爬虫世界里,你是否也想搭建一个功能强大的IP代理池,让你的爬虫无忧无虑地畅游各大网站?今天,我就来教你使用Scrapy框架搭建IP代理池,让你的爬虫更加智能、高效!跟着我一步一步来,轻松…...
中国建设银行招标网站/企业营销策划合同
前几天在读者群里,大家针对看书好、还是看视频好、还是自学好,展开了激烈的讨论,场面一度失控。作为群主的我,为了缓和气氛,选择了和稀泥,我说都好,并且拿我自己举了例子。说着说着我发现&#…...
wordpress 教学培训/网络黄页平台网址有哪些
匹夫怀璧,真的有罪么? 怀璧没有罪,有罪的是他没有能力,没有社会承认他拥有和氏璧的能力 那如何承认呢? 假如秦始王拿到那块和氏璧,没人会质疑,普通人拿到,无论是什么手段拿到&#x…...
1000学习做网站贵吗/观看b站的广告网站平台
2019独角兽企业重金招聘Python工程师标准>>> binSort.cpp /** 这里是主函数的执行文件 * binSort.cpp */ #include<iostream> #include"studentrecord1.h" #include"chainwithiterator.h" #include"myexceptions.h"void…...
网页设计培训计划/百度搜索优化平台
作者:LeonLok编译:ronghuaiyang导读本文来自github,很实用的一个应用。git仓库地址:https://github.com/LeonLok/Multi-Camera-Live-Object-Tracking这个存储库包含了我的目标检测和跟踪项目。所有这些都可以托管在云服务器上。由…...
做视频后期的网站/seo全称是什么意思
为什么80%的码农都做不了架构师?>>> 转自http://blog.csdn.net/dadalan/article/details/3758025 用GDB调试程序 GDB是一个强大的命令行调试工具。大家知道命令行的强大就是在于,其可以形成执行序列,形成脚本。UNIX下的软件全是命…...
网站压缩/国际新闻最新消息中国
前言:用过python递归的同学可能都碰到过:RecursionError: maximum recursion depth exceeded while getting the str of an object,显而易见超过递归深度了,那么python的递归深度到底是多少呢?有没有一个标准呢&#x…...