Update for newer FFmpeg API. Index: lib/codec_ffmpeg.c --- lib/codec_ffmpeg.c.orig +++ lib/codec_ffmpeg.c @@ -23,11 +23,7 @@ #include "codec_ffmpeg.h" #include "iaxclient_lib.h" -#ifdef WIN32 #include "libavcodec/avcodec.h" -#else -#include -#endif struct slice_header_t { @@ -63,30 +59,30 @@ struct decoder_ctx static struct slice_set_t * g_slice_set = 0; -static enum CodecID map_iaxc_codec_to_avcodec(int format) +static enum AVCodecID map_iaxc_codec_to_avcodec(int format) { switch (format) { case IAXC_FORMAT_H261: - return CODEC_ID_H261; + return AV_CODEC_ID_H261; case IAXC_FORMAT_H263: - return CODEC_ID_H263; + return AV_CODEC_ID_H263; case IAXC_FORMAT_H263_PLUS: - return CODEC_ID_H263P; + return AV_CODEC_ID_H263P; case IAXC_FORMAT_MPEG4: - return CODEC_ID_MPEG4; + return AV_CODEC_ID_MPEG4; case IAXC_FORMAT_H264: - return CODEC_ID_H264; + return AV_CODEC_ID_H264; case IAXC_FORMAT_THEORA: - return CODEC_ID_THEORA; + return AV_CODEC_ID_THEORA; default: - return CODEC_ID_NONE; + return AV_CODEC_ID_NONE; } } @@ -165,10 +161,14 @@ static int pass_frame_to_decoder(AVCodecContext * avct { int bytes_decoded; int got_picture; + AVPacket pkt; - bytes_decoded = avcodec_decode_video(avctx, picture, &got_picture, - in, inlen); + pkt.data = in; + pkt.size = inlen; + bytes_decoded = avcodec_decode_video2(avctx, picture, &got_picture, + &pkt); + if ( bytes_decoded != inlen ) { fprintf(stderr, @@ -309,10 +309,14 @@ static int decode_rtp_slice(struct iaxc_video_codec * { int bytes_decoded; int got_picture; + AVPacket pkt; - bytes_decoded = avcodec_decode_video(d->avctx, d->picture, - &got_picture, (unsigned char *)in, inlen); + pkt.data = (unsigned char *)in; + pkt.size = inlen; + bytes_decoded = avcodec_decode_video2(d->avctx, d->picture, + &got_picture, &pkt); + if ( bytes_decoded < 0 ) { fprintf(stderr, @@ -372,9 +376,10 @@ static int encode(struct iaxc_video_codec *c, int inlen, char * in, struct slice_set_t * slice_set) { struct encoder_ctx *e = (struct encoder_ctx *) c->encstate; - int encoded_size; + int encoded_size, ret, got_packet = 0; + AVPacket pkt; - avcodec_get_frame_defaults(e->picture); + av_frame_unref(e->picture); e->picture->data[0] = (unsigned char *)in; e->picture->data[1] = (unsigned char *)in @@ -395,15 +400,25 @@ static int encode(struct iaxc_video_codec *c, g_slice_set = slice_set; slice_set->num_slices = 0; - encoded_size = avcodec_encode_video(e->avctx, - e->frame_buf, e->frame_buf_len, e->picture); + av_init_packet(&pkt); + pkt.data = e->frame_buf; + pkt.size = e->frame_buf_len; - if (!encoded_size) + ret = avcodec_encode_video2(e->avctx, &pkt, e->picture, &got_packet); + if ( ret < 0 ) { fprintf(stderr, "codec_ffmpeg: encode failed\n"); return -1; } + encoded_size = pkt.size; + + if (encoded_size < 0) + { + fprintf(stderr, "codec_ffmpeg: encode failed\n"); + return -1; + } + slice_set->key_frame = e->avctx->coded_frame->key_frame; /* This is paranoia, of course. */ @@ -441,6 +456,7 @@ struct iaxc_video_codec *codec_video_ffmpeg_new(int fo { struct encoder_ctx *e; struct decoder_ctx *d; + AVDictionary *opts = NULL; AVCodec *codec; int ff_enc_id, ff_dec_id; char *name; @@ -454,7 +470,6 @@ struct iaxc_video_codec *codec_video_ffmpeg_new(int fo return NULL; } - avcodec_init(); avcodec_register_all(); c->format = format; @@ -475,10 +490,10 @@ struct iaxc_video_codec *codec_video_ffmpeg_new(int fo if (!c->encstate) goto bail; e = c->encstate; - e->avctx = avcodec_alloc_context(); + e->avctx = avcodec_alloc_context3(NULL); if (!e->avctx) goto bail; - e->picture = avcodec_alloc_frame(); + e->picture = av_frame_alloc(); if (!e->picture) goto bail; /* The idea here is that the encoded frame that will land in this @@ -496,10 +511,10 @@ struct iaxc_video_codec *codec_video_ffmpeg_new(int fo if (!c->decstate) goto bail; d = c->decstate; - d->avctx = avcodec_alloc_context(); + d->avctx = avcodec_alloc_context3(NULL); if (!d->avctx) goto bail; - d->picture = avcodec_alloc_frame(); + d->picture = av_frame_alloc(); if (!d->picture) goto bail; d->frame_buf_len = e->frame_buf_len; @@ -521,20 +536,20 @@ struct iaxc_video_codec *codec_video_ffmpeg_new(int fo /* This determines how often i-frames are sent */ e->avctx->gop_size = framerate * 3; - e->avctx->pix_fmt = PIX_FMT_YUV420P; + e->avctx->pix_fmt = AV_PIX_FMT_YUV420P; e->avctx->has_b_frames = 0; - e->avctx->mb_qmin = e->avctx->qmin = 10; - e->avctx->mb_qmax = e->avctx->qmax = 10; - +#if 0 e->avctx->lmin = 2 * FF_QP2LAMBDA; e->avctx->lmax = 10 * FF_QP2LAMBDA; +#endif + e->avctx->global_quality = FF_QP2LAMBDA * 2; e->avctx->qblur = 0.5; e->avctx->global_quality = 10; - e->avctx->flags |= CODEC_FLAG_PSNR; - e->avctx->flags |= CODEC_FLAG_QSCALE; + e->avctx->flags |= AV_CODEC_FLAG_PSNR; + e->avctx->flags |= AV_CODEC_FLAG_QSCALE; e->avctx->mb_decision = FF_MB_DECISION_SIMPLE; @@ -555,37 +570,38 @@ struct iaxc_video_codec *codec_video_ffmpeg_new(int fo case IAXC_FORMAT_H263: /* TODO: H263 only works with specific resolutions. */ name = "H.263"; - e->avctx->flags |= CODEC_FLAG_AC_PRED; + e->avctx->flags |= AV_CODEC_FLAG_AC_PRED; if (fragsize) { c->decode = decode_rtp_slice; e->avctx->rtp_payload_size = fragsize; e->avctx->flags |= - CODEC_FLAG_TRUNCATED | CODEC_FLAG2_STRICT_GOP; + AV_CODEC_FLAG_TRUNCATED; + av_dict_set(&opts, "strict_gop", "1", 0); e->avctx->rtp_callback = encode_rtp_callback; - d->avctx->flags |= CODEC_FLAG_TRUNCATED; + d->avctx->flags |= AV_CODEC_FLAG_TRUNCATED; } break; case IAXC_FORMAT_H263_PLUS: - /* Although the encoder is CODEC_ID_H263P, the decoder + /* Although the encoder is AV_CODEC_ID_H263P, the decoder * is the regular h.263, so we handle this special case * here. */ - ff_dec_id = CODEC_ID_H263; + ff_dec_id = AV_CODEC_ID_H263; name = "H.263+"; - e->avctx->flags |= CODEC_FLAG_AC_PRED; + e->avctx->flags |= AV_CODEC_FLAG_AC_PRED; if (fragsize) { c->decode = decode_rtp_slice; e->avctx->rtp_payload_size = fragsize; e->avctx->flags |= - CODEC_FLAG_TRUNCATED | - CODEC_FLAG_H263P_SLICE_STRUCT | - CODEC_FLAG2_STRICT_GOP | - CODEC_FLAG2_LOCAL_HEADER; + AV_CODEC_FLAG_TRUNCATED | + AV_CODEC_FLAG2_LOCAL_HEADER; + av_dict_set(&opts, "strict_gop", "1", 0); + av_dict_set(&opts, "structured_slices", "1", 0); e->avctx->rtp_callback = encode_rtp_callback; - d->avctx->flags |= CODEC_FLAG_TRUNCATED; + d->avctx->flags |= AV_CODEC_FLAG_TRUNCATED; } break; @@ -595,12 +611,11 @@ struct iaxc_video_codec *codec_video_ffmpeg_new(int fo e->avctx->rtp_payload_size = fragsize; e->avctx->rtp_callback = encode_rtp_callback; e->avctx->flags |= - CODEC_FLAG_TRUNCATED | - CODEC_FLAG_H263P_SLICE_STRUCT | - CODEC_FLAG2_STRICT_GOP | - CODEC_FLAG2_LOCAL_HEADER; - - d->avctx->flags |= CODEC_FLAG_TRUNCATED; + AV_CODEC_FLAG_TRUNCATED | + AV_CODEC_FLAG2_LOCAL_HEADER; + av_dict_set(&opts, "strict_gop", "1", 0); + av_dict_set(&opts, "structured_slices", "1", 0); + d->avctx->flags |= AV_CODEC_FLAG_TRUNCATED; break; case IAXC_FORMAT_H264: @@ -611,35 +626,35 @@ struct iaxc_video_codec *codec_video_ffmpeg_new(int fo */ /* Headers are not repeated */ - /* e->avctx->flags |= CODEC_FLAG_GLOBAL_HEADER; */ + /* e->avctx->flags |= AV_CODEC_FLAG_GLOBAL_HEADER; */ /* Slower, less blocky */ - /* e->avctx->flags |= CODEC_FLAG_LOOP_FILTER; */ + /* e->avctx->flags |= AV_CODEC_FLAG_LOOP_FILTER; */ - e->avctx->flags |= CODEC_FLAG_PASS1; - /* e->avctx->flags |= CODEC_FLAG_PASS2; */ + e->avctx->flags |= AV_CODEC_FLAG_PASS1; + /* e->avctx->flags |= AV_CODEC_FLAG_PASS2; */ /* Compute psnr values at encode-time (avctx->error[]) */ - /* e->avctx->flags |= CODEC_FLAG_PSNR; */ + /* e->avctx->flags |= AV_CODEC_FLAG_PSNR; */ - /* e->avctx->flags2 |= CODEC_FLAG2_8X8DCT; */ + /* e->avctx->flags2 |= AV_CODEC_FLAG2_8X8DCT; */ /* Access Unit Delimiters */ - e->avctx->flags2 |= CODEC_FLAG2_AUD; + av_dict_set(&opts, "aud", "1", 0); /* Allow b-frames to be used as reference */ - /* e->avctx->flags2 |= CODEC_FLAG2_BPYRAMID; */ + /* e->avctx->flags2 |= AV_CODEC_FLAG2_BPYRAMID; */ /* b-frame rate distortion optimization */ - /* e->avctx->flags2 |= CODEC_FLAG2_BRDO; */ + /* e->avctx->flags2 |= AV_CODEC_FLAG2_BRDO; */ - /* e->avctx->flags2 |= CODEC_FLAG2_FASTPSKIP; */ + /* e->avctx->flags2 |= AV_CODEC_FLAG2_FASTPSKIP; */ /* Multiple references per partition */ - /* e->avctx->flags2 |= CODEC_FLAG2_MIXED_REFS; */ + /* e->avctx->flags2 |= AV_CODEC_FLAG2_MIXED_REFS; */ /* Weighted biprediction for b-frames */ - /* e->avctx->flags2 |= CODEC_FLAG2_WPRED; */ + /* e->avctx->flags2 |= AV_CODEC_FLAG2_WPRED; */ /* * Decoder flags @@ -686,7 +701,7 @@ struct iaxc_video_codec *codec_video_ffmpeg_new(int fo goto bail; } - if (avcodec_open(e->avctx, codec)) + if (avcodec_open2(e->avctx, codec, &opts)) { iaxci_usermsg(IAXC_TEXT_TYPE_ERROR, "codec_ffmpeg: cannot open encoder %s\n", name); @@ -701,7 +716,7 @@ struct iaxc_video_codec *codec_video_ffmpeg_new(int fo ff_dec_id); goto bail; } - if (avcodec_open(d->avctx, codec)) + if (avcodec_open2(d->avctx, codec, NULL)) { iaxci_usermsg(IAXC_TEXT_TYPE_ERROR, "codec_ffmpeg: cannot open decoder %s\n", name); @@ -709,8 +724,8 @@ struct iaxc_video_codec *codec_video_ffmpeg_new(int fo } { - enum PixelFormat fmts[] = { PIX_FMT_YUV420P, -1 }; - if (d->avctx->get_format(d->avctx, fmts) != PIX_FMT_YUV420P) + enum AVPixelFormat fmts[] = { AV_PIX_FMT_YUV420P, -1 }; + if (d->avctx->get_format(d->avctx, fmts) != AV_PIX_FMT_YUV420P) { iaxci_usermsg(IAXC_TEXT_TYPE_ERROR, "codec_ffmpeg: cannot set decode format to YUV420P\n"); @@ -728,17 +743,16 @@ bail: int codec_video_ffmpeg_check_codec(int format) { AVCodec *codec; - enum CodecID codec_id; + enum AVCodecID codec_id; /* These functions are idempotent, so it is okay that we * may call them elsewhere at a different time. */ - avcodec_init(); avcodec_register_all(); codec_id = map_iaxc_codec_to_avcodec(format); - if (codec_id == CODEC_ID_NONE) + if (codec_id == AV_CODEC_ID_NONE) return 0; codec = avcodec_find_encoder(codec_id);