From 0635a8aa21d0495575c24f1883c1e6832d882657 Mon Sep 17 00:00:00 2001 From: Anton Khirnov Date: Thu, 1 Sep 2011 13:15:09 +0200 Subject: [PATCH 01/11] libx264: add 'partitions' private option Deprecate AVCodecContext.partitions. --- libavcodec/avcodec.h | 4 ++-- libavcodec/libx264.c | 30 ++++++++++++++++-------------- libavcodec/options.c | 2 +- libavformat/ffmdec.c | 1 - libavformat/ffmenc.c | 1 - tests/ref/lavf/ffm | 2 +- 6 files changed, 20 insertions(+), 20 deletions(-) diff --git a/libavcodec/avcodec.h b/libavcodec/avcodec.h index 828382a0b5..7eb4a01291 100644 --- a/libavcodec/avcodec.h +++ b/libavcodec/avcodec.h @@ -2472,19 +2472,19 @@ typedef struct AVCodecContext { * - decoding: unused */ attribute_deprecated int deblockbeta; -#endif /** * macroblock subpartition sizes to consider - p8x8, p4x4, b8x8, i8x8, i4x4 * - encoding: Set by user. * - decoding: unused */ - int partitions; + attribute_deprecated int partitions; #define X264_PART_I4X4 0x001 /* Analyze i4x4 */ #define X264_PART_I8X8 0x002 /* Analyze i8x8 (requires 8x8 transform) */ #define X264_PART_P8X8 0x010 /* Analyze p16x8, p8x16 and p8x8 */ #define X264_PART_P4X4 0x020 /* Analyze p8x4, p4x8, p4x4 */ #define X264_PART_B8X8 0x100 /* Analyze b16x8, b8x16 and b8x8 */ +#endif /** * direct MV prediction mode - 0 (none), 1 (spatial), 2 (temporal), 3 (auto) diff --git a/libavcodec/libx264.c b/libavcodec/libx264.c index 8eff59ceb9..10cb32eda2 100644 --- a/libavcodec/libx264.c +++ b/libavcodec/libx264.c @@ -62,6 +62,7 @@ typedef struct X264Context { int mbtree; char *deblock; float cplxblur; + char *partitions; } X264Context; static void X264_log(void *p, int level, const char *fmt, va_list args) @@ -207,20 +208,6 @@ static av_cold int X264_init(AVCodecContext *avctx) x4->params.b_deblocking_filter = avctx->flags & CODEC_FLAG_LOOP_FILTER; - x4->params.analyse.inter = 0; - if (avctx->partitions) { - if (avctx->partitions & X264_PART_I4X4) - x4->params.analyse.inter |= X264_ANALYSE_I4x4; - if (avctx->partitions & X264_PART_I8X8) - x4->params.analyse.inter |= X264_ANALYSE_I8x8; - if (avctx->partitions & X264_PART_P8X8) - x4->params.analyse.inter |= X264_ANALYSE_PSUB16x16; - if (avctx->partitions & X264_PART_P4X4) - x4->params.analyse.inter |= X264_ANALYSE_PSUB8x8; - if (avctx->partitions & X264_PART_B8X8) - x4->params.analyse.inter |= X264_ANALYSE_BSUB16x16; - } - x4->params.analyse.i_direct_mv_pred = avctx->directpred; if (avctx->me_method == ME_EPZS) @@ -320,6 +307,18 @@ static av_cold int X264_init(AVCodecContext *avctx) x4->params.i_deblocking_filter_beta = avctx->deblockbeta; if (avctx->complexityblur >= 0) x4->params.rc.f_complexity_blur = avctx->complexityblur; + if (avctx->partitions) { + if (avctx->partitions & X264_PART_I4X4) + x4->params.analyse.inter |= X264_ANALYSE_I4x4; + if (avctx->partitions & X264_PART_I8X8) + x4->params.analyse.inter |= X264_ANALYSE_I8x8; + if (avctx->partitions & X264_PART_P8X8) + x4->params.analyse.inter |= X264_ANALYSE_PSUB16x16; + if (avctx->partitions & X264_PART_P4X4) + x4->params.analyse.inter |= X264_ANALYSE_PSUB8x8; + if (avctx->partitions & X264_PART_B8X8) + x4->params.analyse.inter |= X264_ANALYSE_BSUB16x16; + } x4->params.analyse.b_ssim = avctx->flags2 & CODEC_FLAG2_SSIM; x4->params.b_intra_refresh = avctx->flags2 & CODEC_FLAG2_INTRA_REFRESH; x4->params.i_bframe_pyramid = avctx->flags2 & CODEC_FLAG2_BPYRAMID ? X264_B_PYRAMID_NORMAL : X264_B_PYRAMID_NONE; @@ -357,6 +356,7 @@ static av_cold int X264_init(AVCodecContext *avctx) x4->params.rc.f_aq_strength = x4->aq_strength; PARSE_X264_OPT("psy-rd", psy_rd); PARSE_X264_OPT("deblock", deblock); + PARSE_X264_OPT("partitions", partitions); if (x4->psy >= 0) x4->params.analyse.b_psy = x4->psy; if (x4->rc_lookahead >= 0) @@ -486,6 +486,8 @@ static const AVOption options[] = { { "mbtree", "Use macroblock tree ratecontrol.", OFFSET(mbtree), FF_OPT_TYPE_INT, {-1 }, -1, 1, VE}, { "deblock", "Loop filter parameters, in form.", OFFSET(deblock), FF_OPT_TYPE_STRING, { 0 }, 0, 0, VE}, { "cplxblur", "Reduce fluctuations in QP (before curve compression)", OFFSET(cplxblur), FF_OPT_TYPE_FLOAT, {-1 }, -1, FLT_MAX, VE}, + { "partitions", "A comma-separated list of partitions to consider. " + "Possible values: p8x8, p4x4, b8x8, i8x8, i4x4, none, all", OFFSET(partitions), FF_OPT_TYPE_STRING, { 0 }, 0, 0, VE}, { NULL }, }; diff --git a/libavcodec/options.c b/libavcodec/options.c index f19a681a56..0d670056dc 100644 --- a/libavcodec/options.c +++ b/libavcodec/options.c @@ -416,13 +416,13 @@ static const AVOption options[]={ {"complexityblur", "reduce fluctuations in qp (before curve compression)", OFFSET(complexityblur), FF_OPT_TYPE_FLOAT, {.dbl = -1 }, -1, FLT_MAX, V|E}, {"deblockalpha", "in-loop deblocking filter alphac0 parameter", OFFSET(deblockalpha), FF_OPT_TYPE_INT, {.dbl = DEFAULT }, -6, 6, V|E}, {"deblockbeta", "in-loop deblocking filter beta parameter", OFFSET(deblockbeta), FF_OPT_TYPE_INT, {.dbl = DEFAULT }, -6, 6, V|E}, -#endif {"partitions", "macroblock subpartition sizes to consider", OFFSET(partitions), FF_OPT_TYPE_FLAGS, {.dbl = DEFAULT }, INT_MIN, INT_MAX, V|E, "partitions"}, {"parti4x4", NULL, 0, FF_OPT_TYPE_CONST, {.dbl = X264_PART_I4X4 }, INT_MIN, INT_MAX, V|E, "partitions"}, {"parti8x8", NULL, 0, FF_OPT_TYPE_CONST, {.dbl = X264_PART_I8X8 }, INT_MIN, INT_MAX, V|E, "partitions"}, {"partp4x4", NULL, 0, FF_OPT_TYPE_CONST, {.dbl = X264_PART_P4X4 }, INT_MIN, INT_MAX, V|E, "partitions"}, {"partp8x8", NULL, 0, FF_OPT_TYPE_CONST, {.dbl = X264_PART_P8X8 }, INT_MIN, INT_MAX, V|E, "partitions"}, {"partb8x8", NULL, 0, FF_OPT_TYPE_CONST, {.dbl = X264_PART_B8X8 }, INT_MIN, INT_MAX, V|E, "partitions"}, +#endif {"sc_factor", "multiplied by qscale for each frame and added to scene_change_score", OFFSET(scenechange_factor), FF_OPT_TYPE_INT, {.dbl = 6 }, 0, INT_MAX, V|E}, {"mv0_threshold", NULL, OFFSET(mv0_threshold), FF_OPT_TYPE_INT, {.dbl = 256 }, 0, INT_MAX, V|E}, #if FF_API_MPEGVIDEO_GLOBAL_OPTS diff --git a/libavformat/ffmdec.c b/libavformat/ffmdec.c index 07f790773c..143f20b5db 100644 --- a/libavformat/ffmdec.c +++ b/libavformat/ffmdec.c @@ -344,7 +344,6 @@ static int ffm_read_header(AVFormatContext *s, AVFormatParameters *ap) codec->thread_count = avio_r8(pb); codec->coder_type = avio_rb32(pb); codec->me_cmp = avio_rb32(pb); - codec->partitions = avio_rb32(pb); codec->me_subpel_quality = avio_rb32(pb); codec->me_range = avio_rb32(pb); codec->keyint_min = avio_rb32(pb); diff --git a/libavformat/ffmenc.c b/libavformat/ffmenc.c index 07876ccd4b..e9d25717b8 100644 --- a/libavformat/ffmenc.c +++ b/libavformat/ffmenc.c @@ -156,7 +156,6 @@ static int ffm_write_header(AVFormatContext *s) avio_w8(pb, codec->thread_count); avio_wb32(pb, codec->coder_type); avio_wb32(pb, codec->me_cmp); - avio_wb32(pb, codec->partitions); avio_wb32(pb, codec->me_subpel_quality); avio_wb32(pb, codec->me_range); avio_wb32(pb, codec->keyint_min); diff --git a/tests/ref/lavf/ffm b/tests/ref/lavf/ffm index b20e132b45..ac4922c942 100644 --- a/tests/ref/lavf/ffm +++ b/tests/ref/lavf/ffm @@ -1,3 +1,3 @@ -f9bee27ea1b6b83a06b5f9efb0a4ac1f *./tests/data/lavf/lavf.ffm +6d6db9474c5c10621bff51f20984797b *./tests/data/lavf/lavf.ffm 376832 ./tests/data/lavf/lavf.ffm ./tests/data/lavf/lavf.ffm CRC=0xf361ed74 From 9c684feadc063473da3f9e341fa07e6c17b75154 Mon Sep 17 00:00:00 2001 From: Anton Khirnov Date: Thu, 1 Sep 2011 13:15:09 +0200 Subject: [PATCH 02/11] libx264: add 'direct-pred' private option Deprecate AVCodecContext.directpred --- libavcodec/avcodec.h | 4 ++-- libavcodec/libx264.c | 12 ++++++++++-- libavcodec/options.c | 2 +- libavformat/ffmdec.c | 1 - libavformat/ffmenc.c | 1 - tests/ref/lavf/ffm | 2 +- 6 files changed, 14 insertions(+), 8 deletions(-) diff --git a/libavcodec/avcodec.h b/libavcodec/avcodec.h index 7eb4a01291..7fc0e545fc 100644 --- a/libavcodec/avcodec.h +++ b/libavcodec/avcodec.h @@ -2484,14 +2484,14 @@ typedef struct AVCodecContext { #define X264_PART_P8X8 0x010 /* Analyze p16x8, p8x16 and p8x8 */ #define X264_PART_P4X4 0x020 /* Analyze p8x4, p4x8, p4x4 */ #define X264_PART_B8X8 0x100 /* Analyze b16x8, b8x16 and b8x8 */ -#endif /** * direct MV prediction mode - 0 (none), 1 (spatial), 2 (temporal), 3 (auto) * - encoding: Set by user. * - decoding: unused */ - int directpred; + attribute_deprecated int directpred; +#endif /** * Audio cutoff bandwidth (0 means "automatic") diff --git a/libavcodec/libx264.c b/libavcodec/libx264.c index 10cb32eda2..d915735a76 100644 --- a/libavcodec/libx264.c +++ b/libavcodec/libx264.c @@ -63,6 +63,7 @@ typedef struct X264Context { char *deblock; float cplxblur; char *partitions; + int direct_pred; } X264Context; static void X264_log(void *p, int level, const char *fmt, va_list args) @@ -208,8 +209,6 @@ static av_cold int X264_init(AVCodecContext *avctx) x4->params.b_deblocking_filter = avctx->flags & CODEC_FLAG_LOOP_FILTER; - x4->params.analyse.i_direct_mv_pred = avctx->directpred; - if (avctx->me_method == ME_EPZS) x4->params.analyse.i_me_method = X264_ME_DIA; else if (avctx->me_method == ME_HEX) @@ -307,6 +306,8 @@ static av_cold int X264_init(AVCodecContext *avctx) x4->params.i_deblocking_filter_beta = avctx->deblockbeta; if (avctx->complexityblur >= 0) x4->params.rc.f_complexity_blur = avctx->complexityblur; + if (avctx->directpred >= 0) + x4->params.analyse.i_direct_mv_pred = avctx->directpred; if (avctx->partitions) { if (avctx->partitions & X264_PART_I4X4) x4->params.analyse.inter |= X264_ANALYSE_I4x4; @@ -386,6 +387,8 @@ static av_cold int X264_init(AVCodecContext *avctx) x4->params.b_aud = x4->aud; if (x4->mbtree >= 0) x4->params.rc.b_mb_tree = x4->mbtree; + if (x4->direct_pred >= 0) + x4->params.analyse.i_direct_mv_pred = x4->direct_pred; if (x4->fastfirstpass) x264_param_apply_fastfirstpass(&x4->params); @@ -488,6 +491,11 @@ static const AVOption options[] = { { "cplxblur", "Reduce fluctuations in QP (before curve compression)", OFFSET(cplxblur), FF_OPT_TYPE_FLOAT, {-1 }, -1, FLT_MAX, VE}, { "partitions", "A comma-separated list of partitions to consider. " "Possible values: p8x8, p4x4, b8x8, i8x8, i4x4, none, all", OFFSET(partitions), FF_OPT_TYPE_STRING, { 0 }, 0, 0, VE}, + { "direct-pred", "Direct MV prediction mode", OFFSET(direct_pred), FF_OPT_TYPE_INT, {-1 }, -1, INT_MAX, VE, "direct-pred" }, + { "none", NULL, 0, FF_OPT_TYPE_CONST, { X264_DIRECT_PRED_NONE }, 0, 0, VE, "direct-pred" }, + { "spatial", NULL, 0, FF_OPT_TYPE_CONST, { X264_DIRECT_PRED_SPATIAL }, 0, 0, VE, "direct-pred" }, + { "temporal", NULL, 0, FF_OPT_TYPE_CONST, { X264_DIRECT_PRED_TEMPORAL }, 0, 0, VE, "direct-pred" }, + { "auto", NULL, 0, FF_OPT_TYPE_CONST, { X264_DIRECT_PRED_AUTO }, 0, 0, VE, "direct-pred" }, { NULL }, }; diff --git a/libavcodec/options.c b/libavcodec/options.c index 0d670056dc..098778aa23 100644 --- a/libavcodec/options.c +++ b/libavcodec/options.c @@ -402,8 +402,8 @@ static const AVOption options[]={ {"bframebias", "influences how often B-frames are used", OFFSET(bframebias), FF_OPT_TYPE_INT, {.dbl = DEFAULT }, INT_MIN, INT_MAX, V|E}, #endif {"trellis", "rate-distortion optimal quantization", OFFSET(trellis), FF_OPT_TYPE_INT, {.dbl = DEFAULT }, INT_MIN, INT_MAX, V|A|E}, -{"directpred", "direct mv prediction mode - 0 (none), 1 (spatial), 2 (temporal), 3 (auto)", OFFSET(directpred), FF_OPT_TYPE_INT, {.dbl = 2 }, INT_MIN, INT_MAX, V|E}, #if FF_API_X264_GLOBAL_OPTS +{"directpred", "direct mv prediction mode - 0 (none), 1 (spatial), 2 (temporal), 3 (auto)", OFFSET(directpred), FF_OPT_TYPE_INT, {.dbl = -1 }, INT_MIN, INT_MAX, V|E}, {"bpyramid", "allows B-frames to be used as references for predicting", 0, FF_OPT_TYPE_CONST, {.dbl = CODEC_FLAG2_BPYRAMID }, INT_MIN, INT_MAX, V|E, "flags2"}, {"wpred", "weighted biprediction for b-frames (H.264)", 0, FF_OPT_TYPE_CONST, {.dbl = CODEC_FLAG2_WPRED }, INT_MIN, INT_MAX, V|E, "flags2"}, {"mixed_refs", "one reference per partition, as opposed to one reference per macroblock", 0, FF_OPT_TYPE_CONST, {.dbl = CODEC_FLAG2_MIXED_REFS }, INT_MIN, INT_MAX, V|E, "flags2"}, diff --git a/libavformat/ffmdec.c b/libavformat/ffmdec.c index 143f20b5db..b9516d5b8b 100644 --- a/libavformat/ffmdec.c +++ b/libavformat/ffmdec.c @@ -353,7 +353,6 @@ static int ffm_read_header(AVFormatContext *s, AVFormatParameters *ap) codec->qblur = av_int2dbl(avio_rb64(pb)); codec->max_qdiff = avio_rb32(pb); codec->refs = avio_rb32(pb); - codec->directpred = avio_rb32(pb); break; case AVMEDIA_TYPE_AUDIO: codec->sample_rate = avio_rb32(pb); diff --git a/libavformat/ffmenc.c b/libavformat/ffmenc.c index e9d25717b8..4bfae693e5 100644 --- a/libavformat/ffmenc.c +++ b/libavformat/ffmenc.c @@ -165,7 +165,6 @@ static int ffm_write_header(AVFormatContext *s) avio_wb64(pb, av_dbl2int(codec->qblur)); avio_wb32(pb, codec->max_qdiff); avio_wb32(pb, codec->refs); - avio_wb32(pb, codec->directpred); break; case AVMEDIA_TYPE_AUDIO: avio_wb32(pb, codec->sample_rate); diff --git a/tests/ref/lavf/ffm b/tests/ref/lavf/ffm index ac4922c942..cdfec4d1fb 100644 --- a/tests/ref/lavf/ffm +++ b/tests/ref/lavf/ffm @@ -1,3 +1,3 @@ -6d6db9474c5c10621bff51f20984797b *./tests/data/lavf/lavf.ffm +bf46c0b53fc318d0a60fa9bf446b2e4f *./tests/data/lavf/lavf.ffm 376832 ./tests/data/lavf/lavf.ffm ./tests/data/lavf/lavf.ffm CRC=0xf361ed74 From 2bb5d637fc9821247cd4cd49a048bd52966ebb34 Mon Sep 17 00:00:00 2001 From: Andrej Peterka Date: Wed, 7 Sep 2011 08:27:28 +0200 Subject: [PATCH 03/11] libx264: fix setting the H.264 level Move setting it after x264_param_default_preset() Signed-off-by: Anton Khirnov --- libavcodec/libx264.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/libavcodec/libx264.c b/libavcodec/libx264.c index d915735a76..305c26a781 100644 --- a/libavcodec/libx264.c +++ b/libavcodec/libx264.c @@ -229,15 +229,15 @@ static av_cold int X264_init(AVCodecContext *avctx) x4->params.analyse.i_trellis = avctx->trellis; x4->params.analyse.i_noise_reduction = avctx->noise_reduction; - if (avctx->level > 0) - x4->params.i_level_idc = avctx->level; - if (x4->preset || x4->tune) if (x264_param_default_preset(&x4->params, x4->preset, x4->tune) < 0) { av_log(avctx, AV_LOG_ERROR, "Error setting preset/tune %s/%s.\n", x4->preset, x4->tune); return AVERROR(EINVAL); } + if (avctx->level > 0) + x4->params.i_level_idc = avctx->level; + x4->params.pf_log = X264_log; x4->params.p_log_private = avctx; x4->params.i_log_level = X264_LOG_DEBUG; From 0962f23b35ec6aa497f8338a7ddc2d82fda0a400 Mon Sep 17 00:00:00 2001 From: Anton Khirnov Date: Wed, 7 Sep 2011 09:13:02 +0200 Subject: [PATCH 04/11] libx264: fix setting some more parameters Specifically, trellis, nr, me_range, me_method, subq, b_strategy, keyint_min, chroma_me and coder. Change their defaults to -1 and apply them after x264_param_default_preset() if the user explicitly set them. --- libavcodec/libx264.c | 63 +++++++++++++++++++++++++------------------- 1 file changed, 36 insertions(+), 27 deletions(-) diff --git a/libavcodec/libx264.c b/libavcodec/libx264.c index 305c26a781..fc0ba150b6 100644 --- a/libavcodec/libx264.c +++ b/libavcodec/libx264.c @@ -200,35 +200,8 @@ static av_cold int X264_init(AVCodecContext *avctx) x264_param_default(&x4->params); - x4->params.b_cabac = avctx->coder_type == FF_CODER_TYPE_AC; - x4->params.i_bframe_adaptive = avctx->b_frame_strategy; - - x4->params.i_keyint_min = avctx->keyint_min; - if (x4->params.i_keyint_min > x4->params.i_keyint_max) - x4->params.i_keyint_min = x4->params.i_keyint_max; - x4->params.b_deblocking_filter = avctx->flags & CODEC_FLAG_LOOP_FILTER; - if (avctx->me_method == ME_EPZS) - x4->params.analyse.i_me_method = X264_ME_DIA; - else if (avctx->me_method == ME_HEX) - x4->params.analyse.i_me_method = X264_ME_HEX; - else if (avctx->me_method == ME_UMH) - x4->params.analyse.i_me_method = X264_ME_UMH; - else if (avctx->me_method == ME_FULL) - x4->params.analyse.i_me_method = X264_ME_ESA; - else if (avctx->me_method == ME_TESA) - x4->params.analyse.i_me_method = X264_ME_TESA; - else x4->params.analyse.i_me_method = X264_ME_HEX; - - x4->params.analyse.i_me_range = avctx->me_range; - x4->params.analyse.i_subpel_refine = avctx->me_subpel_quality; - - x4->params.analyse.b_chroma_me = avctx->me_cmp & FF_CMP_CHROMA; - - x4->params.analyse.i_trellis = avctx->trellis; - x4->params.analyse.i_noise_reduction = avctx->noise_reduction; - if (x4->preset || x4->tune) if (x264_param_default_preset(&x4->params, x4->preset, x4->tune) < 0) { av_log(avctx, AV_LOG_ERROR, "Error setting preset/tune %s/%s.\n", x4->preset, x4->tune); @@ -332,6 +305,17 @@ static av_cold int X264_init(AVCodecContext *avctx) x4->params.rc.b_mb_tree = !!(avctx->flags2 & CODEC_FLAG2_MBTREE); #endif + if (avctx->me_method == ME_EPZS) + x4->params.analyse.i_me_method = X264_ME_DIA; + else if (avctx->me_method == ME_HEX) + x4->params.analyse.i_me_method = X264_ME_HEX; + else if (avctx->me_method == ME_UMH) + x4->params.analyse.i_me_method = X264_ME_UMH; + else if (avctx->me_method == ME_FULL) + x4->params.analyse.i_me_method = X264_ME_ESA; + else if (avctx->me_method == ME_TESA) + x4->params.analyse.i_me_method = X264_ME_TESA; + if (avctx->gop_size >= 0) x4->params.i_keyint_max = avctx->gop_size; if (avctx->max_b_frames >= 0) @@ -350,6 +334,22 @@ static av_cold int X264_init(AVCodecContext *avctx) x4->params.rc.f_qcompress = avctx->qcompress; /* 0.0 => cbr, 1.0 => constant qp */ if (avctx->refs >= 0) x4->params.i_frame_reference = avctx->refs; + if (avctx->trellis >= 0) + x4->params.analyse.i_trellis = avctx->trellis; + if (avctx->me_range >= 0) + x4->params.analyse.i_me_range = avctx->me_range; + if (avctx->noise_reduction >= 0) + x4->params.analyse.i_noise_reduction = avctx->noise_reduction; + if (avctx->me_subpel_quality >= 0) + x4->params.analyse.i_subpel_refine = avctx->me_subpel_quality; + if (avctx->b_frame_strategy >= 0) + x4->params.i_bframe_adaptive = avctx->b_frame_strategy; + if (avctx->keyint_min >= 0) + x4->params.i_keyint_min = avctx->keyint_min; + if (avctx->coder_type >= 0) + x4->params.b_cabac = avctx->coder_type == FF_CODER_TYPE_AC; + if (avctx->me_cmp >= 0) + x4->params.analyse.b_chroma_me = avctx->me_cmp & FF_CMP_CHROMA; if (x4->aq_mode >= 0) x4->params.rc.i_aq_mode = x4->aq_mode; @@ -517,6 +517,15 @@ static const AVCodecDefault x264_defaults[] = { { "qcomp", "-1" }, { "refs", "-1" }, { "sc_threshold", "-1" }, + { "trellis", "-1" }, + { "nr", "-1" }, + { "me_range", "-1" }, + { "me_method", "-1" }, + { "subq", "-1" }, + { "b_strategy", "-1" }, + { "keyint_min", "-1" }, + { "coder", "-1" }, + { "cmp", "-1" }, { "threads", AV_STRINGIFY(X264_THREADS_AUTO) }, { NULL }, }; From a7e2b2ccc9e184820f13894de6cb7e49abcb6130 Mon Sep 17 00:00:00 2001 From: Anton Khirnov Date: Sun, 4 Sep 2011 11:39:49 +0200 Subject: [PATCH 05/11] AVOptions: move doxy for av_opt_set_defaults() from opt.c to opt.h Also change it to be more readable. --- libavutil/opt.c | 6 ------ libavutil/opt.h | 5 +++++ 2 files changed, 5 insertions(+), 6 deletions(-) diff --git a/libavutil/opt.c b/libavutil/opt.c index 707977a7a9..0dd58a7f14 100644 --- a/libavutil/opt.c +++ b/libavutil/opt.c @@ -414,12 +414,6 @@ int av_opt_show2(void *obj, void *av_log_obj, int req_flags, int rej_flags) return 0; } -/** Set the values of the AVCodecContext or AVFormatContext structure. - * They are set to the defaults specified in the according AVOption options - * array default_val field. - * - * @param s AVCodecContext or AVFormatContext for which the defaults will be set - */ void av_opt_set_defaults2(void *s, int mask, int flags) { const AVOption *opt = NULL; diff --git a/libavutil/opt.h b/libavutil/opt.h index 68d2c798e2..f8eea6bc2a 100644 --- a/libavutil/opt.h +++ b/libavutil/opt.h @@ -160,6 +160,11 @@ const AVOption *av_next_option(void *obj, const AVOption *last); */ int av_opt_show2(void *obj, void *av_log_obj, int req_flags, int rej_flags); +/** + * Set the values of all AVOption fields to their default values. + * + * @param s an AVOption-enabled struct (its first member must be a pointer to AVClass) + */ void av_opt_set_defaults(void *s); void av_opt_set_defaults2(void *s, int mask, int flags); From 79eff9132581af69fbbd2674337b75fad29aa306 Mon Sep 17 00:00:00 2001 From: Anton Khirnov Date: Sun, 4 Sep 2011 11:42:41 +0200 Subject: [PATCH 06/11] AVOptions: deprecate av_opt_set_defaults2 It's a hack which was created to allow for multiple options with different defaults to refer to same field (e.g. 'b' vs 'ab'). There is no need for it anymore. --- libavcodec/options.c | 9 +-------- libavfilter/vf_drawtext.c | 2 +- libavfilter/vsrc_movie.c | 2 +- libavutil/avutil.h | 3 +++ libavutil/opt.c | 16 ++++++++++------ libavutil/opt.h | 4 ++++ 6 files changed, 20 insertions(+), 16 deletions(-) diff --git a/libavcodec/options.c b/libavcodec/options.c index 098778aa23..7d14beba6a 100644 --- a/libavcodec/options.c +++ b/libavcodec/options.c @@ -519,19 +519,12 @@ static const AVOption options[]={ static const AVClass av_codec_context_class = { "AVCodecContext", context_to_name, options, LIBAVUTIL_VERSION_INT, OFFSET(log_level_offset), .opt_find = opt_find}; void avcodec_get_context_defaults2(AVCodecContext *s, enum AVMediaType codec_type){ - int flags=0; memset(s, 0, sizeof(AVCodecContext)); s->av_class= &av_codec_context_class; s->codec_type = codec_type; - if(codec_type == AVMEDIA_TYPE_AUDIO) - flags= AV_OPT_FLAG_AUDIO_PARAM; - else if(codec_type == AVMEDIA_TYPE_VIDEO) - flags= AV_OPT_FLAG_VIDEO_PARAM; - else if(codec_type == AVMEDIA_TYPE_SUBTITLE) - flags= AV_OPT_FLAG_SUBTITLE_PARAM; - av_opt_set_defaults2(s, flags, flags); + av_opt_set_defaults(s); s->time_base= (AVRational){0,1}; s->get_buffer= avcodec_default_get_buffer; diff --git a/libavfilter/vf_drawtext.c b/libavfilter/vf_drawtext.c index ed4b1003d8..3e16baf87e 100644 --- a/libavfilter/vf_drawtext.c +++ b/libavfilter/vf_drawtext.c @@ -223,7 +223,7 @@ static av_cold int init(AVFilterContext *ctx, const char *args, void *opaque) Glyph *glyph; dtext->class = &drawtext_class; - av_opt_set_defaults2(dtext, 0, 0); + av_opt_set_defaults(dtext); dtext->fontcolor_string = av_strdup("black"); dtext->boxcolor_string = av_strdup("white"); dtext->shadowcolor_string = av_strdup("black"); diff --git a/libavfilter/vsrc_movie.c b/libavfilter/vsrc_movie.c index b018ba7418..a5d5572f48 100644 --- a/libavfilter/vsrc_movie.c +++ b/libavfilter/vsrc_movie.c @@ -164,7 +164,7 @@ static av_cold int init(AVFilterContext *ctx, const char *args, void *opaque) MovieContext *movie = ctx->priv; int ret; movie->class = &movie_class; - av_opt_set_defaults2(movie, 0, 0); + av_opt_set_defaults(movie); if (args) movie->file_name = av_get_token(&args, ":"); diff --git a/libavutil/avutil.h b/libavutil/avutil.h index 24594107bc..3f9267908a 100644 --- a/libavutil/avutil.h +++ b/libavutil/avutil.h @@ -66,6 +66,9 @@ #ifndef FF_API_AV_FIFO_PEEK #define FF_API_AV_FIFO_PEEK (LIBAVUTIL_VERSION_MAJOR < 52) #endif +#ifndef FF_API_OLD_AVOPTIONS +#define FF_API_OLD_AVOPTIONS (LIBAVUTIL_VERSION_MAJOR < 52) +#endif /** * Return the LIBAVUTIL_VERSION_INT constant. diff --git a/libavutil/opt.c b/libavutil/opt.c index 0dd58a7f14..160da8d756 100644 --- a/libavutil/opt.c +++ b/libavutil/opt.c @@ -414,12 +414,21 @@ int av_opt_show2(void *obj, void *av_log_obj, int req_flags, int rej_flags) return 0; } +void av_opt_set_defaults(void *s) +{ +#if FF_API_OLD_AVOPTIONS + av_opt_set_defaults2(s, 0, 0); +} + void av_opt_set_defaults2(void *s, int mask, int flags) { +#endif const AVOption *opt = NULL; while ((opt = av_next_option(s, opt)) != NULL) { +#if FF_API_OLD_AVOPTIONS if ((opt->flags & mask) != flags) continue; +#endif switch (opt->type) { case FF_OPT_TYPE_CONST: /* Nothing to be done here */ @@ -461,11 +470,6 @@ void av_opt_set_defaults2(void *s, int mask, int flags) } } -void av_opt_set_defaults(void *s) -{ - av_opt_set_defaults2(s, 0, 0); -} - /** * Store the value in the field in ctx that is named like key. * ctx must be an AVClass context, storing is done using AVOptions. @@ -648,7 +652,7 @@ int main(void) }; test_ctx.class = &test_class; - av_opt_set_defaults2(&test_ctx, 0, 0); + av_opt_set_defaults(&test_ctx); test_ctx.string = av_strdup("default"); av_log_set_level(AV_LOG_DEBUG); diff --git a/libavutil/opt.h b/libavutil/opt.h index f8eea6bc2a..c6a59196be 100644 --- a/libavutil/opt.h +++ b/libavutil/opt.h @@ -166,7 +166,11 @@ int av_opt_show2(void *obj, void *av_log_obj, int req_flags, int rej_flags); * @param s an AVOption-enabled struct (its first member must be a pointer to AVClass) */ void av_opt_set_defaults(void *s); + +#if FF_API_OLD_AVOPTIONS +attribute_deprecated void av_opt_set_defaults2(void *s, int mask, int flags); +#endif /** * Parse the key/value pairs list in opts. For each key/value pair From 4dbcdfa86d1405f7e5c0ec14a4be7d2fb5903d7b Mon Sep 17 00:00:00 2001 From: Anton Khirnov Date: Mon, 5 Sep 2011 21:44:33 +0200 Subject: [PATCH 07/11] AVOptions: remove AVOption.offset <= 0 checks They will only ever be <=0 if the option is broken, in which case this check is hiding a bug. --- libavutil/opt.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/libavutil/opt.c b/libavutil/opt.c index 160da8d756..1dec9a67d4 100644 --- a/libavutil/opt.c +++ b/libavutil/opt.c @@ -60,7 +60,7 @@ static int av_set_number2(void *obj, const char *name, double num, int den, int6 void *dst; if (o_out) *o_out= o; - if (!o || o->offset<=0) + if (!o) return AVERROR_OPTION_NOT_FOUND; if (o->max*den < num*intnum || o->min*den > num*intnum) { @@ -124,7 +124,7 @@ int av_set_string3(void *obj, const char *name, const char *val, int alloc, cons *o_out = o; if (!o) return AVERROR_OPTION_NOT_FOUND; - if (!val || o->offset<=0) + if (!val) return AVERROR(EINVAL); if (o->type == FF_OPT_TYPE_BINARY) { @@ -234,7 +234,7 @@ const char *av_get_string(void *obj, const char *name, const AVOption **o_out, c void *dst; uint8_t *bin; int len, i; - if (!o || o->offset<=0) + if (!o) return NULL; if (o->type != FF_OPT_TYPE_STRING && (!buf || !buf_len)) return NULL; @@ -265,7 +265,7 @@ static int get_number(void *obj, const char *name, const AVOption **o_out, doubl { const AVOption *o = av_opt_find(obj, name, NULL, 0, 0); void *dst; - if (!o || o->offset<=0) + if (!o) goto error; dst= ((uint8_t*)obj) + o->offset; From 08fa23d6c2e9a39857045702c1d2804c0b99ccec Mon Sep 17 00:00:00 2001 From: Baptiste Coudurier Date: Sun, 8 May 2011 17:54:20 +0200 Subject: [PATCH 08/11] v210dec: switch to PIX_FMT_422P10 Signed-off-by: Anton Khirnov --- libavcodec/v210dec.c | 20 ++++++++++---------- tests/ref/fate/v210 | 2 +- 2 files changed, 11 insertions(+), 11 deletions(-) diff --git a/libavcodec/v210dec.c b/libavcodec/v210dec.c index fa67635ed3..37b4a3c423 100644 --- a/libavcodec/v210dec.c +++ b/libavcodec/v210dec.c @@ -30,7 +30,7 @@ static av_cold int decode_init(AVCodecContext *avctx) av_log(avctx, AV_LOG_ERROR, "v210 needs even width\n"); return -1; } - avctx->pix_fmt = PIX_FMT_YUV422P16; + avctx->pix_fmt = PIX_FMT_YUV422P10; avctx->bits_per_raw_sample = 10; avctx->coded_frame = avcodec_alloc_frame(); @@ -68,10 +68,10 @@ static int decode_frame(AVCodecContext *avctx, void *data, int *data_size, #define READ_PIXELS(a, b, c) \ do { \ - val = av_le2ne32(*src++); \ - *a++ = val << 6; \ - *b++ = (val >> 4) & 0xFFC0; \ - *c++ = (val >> 14) & 0xFFC0; \ + val = av_le2ne32(*src++); \ + *a++ = val & 0x3FF; \ + *b++ = (val >> 10) & 0x3FF; \ + *c++ = (val >> 20) & 0x3FF; \ } while (0) for (h = 0; h < avctx->height; h++) { @@ -87,15 +87,15 @@ static int decode_frame(AVCodecContext *avctx, void *data, int *data_size, READ_PIXELS(u, y, v); val = av_le2ne32(*src++); - *y++ = val << 6; + *y++ = val & 0x3FF; } if (w < avctx->width - 3) { - *u++ = (val >> 4) & 0xFFC0; - *y++ = (val >> 14) & 0xFFC0; + *u++ = (val >> 10) & 0x3FF; + *y++ = (val >> 20) & 0x3FF; val = av_le2ne32(*src++); - *v++ = val << 6; - *y++ = (val >> 4) & 0xFFC0; + *v++ = val & 0x3FF; + *y++ = (val >> 10) & 0x3FF; } psrc += stride; diff --git a/tests/ref/fate/v210 b/tests/ref/fate/v210 index 8cbf7df787..6a551a56b5 100644 --- a/tests/ref/fate/v210 +++ b/tests/ref/fate/v210 @@ -1 +1 @@ -0, 0, 3686400, 0x8d5c3847 +0, 0, 3686400, 0x75ee1dde From d239b83e2e5addea31c5e3277131406c6bfc3283 Mon Sep 17 00:00:00 2001 From: Baptiste Coudurier Date: Sun, 8 May 2011 17:57:54 +0200 Subject: [PATCH 09/11] v210enc: switch to PIX_FMT_422P10 Signed-off-by: Anton Khirnov --- libavcodec/v210enc.c | 20 +++++++++----------- 1 file changed, 9 insertions(+), 11 deletions(-) diff --git a/libavcodec/v210enc.c b/libavcodec/v210enc.c index 1f621d4907..808ab7d949 100644 --- a/libavcodec/v210enc.c +++ b/libavcodec/v210enc.c @@ -31,8 +31,8 @@ static av_cold int encode_init(AVCodecContext *avctx) return -1; } - if (avctx->pix_fmt != PIX_FMT_YUV422P16) { - av_log(avctx, AV_LOG_ERROR, "v210 needs YUV422P16\n"); + if (avctx->pix_fmt != PIX_FMT_YUV422P10) { + av_log(avctx, AV_LOG_ERROR, "v210 needs YUV422P10\n"); return -1; } @@ -68,9 +68,9 @@ static int encode_frame(AVCodecContext *avctx, unsigned char *buf, #define WRITE_PIXELS(a, b, c) \ do { \ - val = (*a++ >> 6) | \ - ((*b++ & 0xFFC0) << 4); \ - val|= (*c++ & 0xFFC0) << 14; \ + val = *a++; \ + val |= (*b++ << 10) | \ + (*c++ << 20); \ bytestream_put_le32(&p, val); \ } while (0) @@ -85,17 +85,15 @@ static int encode_frame(AVCodecContext *avctx, unsigned char *buf, if (w < avctx->width - 1) { WRITE_PIXELS(u, y, v); - val = *y++ >> 6; + val = *y++; if (w == avctx->width - 2) bytestream_put_le32(&p, val); } if (w < avctx->width - 3) { - val |=((*u++ & 0xFFC0) << 4) | - ((*y++ & 0xFFC0) << 14); + val |= (*u++ << 10) | (*y++ << 20); bytestream_put_le32(&p, val); - val = (*v++ >> 6) | - (*y++ & 0xFFC0) << 4; + val = *v++ | (*y++ << 10); bytestream_put_le32(&p, val); } @@ -124,6 +122,6 @@ AVCodec ff_v210_encoder = { .init = encode_init, .encode = encode_frame, .close = encode_close, - .pix_fmts = (const enum PixelFormat[]){PIX_FMT_YUV422P16, PIX_FMT_NONE}, + .pix_fmts = (const enum PixelFormat[]){PIX_FMT_YUV422P10, PIX_FMT_NONE}, .long_name = NULL_IF_CONFIG_SMALL("Uncompressed 4:2:2 10-bit"), }; From 635bbecfc300ae49461b8987e2ebbf200ec8d6b6 Mon Sep 17 00:00:00 2001 From: Baptiste Coudurier Date: Sun, 8 May 2011 17:58:20 +0200 Subject: [PATCH 10/11] v210enc: clip values according to specifications Signed-off-by: Anton Khirnov --- libavcodec/v210enc.c | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/libavcodec/v210enc.c b/libavcodec/v210enc.c index 808ab7d949..58613520a5 100644 --- a/libavcodec/v210enc.c +++ b/libavcodec/v210enc.c @@ -66,11 +66,13 @@ static int encode_frame(AVCodecContext *avctx, unsigned char *buf, return -1; } +#define CLIP(v) av_clip(v, 4, 1019) + #define WRITE_PIXELS(a, b, c) \ do { \ - val = *a++; \ - val |= (*b++ << 10) | \ - (*c++ << 20); \ + val = CLIP(*a++); \ + val |= (CLIP(*b++) << 10) | \ + (CLIP(*c++) << 20); \ bytestream_put_le32(&p, val); \ } while (0) @@ -85,15 +87,15 @@ static int encode_frame(AVCodecContext *avctx, unsigned char *buf, if (w < avctx->width - 1) { WRITE_PIXELS(u, y, v); - val = *y++; + val = CLIP(*y++); if (w == avctx->width - 2) bytestream_put_le32(&p, val); } if (w < avctx->width - 3) { - val |= (*u++ << 10) | (*y++ << 20); + val |= (CLIP(*u++) << 10) | (CLIP(*y++) << 20); bytestream_put_le32(&p, val); - val = *v++ | (*y++ << 10); + val = CLIP(*v++) | (CLIP(*y++) << 10); bytestream_put_le32(&p, val); } From 0ca36b4de76e10578e23199c2932682c0f510e31 Mon Sep 17 00:00:00 2001 From: Kieran Kunhya Date: Tue, 6 Sep 2011 20:05:27 +0100 Subject: [PATCH 11/11] Add LATM muxer Signed-off-by: Janne Grunau --- Changelog | 1 + doc/general.texi | 1 + libavcodec/Makefile | 1 + libavformat/Makefile | 1 + libavformat/allformats.c | 1 + libavformat/latmenc.c | 190 +++++++++++++++++++++++++++++++++++++++ libavformat/version.h | 2 +- 7 files changed, 196 insertions(+), 1 deletion(-) create mode 100644 libavformat/latmenc.c diff --git a/Changelog b/Changelog index 510de33e1e..8e9ed388d9 100644 --- a/Changelog +++ b/Changelog @@ -42,6 +42,7 @@ easier to use. The changes are: * -intra option was removed, it's equivalent to -g 0. - XMV demuxer - Windows Media Image decoder +- LATM muxer version 0.7: diff --git a/doc/general.texi b/doc/general.texi index 2a11f81b2a..50278e1eee 100644 --- a/doc/general.texi +++ b/doc/general.texi @@ -118,6 +118,7 @@ library: @tab A format generated by IndigoVision 8000 video server. @item IVF (On2) @tab X @tab X @tab A format used by libvpx +@item LATM @tab X @tab X @item LMLM4 @tab @tab X @tab Used by Linux Media Labs MPEG-4 PCI boards @item LXF @tab @tab X diff --git a/libavcodec/Makefile b/libavcodec/Makefile index 2264e86b7d..1bb6b090cc 100644 --- a/libavcodec/Makefile +++ b/libavcodec/Makefile @@ -531,6 +531,7 @@ OBJS-$(CONFIG_FLAC_MUXER) += flacdec.o flacdata.o flac.o OBJS-$(CONFIG_FLV_DEMUXER) += mpeg4audio.o OBJS-$(CONFIG_GXF_DEMUXER) += mpeg12data.o OBJS-$(CONFIG_IFF_DEMUXER) += iff.o +OBJS-$(CONFIG_LATM_MUXER) += mpeg4audio.o OBJS-$(CONFIG_MATROSKA_AUDIO_MUXER) += xiph.o mpeg4audio.o \ flacdec.o flacdata.o flac.o OBJS-$(CONFIG_MATROSKA_DEMUXER) += mpeg4audio.o mpegaudiodata.o diff --git a/libavformat/Makefile b/libavformat/Makefile index 3f84019eb8..06c2027692 100644 --- a/libavformat/Makefile +++ b/libavformat/Makefile @@ -109,6 +109,7 @@ OBJS-$(CONFIG_IV8_DEMUXER) += iv8.o OBJS-$(CONFIG_IVF_DEMUXER) += ivfdec.o riff.o OBJS-$(CONFIG_IVF_MUXER) += ivfenc.o OBJS-$(CONFIG_JV_DEMUXER) += jvdec.o +OBJS-$(CONFIG_LATM_MUXER) += latmenc.o OBJS-$(CONFIG_LMLM4_DEMUXER) += lmlm4.o OBJS-$(CONFIG_LXF_DEMUXER) += lxfdec.o OBJS-$(CONFIG_M4V_DEMUXER) += m4vdec.o rawdec.o diff --git a/libavformat/allformats.c b/libavformat/allformats.c index 17c07a28e0..d640340cec 100644 --- a/libavformat/allformats.c +++ b/libavformat/allformats.c @@ -113,6 +113,7 @@ void av_register_all(void) REGISTER_DEMUXER (IV8, iv8); REGISTER_MUXDEMUX (IVF, ivf); REGISTER_DEMUXER (JV, jv); + REGISTER_MUXER (LATM, latm); REGISTER_DEMUXER (LMLM4, lmlm4); REGISTER_DEMUXER (LXF, lxf); REGISTER_MUXDEMUX (M4V, m4v); diff --git a/libavformat/latmenc.c b/libavformat/latmenc.c new file mode 100644 index 0000000000..8d67b5a615 --- /dev/null +++ b/libavformat/latmenc.c @@ -0,0 +1,190 @@ +/* + * LATM/LOAS muxer + * Copyright (c) 2011 Kieran Kunhya + * + * This file is part of Libav. + * + * Libav is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * Libav is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with Libav; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include "libavcodec/get_bits.h" +#include "libavcodec/put_bits.h" +#include "libavcodec/avcodec.h" +#include "libavcodec/mpeg4audio.h" +#include "libavutil/opt.h" +#include "avformat.h" + +typedef struct { + int off; + int channel_conf; + int object_type; + int counter; + int mod; +} LATMContext; + +static const AVOption options[] = { + {"smc-interval", "StreamMuxConfig interval.", + offsetof(LATMContext, mod), FF_OPT_TYPE_INT, {.dbl = 0x0014}, 0x0001, 0xffff, AV_OPT_FLAG_ENCODING_PARAM}, + {NULL}, +}; + +static const AVClass latm_muxer_class = { + .class_name = "LATM/LOAS muxer", + .item_name = av_default_item_name, + .option = options, + .version = LIBAVUTIL_VERSION_INT, +}; + +static int latm_decode_extradata(LATMContext *ctx, uint8_t *buf, int size) +{ + GetBitContext gb; + MPEG4AudioConfig m4ac; + + init_get_bits(&gb, buf, size * 8); + ctx->off = ff_mpeg4audio_get_config(&m4ac, buf, size); + if (ctx->off < 0) + return ctx->off; + skip_bits_long(&gb, ctx->off); + + /* FIXME: are any formats not allowed in LATM? */ + + if (m4ac.object_type > AOT_SBR && m4ac.object_type != AOT_ALS) { + av_log(ctx, AV_LOG_ERROR, "Muxing MPEG-4 AOT %d in LATM is not supported\n", m4ac.object_type); + return AVERROR_INVALIDDATA; + } + ctx->channel_conf = m4ac.chan_config; + ctx->object_type = m4ac.object_type; + + return 0; +} + +static int latm_write_header(AVFormatContext *s) +{ + LATMContext *ctx = s->priv_data; + AVCodecContext *avctx = s->streams[0]->codec; + + if (avctx->extradata_size > 0 && + latm_decode_extradata(ctx, avctx->extradata, avctx->extradata_size) < 0) + return AVERROR_INVALIDDATA; + + return 0; +} + +static int latm_write_frame_header(AVFormatContext *s, PutBitContext *bs) +{ + LATMContext *ctx = s->priv_data; + AVCodecContext *avctx = s->streams[0]->codec; + GetBitContext gb; + int header_size; + + /* AudioMuxElement */ + put_bits(bs, 1, !!ctx->counter); + + if (!ctx->counter) { + init_get_bits(&gb, avctx->extradata, avctx->extradata_size * 8); + + /* StreamMuxConfig */ + put_bits(bs, 1, 0); /* audioMuxVersion */ + put_bits(bs, 1, 1); /* allStreamsSameTimeFraming */ + put_bits(bs, 6, 0); /* numSubFrames */ + put_bits(bs, 4, 0); /* numProgram */ + put_bits(bs, 3, 0); /* numLayer */ + + /* AudioSpecificConfig */ + if (ctx->object_type == AOT_ALS) { + header_size = avctx->extradata_size-(ctx->off + 7) >> 3; + ff_copy_bits(bs, &avctx->extradata[ctx->off], header_size); + } else { + ff_copy_bits(bs, avctx->extradata, ctx->off + 3); + + if (!ctx->channel_conf) { + ff_copy_pce_data(bs, &gb); + } + } + + put_bits(bs, 3, 0); /* frameLengthType */ + put_bits(bs, 8, 0); /* latmBufferFullness */ + + put_bits(bs, 1, 0); /* otherDataPresent */ + put_bits(bs, 1, 0); /* crcCheckPresent */ + } + + ctx->counter++; + ctx->counter %= ctx->mod; + + return 0; +} + +static int latm_write_packet(AVFormatContext *s, AVPacket *pkt) +{ + AVIOContext *pb = s->pb; + PutBitContext bs; + int i, len; + uint8_t loas_header[] = "\x56\xe0\x00"; + uint8_t *buf; + + if (pkt->size > 2 && pkt->data[0] == 0xff && (pkt->data[1] >> 4) == 0xf) { + av_log(s, AV_LOG_ERROR, "ADTS header detected - ADTS will not be incorrectly muxed into LATM\n"); + return AVERROR_INVALIDDATA; + } + + buf = av_malloc(pkt->size+1024); + if (!buf) + return AVERROR(ENOMEM); + + init_put_bits(&bs, buf, pkt->size+1024); + + latm_write_frame_header(s, &bs); + + /* PayloadLengthInfo() */ + for (i = 0; i <= pkt->size-255; i+=255) + put_bits(&bs, 8, 255); + + put_bits(&bs, 8, pkt->size-i); + + /* The LATM payload is written unaligned */ + + /* PayloadMux() */ + for (i = 0; i < pkt->size; i++) + put_bits(&bs, 8, pkt->data[i]); + + align_put_bits(&bs); + flush_put_bits(&bs); + + len = put_bits_count(&bs) >> 3; + + loas_header[1] |= (len >> 8) & 0x1f; + loas_header[2] |= len & 0xff; + + avio_write(pb, loas_header, 3); + avio_write(pb, buf, len); + + av_free(buf); + + return 0; +} + +AVOutputFormat ff_latm_muxer = { + .name = "latm", + .long_name = NULL_IF_CONFIG_SMALL("LOAS/LATM"), + .mime_type = "audio/MP4A-LATM", + .extensions = "latm", + .priv_data_size = sizeof(LATMContext), + .audio_codec = CODEC_ID_AAC, + .video_codec = CODEC_ID_NONE, + .write_header = latm_write_header, + .write_packet = latm_write_packet, + .priv_class = &latm_muxer_class, +}; diff --git a/libavformat/version.h b/libavformat/version.h index f952967f5d..2d64826e32 100644 --- a/libavformat/version.h +++ b/libavformat/version.h @@ -24,7 +24,7 @@ #include "libavutil/avutil.h" #define LIBAVFORMAT_VERSION_MAJOR 53 -#define LIBAVFORMAT_VERSION_MINOR 6 +#define LIBAVFORMAT_VERSION_MINOR 7 #define LIBAVFORMAT_VERSION_MICRO 0 #define LIBAVFORMAT_VERSION_INT AV_VERSION_INT(LIBAVFORMAT_VERSION_MAJOR, \