X-Git-Url: https://git.sesse.net/?a=blobdiff_plain;f=libavcodec%2Fmpeg12enc.c;h=f246427eeb320c02838708da3a24292f707a8c4b;hb=60e7021064ea9e99854c585d452e89f38635480e;hp=d0b458e34bdb492992358d0b6465f885e08f556b;hpb=f3881c04e93ee70567bd3fe087f49b996b026d30;p=ffmpeg diff --git a/libavcodec/mpeg12enc.c b/libavcodec/mpeg12enc.c index d0b458e34bd..f246427eeb3 100644 --- a/libavcodec/mpeg12enc.c +++ b/libavcodec/mpeg12enc.c @@ -41,6 +41,7 @@ #include "mpeg12data.h" #include "mpegutils.h" #include "mpegvideo.h" +#include "profiles.h" static const uint8_t svcd_scan_offset_placeholder[] = { 0x10, 0x0E, 0x00, 0x80, 0x81, 0x00, 0x80, @@ -61,6 +62,8 @@ static uint32_t mpeg1_chr_dc_uni[512]; static uint8_t mpeg1_index_run[2][64]; static int8_t mpeg1_max_level[2][64]; +#define A53_MAX_CC_COUNT 0x1f + static av_cold void init_uni_ac_vlc(RLTable *rl, uint8_t *uni_ac_vlc_len) { int i; @@ -137,16 +140,17 @@ static int find_frame_rate_index(MpegEncContext *s) static av_cold int encode_init(AVCodecContext *avctx) { + int ret; MpegEncContext *s = avctx->priv_data; - if (ff_mpv_encode_init(avctx) < 0) - return -1; + if ((ret = ff_mpv_encode_init(avctx)) < 0) + return ret; if (find_frame_rate_index(s) < 0) { if (s->strict_std_compliance > FF_COMPLIANCE_EXPERIMENTAL) { av_log(avctx, AV_LOG_ERROR, "MPEG-1/2 does not support %d/%d fps\n", avctx->time_base.den, avctx->time_base.num); - return -1; + return AVERROR(EINVAL); } else { av_log(avctx, AV_LOG_INFO, "MPEG-1/2 does not support %d/%d fps, there may be AV sync issues\n", @@ -157,23 +161,23 @@ static av_cold int encode_init(AVCodecContext *avctx) if (avctx->profile == FF_PROFILE_UNKNOWN) { if (avctx->level != FF_LEVEL_UNKNOWN) { av_log(avctx, AV_LOG_ERROR, "Set profile and level\n"); - return -1; + return AVERROR(EINVAL); } /* Main or 4:2:2 */ - avctx->profile = s->chroma_format == CHROMA_420 ? 4 : 0; + avctx->profile = s->chroma_format == CHROMA_420 ? FF_PROFILE_MPEG2_MAIN : FF_PROFILE_MPEG2_422; } if (avctx->level == FF_LEVEL_UNKNOWN) { - if (avctx->profile == 0) { /* 4:2:2 */ + if (avctx->profile == FF_PROFILE_MPEG2_422) { /* 4:2:2 */ if (avctx->width <= 720 && avctx->height <= 608) avctx->level = 5; /* Main */ else avctx->level = 2; /* High */ } else { - if (avctx->profile != 1 && s->chroma_format != CHROMA_420) { + if (avctx->profile != FF_PROFILE_MPEG2_HIGH && s->chroma_format != CHROMA_420) { av_log(avctx, AV_LOG_ERROR, "Only High(1) and 4:2:2(0) profiles support 4:2:2 color sampling\n"); - return -1; + return AVERROR(EINVAL); } if (avctx->width <= 720 && avctx->height <= 576) avctx->level = 8; /* Main */ @@ -203,7 +207,7 @@ static av_cold int encode_init(AVCodecContext *avctx) if (s->drop_frame_timecode && s->frame_rate_index != 4) { av_log(avctx, AV_LOG_ERROR, "Drop frame time code only allowed with 1001/30000 fps\n"); - return -1; + return AVERROR(EINVAL); } #if FF_API_PRIVATE_OPT @@ -319,7 +323,7 @@ static void mpeg1_encode_sequence_header(MpegEncContext *s) put_header(s, EXT_START_CODE); put_bits(&s->pb, 4, 1); // seq ext - put_bits(&s->pb, 1, s->avctx->profile == 0); // escx 1 for 4:2:2 profile + put_bits(&s->pb, 1, s->avctx->profile == FF_PROFILE_MPEG2_422); // escx 1 for 4:2:2 profile put_bits(&s->pb, 3, s->avctx->profile); // profile put_bits(&s->pb, 4, s->avctx->level); // level @@ -544,6 +548,36 @@ void ff_mpeg1_encode_picture_header(MpegEncContext *s, int picture_number) } } + if (s->codec_id == AV_CODEC_ID_MPEG2VIDEO && s->a53_cc) { + side_data = av_frame_get_side_data(s->current_picture_ptr->f, + AV_FRAME_DATA_A53_CC); + if (side_data) { + if (side_data->size <= A53_MAX_CC_COUNT * 3 && side_data->size % 3 == 0) { + int i = 0; + + put_header (s, USER_START_CODE); + + put_bits(&s->pb, 8, 'G'); // user_identifier + put_bits(&s->pb, 8, 'A'); + put_bits(&s->pb, 8, '9'); + put_bits(&s->pb, 8, '4'); + put_bits(&s->pb, 8, 3); // user_data_type_code + put_bits(&s->pb, 8, + (side_data->size / 3 & A53_MAX_CC_COUNT) | 0x40); // flags, cc_count + put_bits(&s->pb, 8, 0xff); // em_data + + for (i = 0; i < side_data->size; i++) + put_bits(&s->pb, 8, side_data->data[i]); + + put_bits(&s->pb, 8, 0xff); // marker_bits + } else { + av_log(s->avctx, AV_LOG_WARNING, + "Warning Closed Caption size (%d) can not exceed 93 bytes " + "and must be a multiple of 3\n", side_data->size); + } + } + } + s->mb_y = 0; ff_mpeg1_encode_slice_header(s); } @@ -1102,7 +1136,7 @@ av_cold void ff_mpeg1_encode_init(MpegEncContext *s) #define VE AV_OPT_FLAG_ENCODING_PARAM | AV_OPT_FLAG_VIDEO_PARAM #define COMMON_OPTS \ { "gop_timecode", "MPEG GOP Timecode in hh:mm:ss[:;.]ff format. Overrides timecode_frame_start.", \ - OFFSET(tc_opt_str), AV_OPT_TYPE_STRING, {.str=NULL}, CHAR_MIN, CHAR_MAX, VE },\ + OFFSET(tc_opt_str), AV_OPT_TYPE_STRING, {.str=NULL}, 0, 0, VE },\ { "intra_vlc", "Use MPEG-2 intra VLC table.", \ OFFSET(intra_vlc_format), AV_OPT_TYPE_BOOL, { .i64 = 0 }, 0, 1, VE }, \ { "drop_frame_timecode", "Timecode is in drop frame format.", \ @@ -1133,7 +1167,14 @@ static const AVOption mpeg2_options[] = { { "secam", NULL, 0, AV_OPT_TYPE_CONST, {.i64 = VIDEO_FORMAT_SECAM }, 0, 0, VE, "video_format" }, { "mac", NULL, 0, AV_OPT_TYPE_CONST, {.i64 = VIDEO_FORMAT_MAC }, 0, 0, VE, "video_format" }, { "unspecified", NULL, 0, AV_OPT_TYPE_CONST, {.i64 = VIDEO_FORMAT_UNSPECIFIED}, 0, 0, VE, "video_format" }, +#define LEVEL(name, value) name, NULL, 0, AV_OPT_TYPE_CONST, { .i64 = value }, 0, 0, VE, "avctx.level" + { LEVEL("high", 4) }, + { LEVEL("high1440", 6) }, + { LEVEL("main", 8) }, + { LEVEL("low", 10) }, +#undef LEVEL FF_MPV_COMMON_OPTS + FF_MPEG2_PROFILE_OPTS { NULL }, }; @@ -1161,6 +1202,7 @@ AVCodec ff_mpeg1video_encoder = { .pix_fmts = (const enum AVPixelFormat[]) { AV_PIX_FMT_YUV420P, AV_PIX_FMT_NONE }, .capabilities = AV_CODEC_CAP_DELAY | AV_CODEC_CAP_SLICE_THREADS, + .caps_internal = FF_CODEC_CAP_INIT_CLEANUP, .priv_class = &mpeg1_class, }; @@ -1178,5 +1220,6 @@ AVCodec ff_mpeg2video_encoder = { AV_PIX_FMT_YUV422P, AV_PIX_FMT_NONE }, .capabilities = AV_CODEC_CAP_DELAY | AV_CODEC_CAP_SLICE_THREADS, + .caps_internal = FF_CODEC_CAP_INIT_CLEANUP, .priv_class = &mpeg2_class, };