介绍
- 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.h
Add a new audio/video encoding and decoding API with decoupled input
and output -- avcodec_send_packet(), avcodec_receive_frame(),
avcodec_send_frame() and avcodec_receive_packet().
- 可以通过命令行ffmpeg configure -encoders查看支持哪些编码器格式;但是好像configure 里说明的和源码不完全一致,源码里有支持 kvazaar 编码器(一种符合h265编码标准的开源编码器),但 configure 并没有体现出来。
Encoders:
V..... = Video
A..... = Audio
S..... = 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 image
V..... amv AMV Video
V....D apng APNG (Animated Portable Network Graphics) image
V....D asv1 ASUS V1
V....D asv2 ASUS V2
V....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 Packer
V..X.D avui Avid Meridien Uncompressed
V....D ayuv Uncompressed packed MS 4:4:4:4
VF...D bitpacked Bitpacked
V....D bmp BMP (Windows and OS/2 bitmap)
VF...D cfhd GoPro CineForm HD
V....D cinepak Cinepak
V....D cljr Cirrus Logic AccuPak
V.S..D vc2 SMPTE VC-2 (codec dirac)
VFS..D dnxhd VC3/DNxHD
V....D dpx DPX (Digital Picture Exchange) image
VFS..D dvvideo DV (Digital Video)
VF...D exr OpenEXR image
V.S..D ffv1 FFmpeg video codec
VF...D ffvhuff Huffyuv FFmpeg variant
V....D fits Flexible Image Transport System
V....D flashsv Flash Screen Video
V....D flashsv2 Flash Screen Video Version 2
V..... flv FLV / Sorenson Spark / Sorenson H.263 (Flash Video) (codec flv1)
V....D gif GIF (Graphics Interchange Format)
V..... h261 H.261
V..... h263 H.263 / H.263-1996
V.S... h263p H.263+ / H.263-1998 / H.263 version 2
V....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 Hap
VF...D hdr HDR (Radiance RGBE format) image
V....D libx265 libx265 H.265 / HEVC (codec hevc)
V....D hevc_videotoolbox VideoToolbox H.265 Encoder (codec hevc)
VF...D huffyuv Huffyuv / HuffYUV
V....D jpeg2000 JPEG 2000
VF.... libopenjpeg OpenJPEG JPEG 2000 (codec jpeg2000)
VF...D jpegls JPEG-LS
VF...D ljpeg Lossless JPEG
VF...D magicyuv MagicYUV video
VFS... mjpeg MJPEG (Motion JPEG)
V.S... mpeg1video MPEG-1 video
V.S... mpeg2video MPEG-2 video
V.S... mpeg4 MPEG-4 part 2
V....D libxvid libxvidcore MPEG-4 part 2 (codec mpeg4)
V..... msmpeg4v2 MPEG-4 part 2 Microsoft variant version 2
V..... msmpeg4 MPEG-4 part 2 Microsoft variant version 3 (codec msmpeg4v3)
V..... msvideo1 Microsoft Video-1
V....D pam PAM (Portable AnyMap) image
V....D pbm PBM (Portable BitMap) image
V....D pcx PC Paintbrush PCX image
V....D pfm PFM (Portable FloatMap) image
V....D pgm PGM (Portable GrayMap) image
V....D pgmyuv PGMYUV (Portable GrayMap YUV) image
V....D phm PHM (Portable HalfFloatMap) image
VF...D png PNG (Portable Network Graphics) image
V....D ppm PPM (Portable PixelMap) image
VF...D prores Apple ProRes
VF...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) image
V....D qtrle QuickTime Animation (RLE) video
V....D r10k AJA Kona 10-bit RGB Codec
V....D r210 Uncompressed RGB 10-bit
VF...D rawvideo raw video
V....D roqvideo id RoQ video (codec roq)
V....D rpza QuickTime video (RPZA)
V..... rv10 RealVideo 1.0
V..... rv20 RealVideo 2.0
V....D sgi SGI image
V....D smc QuickTime Graphics (SMC)
V....D snow Snow
V..... speedhq NewTek SpeedHQ
V....D sunrast Sun Rasterfile image
V....D svq1 Sorenson Vector Quantizer 1 / Sorenson Video 1 / SVQ1
V....D targa Truevision Targa image
V....D libtheora libtheora Theora (codec theora)
VF...D tiff TIFF image
VF...D utvideo Ut Video
VF...D v210 Uncompressed 4:2:2 10-bit
V....D v308 Uncompressed packed 4:4:4
V....D v408 Uncompressed packed QT 4:4:4:4
V....D v410 Uncompressed 4:4:4 10-bit
V.S..D vbn Vizrt Binary Image
V..... vnull null video
V....D libvpx libvpx VP8 (codec vp8)
V....D libvpx-vp9 libvpx VP9 (codec vp9)
VF...D wbmp WBMP (Wireless Application Protocol Bitmap) image
V....D libwebp_anim libwebp WebP image (codec webp)
V....D libwebp libwebp WebP image (codec webp)
V..... wmv1 Windows Media Video 7
V..... wmv2 Windows Media Video 8
V..... wrapped_avframe AVFrame to AVPacket passthrough
V....D xbm XBM (X BitMap) image
V....D xface X-face image
V....D xwd XWD (X Window Dump) image
V....D y41p Uncompressed YUV 4:1:1 12-bit
V....D yuv4 Uncompressed packed 4:2:0
VF...D zlib LCL (LossLess Codec Library) ZLIB
V....D zmbv Zip Motion Blocks Video
A....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 ADPCM
A....D adpcm_argo ADPCM Argonaut Games
A....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 ALP
A....D adpcm_ima_amv ADPCM IMA AMV
A....D adpcm_ima_apm ADPCM IMA Ubisoft APM
A....D adpcm_ima_qt ADPCM IMA QuickTime
A....D adpcm_ima_ssi ADPCM IMA Simon & Schuster Interactive
A....D adpcm_ima_wav ADPCM IMA WAV
A....D adpcm_ima_ws ADPCM IMA Westwood
A....D adpcm_ms ADPCM Microsoft
A....D adpcm_swf ADPCM Shockwave Flash
A....D adpcm_yamaha ADPCM Yamaha
A....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 audio
A....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 generator
A....D dfpwm DFPWM1a audio
A..X.D dca DCA (DTS Coherent Acoustics) (codec dts)
A....D eac3 ATSC A/52 E-AC-3
A....D flac FLAC (Free Lossless Audio Codec)
A....D g723_1 G.723.1
A..... 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 Asao
A..X.D opus Opus
A....D libopus libopus Opus (codec opus)
A....D pcm_alaw PCM A-law / G.711 A-law
A..... pcm_alaw_at pcm_alaw (AudioToolbox) (codec pcm_alaw)
A....D pcm_bluray PCM signed 16|20|24-bit big-endian for Blu-ray media
A....D pcm_dvd PCM signed 16|20|24-bit big-endian for DVD media
A....D pcm_f32be PCM 32-bit floating point big-endian
A....D pcm_f32le PCM 32-bit floating point little-endian
A....D pcm_f64be PCM 64-bit floating point big-endian
A....D pcm_f64le PCM 64-bit floating point little-endian
A....D pcm_mulaw PCM mu-law / G.711 mu-law
A..... pcm_mulaw_at pcm_mulaw (AudioToolbox) (codec pcm_mulaw)
A....D pcm_s16be PCM signed 16-bit big-endian
A....D pcm_s16be_planar PCM signed 16-bit big-endian planar
A....D pcm_s16le PCM signed 16-bit little-endian
A....D pcm_s16le_planar PCM signed 16-bit little-endian planar
A....D pcm_s24be PCM signed 24-bit big-endian
A....D pcm_s24daud PCM D-Cinema audio signed 24-bit
A....D pcm_s24le PCM signed 24-bit little-endian
A....D pcm_s24le_planar PCM signed 24-bit little-endian planar
A....D pcm_s32be PCM signed 32-bit big-endian
A....D pcm_s32le PCM signed 32-bit little-endian
A....D pcm_s32le_planar PCM signed 32-bit little-endian planar
A....D pcm_s64be PCM signed 64-bit big-endian
A....D pcm_s64le PCM signed 64-bit little-endian
A....D pcm_s8 PCM signed 8-bit
A....D pcm_s8_planar PCM signed 8-bit planar
A....D pcm_u16be PCM unsigned 16-bit big-endian
A....D pcm_u16le PCM unsigned 16-bit little-endian
A....D pcm_u24be PCM unsigned 24-bit big-endian
A....D pcm_u24le PCM unsigned 24-bit little-endian
A....D pcm_u32be PCM unsigned 32-bit big-endian
A....D pcm_u32le PCM unsigned 32-bit little-endian
A....D pcm_u8 PCM unsigned 8-bit
A....D pcm_vidc PCM Archimedes VIDC
A....D real_144 RealAudio 1.0 (14.4K) (codec ra_144)
A....D roq_dpcm id RoQ DPCM
A..X.D s302m SMPTE 302M
A....D sbc SBC (low-complexity subband codec)
A..X.D sonic Sonic
A..X.D sonicls Sonic lossless
A....D libspeex libspeex Speex (codec speex)
A..X.D truehd TrueHD
A....D tta TTA (True Audio)
A..X.D vorbis Vorbis
A....D libvorbis libvorbis (codec vorbis)
A....D wavpack WavPack
A....D wmav1 Windows Media Audio 1
A....D wmav2 Windows Media Audio 2
S..... ssa ASS (Advanced SubStation Alpha) subtitle (codec ass)
S..... ass ASS (Advanced SubStation Alpha) subtitle
S..... dvbsub DVB subtitles (codec dvb_subtitle)
S..... dvdsub DVD subtitles (codec dvd_subtitle)
S..... mov_text 3GPP Timed Text subtitle
S..... srt SubRip subtitle (codec subrip)
S..... subrip SubRip subtitle
S..... text Raw text subtitle
S..... ttml TTML subtitle
S..... webvtt WebVTT subtitle
S..... xsub DivX subtitles (XSUB)
视频编码详细流程
- 从流程可以看到,完成编码的核心函数就是 do_video_out();里面实现编码的核心 API 就是 avcodec_send_frame() 和 avcodec_receive_packet() 两个函数;两个函数有点类似状态机,收到帧frame 到输出包 packet,通过判断 buffer 中是否有数据完成编码。
编码核心 API 介绍
avcodec_send_frame()
- API申明介绍
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 申明介绍
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 模块中相同。
官方编码实例
#include
#include
#include
#include
#include
#include
static void encode(AVCodecContext *enc_ctx, AVFrame *frame, AVPacket *pkt,
FILE *outfile)
{
int ret;
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 , argv[0]);
exit(0);
}
filename = argv[1];
codec_name = argv[2];
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);
c->bit_rate = 400000;
c->width = 352;
c->height = 288;
c->time_base = (AVRational){1, 25};
c->framerate = (AVRational){25, 1};
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);
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);
}
for (i = 0; i < 25; i++) {
fflush(stdout);
ret = av_frame_make_writable(frame);
if (ret < 0)
exit(1);
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;
}
}
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(c, frame, pkt, f);
}
encode(c, NULL, pkt, f);
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/