1
0
mirror of https://github.com/FFmpeg/FFmpeg.git synced 2025-08-04 22:03:09 +02:00

avcodec/mpeg12enc: Move encode_init() to the end of the file

Will avoid forward declarations later.

Signed-off-by: Andreas Rheinhardt <andreas.rheinhardt@outlook.com>
This commit is contained in:
Andreas Rheinhardt
2025-03-03 18:11:10 +01:00
parent edebd1d9a4
commit 34557b1d30

View File

@ -137,155 +137,6 @@ av_cold void ff_mpeg1_init_uni_ac_vlc(const int8_t max_level[],
}
#if CONFIG_MPEG1VIDEO_ENCODER || CONFIG_MPEG2VIDEO_ENCODER
static int find_frame_rate_index(AVCodecContext *avctx, MPEG12EncContext *mpeg12)
{
int i;
AVRational bestq = (AVRational) {0, 0};
AVRational ext;
AVRational target = av_inv_q(avctx->time_base);
for (i = 1; i < 14; i++) {
if (avctx->strict_std_compliance > FF_COMPLIANCE_UNOFFICIAL &&
i >= 9)
break;
for (ext.num=1; ext.num <= 4; ext.num++) {
for (ext.den=1; ext.den <= 32; ext.den++) {
AVRational q = av_mul_q(ext, ff_mpeg12_frame_rate_tab[i]);
if (avctx->codec_id != AV_CODEC_ID_MPEG2VIDEO && (ext.den!=1 || ext.num!=1))
continue;
if (av_gcd(ext.den, ext.num) != 1)
continue;
if ( bestq.num==0
|| av_nearer_q(target, bestq, q) < 0
|| ext.num==1 && ext.den==1 && av_nearer_q(target, bestq, q) == 0) {
bestq = q;
mpeg12->frame_rate_index = i;
mpeg12->frame_rate_ext.num = ext.num;
mpeg12->frame_rate_ext.den = ext.den;
}
}
}
}
if (av_cmp_q(target, bestq))
return -1;
else
return 0;
}
static av_cold int encode_init(AVCodecContext *avctx)
{
MPEG12EncContext *const mpeg12 = avctx->priv_data;
int ret;
int max_size = avctx->codec_id == AV_CODEC_ID_MPEG2VIDEO ? 16383 : 4095;
if (avctx->width > max_size || avctx->height > max_size) {
av_log(avctx, AV_LOG_ERROR, "%s does not support resolutions above %dx%d\n",
CONFIG_SMALL ? avctx->codec->name : avctx->codec->long_name,
max_size, max_size);
return AVERROR(EINVAL);
}
if ((avctx->width & 0xFFF) == 0 && (avctx->height & 0xFFF) == 1) {
av_log(avctx, AV_LOG_ERROR, "Width / Height is invalid for MPEG2\n");
return AVERROR(EINVAL);
}
if (avctx->strict_std_compliance > FF_COMPLIANCE_UNOFFICIAL) {
if ((avctx->width & 0xFFF) == 0 || (avctx->height & 0xFFF) == 0) {
av_log(avctx, AV_LOG_ERROR, "Width or Height are not allowed to be multiples of 4096\n"
"add '-strict %d' if you want to use them anyway.\n", FF_COMPLIANCE_UNOFFICIAL);
return AVERROR(EINVAL);
}
}
if (mpeg12->mpeg.s.q_scale_type == 1) {
if (avctx->qmax > 28) {
av_log(avctx, AV_LOG_ERROR,
"non linear quant only supports qmax <= 28 currently\n");
return AVERROR_PATCHWELCOME;
}
}
if (avctx->profile == AV_PROFILE_UNKNOWN) {
if (avctx->level != AV_LEVEL_UNKNOWN) {
av_log(avctx, AV_LOG_ERROR, "Set profile and level\n");
return AVERROR(EINVAL);
}
/* Main or 4:2:2 */
avctx->profile = avctx->pix_fmt == AV_PIX_FMT_YUV420P ? AV_PROFILE_MPEG2_MAIN
: AV_PROFILE_MPEG2_422;
}
if (avctx->level == AV_LEVEL_UNKNOWN) {
if (avctx->profile == AV_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 != AV_PROFILE_MPEG2_HIGH &&
avctx->pix_fmt != AV_PIX_FMT_YUV420P) {
av_log(avctx, AV_LOG_ERROR,
"Only High(1) and 4:2:2(0) profiles support 4:2:2 color sampling\n");
return AVERROR(EINVAL);
}
if (avctx->width <= 720 && avctx->height <= 576)
avctx->level = 8; /* Main */
else if (avctx->width <= 1440)
avctx->level = 6; /* High 1440 */
else
avctx->level = 4; /* High */
}
}
if ((ret = ff_mpv_encode_init(avctx)) < 0)
return ret;
if (find_frame_rate_index(avctx, mpeg12) < 0) {
if (avctx->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 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",
avctx->time_base.den, avctx->time_base.num);
}
}
if (avctx->rc_max_rate &&
avctx->rc_min_rate == avctx->rc_max_rate &&
90000LL * (avctx->rc_buffer_size - 1) >
avctx->rc_max_rate * 0xFFFFLL) {
av_log(avctx, AV_LOG_INFO,
"Warning vbv_delay will be set to 0xFFFF (=VBR) as the "
"specified vbv buffer is too large for the given bitrate!\n");
}
if (mpeg12->drop_frame_timecode)
mpeg12->tc.flags |= AV_TIMECODE_FLAG_DROPFRAME;
if (mpeg12->drop_frame_timecode && mpeg12->frame_rate_index != 4) {
av_log(avctx, AV_LOG_ERROR,
"Drop frame time code only allowed with 1001/30000 fps\n");
return AVERROR(EINVAL);
}
if (mpeg12->tc_opt_str) {
AVRational rate = ff_mpeg12_frame_rate_tab[mpeg12->frame_rate_index];
int ret = av_timecode_init_from_string(&mpeg12->tc, rate, mpeg12->tc_opt_str, avctx);
if (ret < 0)
return ret;
mpeg12->drop_frame_timecode = !!(mpeg12->tc.flags & AV_TIMECODE_FLAG_DROPFRAME);
mpeg12->timecode_frame_start = mpeg12->tc.start;
} else {
mpeg12->timecode_frame_start = 0; // default is -1
}
return 0;
}
static void put_header(MpegEncContext *s, uint32_t header)
{
align_put_bits(&s->pb);
@ -1179,6 +1030,155 @@ av_cold void ff_mpeg1_encode_init(MpegEncContext *s)
ff_thread_once(&init_static_once, mpeg12_encode_init_static);
}
static av_cold int find_frame_rate_index(AVCodecContext *avctx, MPEG12EncContext *mpeg12)
{
AVRational bestq = (AVRational) {0, 0};
AVRational ext;
AVRational target = av_inv_q(avctx->time_base);
for (int i = 1; i < 14; i++) {
if (avctx->strict_std_compliance > FF_COMPLIANCE_UNOFFICIAL &&
i >= 9)
break;
for (ext.num = 1; ext.num <= 4; ext.num++) {
for (ext.den = 1; ext.den <= 32; ext.den++) {
AVRational q = av_mul_q(ext, ff_mpeg12_frame_rate_tab[i]);
if (avctx->codec_id != AV_CODEC_ID_MPEG2VIDEO && (ext.den!=1 || ext.num!=1))
continue;
if (av_gcd(ext.den, ext.num) != 1)
continue;
if ( bestq.num==0
|| av_nearer_q(target, bestq, q) < 0
|| ext.num==1 && ext.den==1 && av_nearer_q(target, bestq, q) == 0) {
bestq = q;
mpeg12->frame_rate_index = i;
mpeg12->frame_rate_ext.num = ext.num;
mpeg12->frame_rate_ext.den = ext.den;
}
}
}
}
if (av_cmp_q(target, bestq))
return -1;
else
return 0;
}
static av_cold int encode_init(AVCodecContext *avctx)
{
MPEG12EncContext *const mpeg12 = avctx->priv_data;
int ret;
int max_size = avctx->codec_id == AV_CODEC_ID_MPEG2VIDEO ? 16383 : 4095;
if (avctx->width > max_size || avctx->height > max_size) {
av_log(avctx, AV_LOG_ERROR, "%s does not support resolutions above %dx%d\n",
CONFIG_SMALL ? avctx->codec->name : avctx->codec->long_name,
max_size, max_size);
return AVERROR(EINVAL);
}
if ((avctx->width & 0xFFF) == 0 && (avctx->height & 0xFFF) == 1) {
av_log(avctx, AV_LOG_ERROR, "Width / Height is invalid for MPEG2\n");
return AVERROR(EINVAL);
}
if (avctx->strict_std_compliance > FF_COMPLIANCE_UNOFFICIAL) {
if ((avctx->width & 0xFFF) == 0 || (avctx->height & 0xFFF) == 0) {
av_log(avctx, AV_LOG_ERROR, "Width or Height are not allowed to be multiples of 4096\n"
"add '-strict %d' if you want to use them anyway.\n", FF_COMPLIANCE_UNOFFICIAL);
return AVERROR(EINVAL);
}
}
if (mpeg12->mpeg.s.q_scale_type == 1) {
if (avctx->qmax > 28) {
av_log(avctx, AV_LOG_ERROR,
"non linear quant only supports qmax <= 28 currently\n");
return AVERROR_PATCHWELCOME;
}
}
if (avctx->profile == AV_PROFILE_UNKNOWN) {
if (avctx->level != AV_LEVEL_UNKNOWN) {
av_log(avctx, AV_LOG_ERROR, "Set profile and level\n");
return AVERROR(EINVAL);
}
/* Main or 4:2:2 */
avctx->profile = avctx->pix_fmt == AV_PIX_FMT_YUV420P ? AV_PROFILE_MPEG2_MAIN
: AV_PROFILE_MPEG2_422;
}
if (avctx->level == AV_LEVEL_UNKNOWN) {
if (avctx->profile == AV_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 != AV_PROFILE_MPEG2_HIGH &&
avctx->pix_fmt != AV_PIX_FMT_YUV420P) {
av_log(avctx, AV_LOG_ERROR,
"Only High(1) and 4:2:2(0) profiles support 4:2:2 color sampling\n");
return AVERROR(EINVAL);
}
if (avctx->width <= 720 && avctx->height <= 576)
avctx->level = 8; /* Main */
else if (avctx->width <= 1440)
avctx->level = 6; /* High 1440 */
else
avctx->level = 4; /* High */
}
}
ret = ff_mpv_encode_init(avctx);
if (ret < 0)
return ret;
if (find_frame_rate_index(avctx, mpeg12) < 0) {
if (avctx->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 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",
avctx->time_base.den, avctx->time_base.num);
}
}
if (avctx->rc_max_rate &&
avctx->rc_min_rate == avctx->rc_max_rate &&
90000LL * (avctx->rc_buffer_size - 1) >
avctx->rc_max_rate * 0xFFFFLL) {
av_log(avctx, AV_LOG_INFO,
"Warning vbv_delay will be set to 0xFFFF (=VBR) as the "
"specified vbv buffer is too large for the given bitrate!\n");
}
if (mpeg12->drop_frame_timecode)
mpeg12->tc.flags |= AV_TIMECODE_FLAG_DROPFRAME;
if (mpeg12->drop_frame_timecode && mpeg12->frame_rate_index != 4) {
av_log(avctx, AV_LOG_ERROR,
"Drop frame time code only allowed with 1001/30000 fps\n");
return AVERROR(EINVAL);
}
if (mpeg12->tc_opt_str) {
AVRational rate = ff_mpeg12_frame_rate_tab[mpeg12->frame_rate_index];
int ret = av_timecode_init_from_string(&mpeg12->tc, rate, mpeg12->tc_opt_str, avctx);
if (ret < 0)
return ret;
mpeg12->drop_frame_timecode = !!(mpeg12->tc.flags & AV_TIMECODE_FLAG_DROPFRAME);
mpeg12->timecode_frame_start = mpeg12->tc.start;
} else {
mpeg12->timecode_frame_start = 0; // default is -1
}
return 0;
}
#define OFFSET(x) offsetof(MPEG12EncContext, x)
#define VE AV_OPT_FLAG_ENCODING_PARAM | AV_OPT_FLAG_VIDEO_PARAM
#define COMMON_OPTS \