1
0
mirror of https://github.com/FFmpeg/FFmpeg.git synced 2024-12-23 12:43:46 +02:00
FFmpeg/libavcodec/mpeg12enc.c
Anton Khirnov 717503f716 put_bits: make avpriv_align_put_bits() inline
This function is so extremely simple that it is preferable to make it
inline rather than deal with all the complications arising from it being
an exported symbol.

Keep avpriv_align_put_bits() around until the next major bump to
preserve ABI compatibility.
2020-10-28 13:53:23 +01:00

1226 lines
48 KiB
C

/*
* MPEG-1/2 encoder
* Copyright (c) 2000,2001 Fabrice Bellard
* Copyright (c) 2002-2004 Michael Niedermayer <michaelni@gmx.at>
*
* This file is part of FFmpeg.
*
* FFmpeg 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.
*
* FFmpeg 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 FFmpeg; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
/**
* @file
* MPEG-1/2 encoder
*/
#include <stdint.h>
#include "libavutil/attributes.h"
#include "libavutil/avassert.h"
#include "libavutil/log.h"
#include "libavutil/opt.h"
#include "libavutil/timecode.h"
#include "libavutil/stereo3d.h"
#include "avcodec.h"
#include "bytestream.h"
#include "mathops.h"
#include "mpeg12.h"
#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,
0x81, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
};
static uint8_t mv_penalty[MAX_FCODE + 1][MAX_DMV * 2 + 1];
static uint8_t fcode_tab[MAX_MV * 2 + 1];
static uint8_t uni_mpeg1_ac_vlc_len[64 * 64 * 2];
static uint8_t uni_mpeg2_ac_vlc_len[64 * 64 * 2];
/* simple include everything table for dc, first byte is bits
* number next 3 are code */
static uint32_t mpeg1_lum_dc_uni[512];
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;
for (i = 0; i < 128; i++) {
int level = i - 64;
int run;
if (!level)
continue;
for (run = 0; run < 64; run++) {
int len, code;
int alevel = FFABS(level);
if (alevel > rl->max_level[0][run])
code = 111; /* rl->n */
else
code = rl->index_run[0][run] + alevel - 1;
if (code < 111) { /* rl->n */
/* length of VLC and sign */
len = rl->table_vlc[code][1] + 1;
} else {
len = rl->table_vlc[111 /* rl->n */][1] + 6;
if (alevel < 128)
len += 8;
else
len += 16;
}
uni_ac_vlc_len[UNI_AC_ENC_INDEX(run, i)] = len;
}
}
}
static int find_frame_rate_index(MpegEncContext *s)
{
int i;
AVRational bestq = (AVRational) {0, 0};
AVRational ext;
AVRational target = av_inv_q(s->avctx->time_base);
for (i = 1; i < 14; i++) {
if (s->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 (s->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;
s->frame_rate_index = i;
s->mpeg2_frame_rate_ext.num = ext.num;
s->mpeg2_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)
{
int ret;
MpegEncContext *s = avctx->priv_data;
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 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->profile == FF_PROFILE_UNKNOWN) {
if (avctx->level != FF_LEVEL_UNKNOWN) {
av_log(avctx, AV_LOG_ERROR, "Set profile and level\n");
return AVERROR(EINVAL);
}
/* Main or 4:2:2 */
avctx->profile = s->chroma_format == CHROMA_420 ? FF_PROFILE_MPEG2_MAIN : FF_PROFILE_MPEG2_422;
}
if (avctx->level == FF_LEVEL_UNKNOWN) {
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 != 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 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 ((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 (s->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);
}
}
s->drop_frame_timecode = s->drop_frame_timecode || !!(avctx->flags2 & AV_CODEC_FLAG2_DROP_FRAME_TIMECODE);
if (s->drop_frame_timecode)
s->tc.flags |= AV_TIMECODE_FLAG_DROPFRAME;
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 AVERROR(EINVAL);
}
#if FF_API_PRIVATE_OPT
FF_DISABLE_DEPRECATION_WARNINGS
if (avctx->timecode_frame_start)
s->timecode_frame_start = avctx->timecode_frame_start;
FF_ENABLE_DEPRECATION_WARNINGS
#endif
if (s->tc_opt_str) {
AVRational rate = ff_mpeg12_frame_rate_tab[s->frame_rate_index];
int ret = av_timecode_init_from_string(&s->tc, rate, s->tc_opt_str, s);
if (ret < 0)
return ret;
s->drop_frame_timecode = !!(s->tc.flags & AV_TIMECODE_FLAG_DROPFRAME);
s->timecode_frame_start = s->tc.start;
} else {
s->timecode_frame_start = 0; // default is -1
}
return 0;
}
static void put_header(MpegEncContext *s, int header)
{
align_put_bits(&s->pb);
put_bits(&s->pb, 16, header >> 16);
put_sbits(&s->pb, 16, header);
}
/* put sequence header if needed */
static void mpeg1_encode_sequence_header(MpegEncContext *s)
{
unsigned int vbv_buffer_size, fps, v;
int i, constraint_parameter_flag;
uint64_t time_code;
int64_t best_aspect_error = INT64_MAX;
AVRational aspect_ratio = s->avctx->sample_aspect_ratio;
if (aspect_ratio.num == 0 || aspect_ratio.den == 0)
aspect_ratio = (AVRational){1,1}; // pixel aspect 1.1 (VGA)
if (s->current_picture.f->key_frame) {
AVRational framerate = ff_mpeg12_frame_rate_tab[s->frame_rate_index];
/* MPEG-1 header repeated every GOP */
put_header(s, SEQ_START_CODE);
put_sbits(&s->pb, 12, s->width & 0xFFF);
put_sbits(&s->pb, 12, s->height & 0xFFF);
for (i = 1; i < 15; i++) {
int64_t error = aspect_ratio.num * (1LL<<32) / aspect_ratio.den;
if (s->codec_id == AV_CODEC_ID_MPEG1VIDEO || i <= 1)
error -= (1LL<<32) / ff_mpeg1_aspect[i];
else
error -= (1LL<<32)*ff_mpeg2_aspect[i].num * s->height / s->width / ff_mpeg2_aspect[i].den;
error = FFABS(error);
if (error - 2 <= best_aspect_error) {
best_aspect_error = error;
s->aspect_ratio_info = i;
}
}
put_bits(&s->pb, 4, s->aspect_ratio_info);
put_bits(&s->pb, 4, s->frame_rate_index);
if (s->avctx->rc_max_rate) {
v = (s->avctx->rc_max_rate + 399) / 400;
if (v > 0x3ffff && s->codec_id == AV_CODEC_ID_MPEG1VIDEO)
v = 0x3ffff;
} else {
v = 0x3FFFF;
}
if (s->avctx->rc_buffer_size)
vbv_buffer_size = s->avctx->rc_buffer_size;
else
/* VBV calculation: Scaled so that a VCD has the proper
* VBV size of 40 kilobytes */
vbv_buffer_size = ((20 * s->bit_rate) / (1151929 / 2)) * 8 * 1024;
vbv_buffer_size = (vbv_buffer_size + 16383) / 16384;
put_sbits(&s->pb, 18, v);
put_bits(&s->pb, 1, 1); // marker
put_sbits(&s->pb, 10, vbv_buffer_size);
constraint_parameter_flag =
s->width <= 768 &&
s->height <= 576 &&
s->mb_width * s->mb_height <= 396 &&
s->mb_width * s->mb_height * framerate.num <= 396 * 25 * framerate.den &&
framerate.num <= framerate.den * 30 &&
s->avctx->me_range &&
s->avctx->me_range < 128 &&
vbv_buffer_size <= 20 &&
v <= 1856000 / 400 &&
s->codec_id == AV_CODEC_ID_MPEG1VIDEO;
put_bits(&s->pb, 1, constraint_parameter_flag);
ff_write_quant_matrix(&s->pb, s->avctx->intra_matrix);
ff_write_quant_matrix(&s->pb, s->avctx->inter_matrix);
if (s->codec_id == AV_CODEC_ID_MPEG2VIDEO) {
AVFrameSideData *side_data;
int width = s->width;
int height = s->height;
int use_seq_disp_ext;
put_header(s, EXT_START_CODE);
put_bits(&s->pb, 4, 1); // seq ext
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
put_bits(&s->pb, 1, s->progressive_sequence);
put_bits(&s->pb, 2, s->chroma_format);
put_bits(&s->pb, 2, s->width >> 12);
put_bits(&s->pb, 2, s->height >> 12);
put_bits(&s->pb, 12, v >> 18); // bitrate ext
put_bits(&s->pb, 1, 1); // marker
put_bits(&s->pb, 8, vbv_buffer_size >> 10); // vbv buffer ext
put_bits(&s->pb, 1, s->low_delay);
put_bits(&s->pb, 2, s->mpeg2_frame_rate_ext.num-1); // frame_rate_ext_n
put_bits(&s->pb, 5, s->mpeg2_frame_rate_ext.den-1); // frame_rate_ext_d
side_data = av_frame_get_side_data(s->current_picture_ptr->f, AV_FRAME_DATA_PANSCAN);
if (side_data) {
AVPanScan *pan_scan = (AVPanScan *)side_data->data;
if (pan_scan->width && pan_scan->height) {
width = pan_scan->width >> 4;
height = pan_scan->height >> 4;
}
}
use_seq_disp_ext = (width != s->width ||
height != s->height ||
s->avctx->color_primaries != AVCOL_PRI_UNSPECIFIED ||
s->avctx->color_trc != AVCOL_TRC_UNSPECIFIED ||
s->avctx->colorspace != AVCOL_SPC_UNSPECIFIED ||
s->video_format != VIDEO_FORMAT_UNSPECIFIED);
if (s->seq_disp_ext == 1 || (s->seq_disp_ext == -1 && use_seq_disp_ext)) {
put_header(s, EXT_START_CODE);
put_bits(&s->pb, 4, 2); // sequence display extension
put_bits(&s->pb, 3, s->video_format); // video_format
put_bits(&s->pb, 1, 1); // colour_description
put_bits(&s->pb, 8, s->avctx->color_primaries); // colour_primaries
put_bits(&s->pb, 8, s->avctx->color_trc); // transfer_characteristics
put_bits(&s->pb, 8, s->avctx->colorspace); // matrix_coefficients
put_bits(&s->pb, 14, width); // display_horizontal_size
put_bits(&s->pb, 1, 1); // marker_bit
put_bits(&s->pb, 14, height); // display_vertical_size
put_bits(&s->pb, 3, 0); // remaining 3 bits are zero padding
}
}
put_header(s, GOP_START_CODE);
put_bits(&s->pb, 1, s->drop_frame_timecode); // drop frame flag
/* time code: we must convert from the real frame rate to a
* fake MPEG frame rate in case of low frame rate */
fps = (framerate.num + framerate.den / 2) / framerate.den;
time_code = s->current_picture_ptr->f->coded_picture_number +
s->timecode_frame_start;
s->gop_picture_number = s->current_picture_ptr->f->coded_picture_number;
av_assert0(s->drop_frame_timecode == !!(s->tc.flags & AV_TIMECODE_FLAG_DROPFRAME));
if (s->drop_frame_timecode)
time_code = av_timecode_adjust_ntsc_framenum2(time_code, fps);
put_bits(&s->pb, 5, (uint32_t)((time_code / (fps * 3600)) % 24));
put_bits(&s->pb, 6, (uint32_t)((time_code / (fps * 60)) % 60));
put_bits(&s->pb, 1, 1);
put_bits(&s->pb, 6, (uint32_t)((time_code / fps) % 60));
put_bits(&s->pb, 6, (uint32_t)((time_code % fps)));
put_bits(&s->pb, 1, !!(s->avctx->flags & AV_CODEC_FLAG_CLOSED_GOP) || s->intra_only || !s->gop_picture_number);
put_bits(&s->pb, 1, 0); // broken link
}
}
static inline void encode_mb_skip_run(MpegEncContext *s, int run)
{
while (run >= 33) {
put_bits(&s->pb, 11, 0x008);
run -= 33;
}
put_bits(&s->pb, ff_mpeg12_mbAddrIncrTable[run][1],
ff_mpeg12_mbAddrIncrTable[run][0]);
}
static av_always_inline void put_qscale(MpegEncContext *s)
{
put_bits(&s->pb, 5, s->qscale);
}
void ff_mpeg1_encode_slice_header(MpegEncContext *s)
{
if (s->codec_id == AV_CODEC_ID_MPEG2VIDEO && s->height > 2800) {
put_header(s, SLICE_MIN_START_CODE + (s->mb_y & 127));
/* slice_vertical_position_extension */
put_bits(&s->pb, 3, s->mb_y >> 7);
} else {
put_header(s, SLICE_MIN_START_CODE + s->mb_y);
}
put_qscale(s);
/* slice extra information */
put_bits(&s->pb, 1, 0);
}
void ff_mpeg1_encode_picture_header(MpegEncContext *s, int picture_number)
{
AVFrameSideData *side_data;
mpeg1_encode_sequence_header(s);
/* MPEG-1 picture header */
put_header(s, PICTURE_START_CODE);
/* temporal reference */
// RAL: s->picture_number instead of s->fake_picture_number
put_bits(&s->pb, 10,
(s->picture_number - s->gop_picture_number) & 0x3ff);
put_bits(&s->pb, 3, s->pict_type);
s->vbv_delay_ptr = s->pb.buf + put_bits_count(&s->pb) / 8;
put_bits(&s->pb, 16, 0xFFFF); /* vbv_delay */
// RAL: Forward f_code also needed for B-frames
if (s->pict_type == AV_PICTURE_TYPE_P ||
s->pict_type == AV_PICTURE_TYPE_B) {
put_bits(&s->pb, 1, 0); /* half pel coordinates */
if (s->codec_id == AV_CODEC_ID_MPEG1VIDEO)
put_bits(&s->pb, 3, s->f_code); /* forward_f_code */
else
put_bits(&s->pb, 3, 7); /* forward_f_code */
}
// RAL: Backward f_code necessary for B-frames
if (s->pict_type == AV_PICTURE_TYPE_B) {
put_bits(&s->pb, 1, 0); /* half pel coordinates */
if (s->codec_id == AV_CODEC_ID_MPEG1VIDEO)
put_bits(&s->pb, 3, s->b_code); /* backward_f_code */
else
put_bits(&s->pb, 3, 7); /* backward_f_code */
}
put_bits(&s->pb, 1, 0); /* extra bit picture */
s->frame_pred_frame_dct = 1;
if (s->codec_id == AV_CODEC_ID_MPEG2VIDEO) {
put_header(s, EXT_START_CODE);
put_bits(&s->pb, 4, 8); /* pic ext */
if (s->pict_type == AV_PICTURE_TYPE_P ||
s->pict_type == AV_PICTURE_TYPE_B) {
put_bits(&s->pb, 4, s->f_code);
put_bits(&s->pb, 4, s->f_code);
} else {
put_bits(&s->pb, 8, 255);
}
if (s->pict_type == AV_PICTURE_TYPE_B) {
put_bits(&s->pb, 4, s->b_code);
put_bits(&s->pb, 4, s->b_code);
} else {
put_bits(&s->pb, 8, 255);
}
put_bits(&s->pb, 2, s->intra_dc_precision);
av_assert0(s->picture_structure == PICT_FRAME);
put_bits(&s->pb, 2, s->picture_structure);
if (s->progressive_sequence)
put_bits(&s->pb, 1, 0); /* no repeat */
else
put_bits(&s->pb, 1, s->current_picture_ptr->f->top_field_first);
/* XXX: optimize the generation of this flag with entropy measures */
s->frame_pred_frame_dct = s->progressive_sequence;
put_bits(&s->pb, 1, s->frame_pred_frame_dct);
put_bits(&s->pb, 1, s->concealment_motion_vectors);
put_bits(&s->pb, 1, s->q_scale_type);
put_bits(&s->pb, 1, s->intra_vlc_format);
put_bits(&s->pb, 1, s->alternate_scan);
put_bits(&s->pb, 1, s->repeat_first_field);
s->progressive_frame = s->progressive_sequence;
/* chroma_420_type */
put_bits(&s->pb, 1, s->chroma_format ==
CHROMA_420 ? s->progressive_frame : 0);
put_bits(&s->pb, 1, s->progressive_frame);
put_bits(&s->pb, 1, 0); /* composite_display_flag */
}
if (s->scan_offset) {
int i;
put_header(s, USER_START_CODE);
for (i = 0; i < sizeof(svcd_scan_offset_placeholder); i++)
put_bits(&s->pb, 8, svcd_scan_offset_placeholder[i]);
}
side_data = av_frame_get_side_data(s->current_picture_ptr->f,
AV_FRAME_DATA_STEREO3D);
if (side_data) {
AVStereo3D *stereo = (AVStereo3D *)side_data->data;
uint8_t fpa_type;
switch (stereo->type) {
case AV_STEREO3D_SIDEBYSIDE:
fpa_type = 0x03;
break;
case AV_STEREO3D_TOPBOTTOM:
fpa_type = 0x04;
break;
case AV_STEREO3D_2D:
fpa_type = 0x08;
break;
case AV_STEREO3D_SIDEBYSIDE_QUINCUNX:
fpa_type = 0x23;
break;
default:
fpa_type = 0;
break;
}
if (fpa_type != 0) {
put_header(s, USER_START_CODE);
put_bits(&s->pb, 8, 'J'); // S3D_video_format_signaling_identifier
put_bits(&s->pb, 8, 'P');
put_bits(&s->pb, 8, '3');
put_bits(&s->pb, 8, 'D');
put_bits(&s->pb, 8, 0x03); // S3D_video_format_length
put_bits(&s->pb, 1, 1); // reserved_bit
put_bits(&s->pb, 7, fpa_type); // S3D_video_format_type
put_bits(&s->pb, 8, 0x04); // reserved_data[0]
put_bits(&s->pb, 8, 0xFF); // reserved_data[1]
}
}
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);
}
static inline void put_mb_modes(MpegEncContext *s, int n, int bits,
int has_mv, int field_motion)
{
put_bits(&s->pb, n, bits);
if (!s->frame_pred_frame_dct) {
if (has_mv)
/* motion_type: frame/field */
put_bits(&s->pb, 2, 2 - field_motion);
put_bits(&s->pb, 1, s->interlaced_dct);
}
}
// RAL: Parameter added: f_or_b_code
static void mpeg1_encode_motion(MpegEncContext *s, int val, int f_or_b_code)
{
if (val == 0) {
/* zero vector */
put_bits(&s->pb,
ff_mpeg12_mbMotionVectorTable[0][1],
ff_mpeg12_mbMotionVectorTable[0][0]);
} else {
int code, sign, bits;
int bit_size = f_or_b_code - 1;
int range = 1 << bit_size;
/* modulo encoding */
val = sign_extend(val, 5 + bit_size);
if (val >= 0) {
val--;
code = (val >> bit_size) + 1;
bits = val & (range - 1);
sign = 0;
} else {
val = -val;
val--;
code = (val >> bit_size) + 1;
bits = val & (range - 1);
sign = 1;
}
av_assert2(code > 0 && code <= 16);
put_bits(&s->pb,
ff_mpeg12_mbMotionVectorTable[code][1],
ff_mpeg12_mbMotionVectorTable[code][0]);
put_bits(&s->pb, 1, sign);
if (bit_size > 0)
put_bits(&s->pb, bit_size, bits);
}
}
static inline void encode_dc(MpegEncContext *s, int diff, int component)
{
unsigned int diff_u = diff + 255;
if (diff_u >= 511) {
int index;
if (diff < 0) {
index = av_log2_16bit(-2 * diff);
diff--;
} else {
index = av_log2_16bit(2 * diff);
}
if (component == 0)
put_bits(&s->pb,
ff_mpeg12_vlc_dc_lum_bits[index] + index,
(ff_mpeg12_vlc_dc_lum_code[index] << index) +
av_mod_uintp2(diff, index));
else
put_bits(&s->pb,
ff_mpeg12_vlc_dc_chroma_bits[index] + index,
(ff_mpeg12_vlc_dc_chroma_code[index] << index) +
av_mod_uintp2(diff, index));
} else {
if (component == 0)
put_bits(&s->pb,
mpeg1_lum_dc_uni[diff + 255] & 0xFF,
mpeg1_lum_dc_uni[diff + 255] >> 8);
else
put_bits(&s->pb,
mpeg1_chr_dc_uni[diff + 255] & 0xFF,
mpeg1_chr_dc_uni[diff + 255] >> 8);
}
}
static void mpeg1_encode_block(MpegEncContext *s, int16_t *block, int n)
{
int alevel, level, last_non_zero, dc, diff, i, j, run, last_index, sign;
int code, component;
const uint16_t (*table_vlc)[2] = ff_rl_mpeg1.table_vlc;
last_index = s->block_last_index[n];
/* DC coef */
if (s->mb_intra) {
component = (n <= 3 ? 0 : (n & 1) + 1);
dc = block[0]; /* overflow is impossible */
diff = dc - s->last_dc[component];
encode_dc(s, diff, component);
s->last_dc[component] = dc;
i = 1;
if (s->intra_vlc_format)
table_vlc = ff_rl_mpeg2.table_vlc;
} else {
/* encode the first coefficient: needs to be done here because
* it is handled slightly differently */
level = block[0];
if (abs(level) == 1) {
code = ((uint32_t)level >> 31); /* the sign bit */
put_bits(&s->pb, 2, code | 0x02);
i = 1;
} else {
i = 0;
last_non_zero = -1;
goto next_coef;
}
}
/* now quantify & encode AC coefs */
last_non_zero = i - 1;
for (; i <= last_index; i++) {
j = s->intra_scantable.permutated[i];
level = block[j];
next_coef:
/* encode using VLC */
if (level != 0) {
run = i - last_non_zero - 1;
alevel = level;
MASK_ABS(sign, alevel);
sign &= 1;
if (alevel <= mpeg1_max_level[0][run]) {
code = mpeg1_index_run[0][run] + alevel - 1;
/* store the VLC & sign at once */
put_bits(&s->pb, table_vlc[code][1] + 1,
(table_vlc[code][0] << 1) + sign);
} else {
/* escape seems to be pretty rare <5% so I do not optimize it */
put_bits(&s->pb, table_vlc[111][1], table_vlc[111][0]);
/* escape: only clip in this case */
put_bits(&s->pb, 6, run);
if (s->codec_id == AV_CODEC_ID_MPEG1VIDEO) {
if (alevel < 128) {
put_sbits(&s->pb, 8, level);
} else {
if (level < 0)
put_bits(&s->pb, 16, 0x8001 + level + 255);
else
put_sbits(&s->pb, 16, level);
}
} else {
put_sbits(&s->pb, 12, level);
}
}
last_non_zero = i;
}
}
/* end of block */
put_bits(&s->pb, table_vlc[112][1], table_vlc[112][0]);
}
static av_always_inline void mpeg1_encode_mb_internal(MpegEncContext *s,
int16_t block[8][64],
int motion_x, int motion_y,
int mb_block_count)
{
int i, cbp;
const int mb_x = s->mb_x;
const int mb_y = s->mb_y;
const int first_mb = mb_x == s->resync_mb_x && mb_y == s->resync_mb_y;
/* compute cbp */
cbp = 0;
for (i = 0; i < mb_block_count; i++)
if (s->block_last_index[i] >= 0)
cbp |= 1 << (mb_block_count - 1 - i);
if (cbp == 0 && !first_mb && s->mv_type == MV_TYPE_16X16 &&
(mb_x != s->mb_width - 1 ||
(mb_y != s->end_mb_y - 1 && s->codec_id == AV_CODEC_ID_MPEG1VIDEO)) &&
((s->pict_type == AV_PICTURE_TYPE_P && (motion_x | motion_y) == 0) ||
(s->pict_type == AV_PICTURE_TYPE_B && s->mv_dir == s->last_mv_dir &&
(((s->mv_dir & MV_DIR_FORWARD)
? ((s->mv[0][0][0] - s->last_mv[0][0][0]) |
(s->mv[0][0][1] - s->last_mv[0][0][1])) : 0) |
((s->mv_dir & MV_DIR_BACKWARD)
? ((s->mv[1][0][0] - s->last_mv[1][0][0]) |
(s->mv[1][0][1] - s->last_mv[1][0][1])) : 0)) == 0))) {
s->mb_skip_run++;
s->qscale -= s->dquant;
s->skip_count++;
s->misc_bits++;
s->last_bits++;
if (s->pict_type == AV_PICTURE_TYPE_P) {
s->last_mv[0][0][0] =
s->last_mv[0][0][1] =
s->last_mv[0][1][0] =
s->last_mv[0][1][1] = 0;
}
} else {
if (first_mb) {
av_assert0(s->mb_skip_run == 0);
encode_mb_skip_run(s, s->mb_x);
} else {
encode_mb_skip_run(s, s->mb_skip_run);
}
if (s->pict_type == AV_PICTURE_TYPE_I) {
if (s->dquant && cbp) {
/* macroblock_type: macroblock_quant = 1 */
put_mb_modes(s, 2, 1, 0, 0);
put_qscale(s);
} else {
/* macroblock_type: macroblock_quant = 0 */
put_mb_modes(s, 1, 1, 0, 0);
s->qscale -= s->dquant;
}
s->misc_bits += get_bits_diff(s);
s->i_count++;
} else if (s->mb_intra) {
if (s->dquant && cbp) {
put_mb_modes(s, 6, 0x01, 0, 0);
put_qscale(s);
} else {
put_mb_modes(s, 5, 0x03, 0, 0);
s->qscale -= s->dquant;
}
s->misc_bits += get_bits_diff(s);
s->i_count++;
memset(s->last_mv, 0, sizeof(s->last_mv));
} else if (s->pict_type == AV_PICTURE_TYPE_P) {
if (s->mv_type == MV_TYPE_16X16) {
if (cbp != 0) {
if ((motion_x | motion_y) == 0) {
if (s->dquant) {
/* macroblock_pattern & quant */
put_mb_modes(s, 5, 1, 0, 0);
put_qscale(s);
} else {
/* macroblock_pattern only */
put_mb_modes(s, 2, 1, 0, 0);
}
s->misc_bits += get_bits_diff(s);
} else {
if (s->dquant) {
put_mb_modes(s, 5, 2, 1, 0); /* motion + cbp */
put_qscale(s);
} else {
put_mb_modes(s, 1, 1, 1, 0); /* motion + cbp */
}
s->misc_bits += get_bits_diff(s);
// RAL: f_code parameter added
mpeg1_encode_motion(s,
motion_x - s->last_mv[0][0][0],
s->f_code);
// RAL: f_code parameter added
mpeg1_encode_motion(s,
motion_y - s->last_mv[0][0][1],
s->f_code);
s->mv_bits += get_bits_diff(s);
}
} else {
put_bits(&s->pb, 3, 1); /* motion only */
if (!s->frame_pred_frame_dct)
put_bits(&s->pb, 2, 2); /* motion_type: frame */
s->misc_bits += get_bits_diff(s);
// RAL: f_code parameter added
mpeg1_encode_motion(s,
motion_x - s->last_mv[0][0][0],
s->f_code);
// RAL: f_code parameter added
mpeg1_encode_motion(s,
motion_y - s->last_mv[0][0][1],
s->f_code);
s->qscale -= s->dquant;
s->mv_bits += get_bits_diff(s);
}
s->last_mv[0][1][0] = s->last_mv[0][0][0] = motion_x;
s->last_mv[0][1][1] = s->last_mv[0][0][1] = motion_y;
} else {
av_assert2(!s->frame_pred_frame_dct && s->mv_type == MV_TYPE_FIELD);
if (cbp) {
if (s->dquant) {
put_mb_modes(s, 5, 2, 1, 1); /* motion + cbp */
put_qscale(s);
} else {
put_mb_modes(s, 1, 1, 1, 1); /* motion + cbp */
}
} else {
put_bits(&s->pb, 3, 1); /* motion only */
put_bits(&s->pb, 2, 1); /* motion_type: field */
s->qscale -= s->dquant;
}
s->misc_bits += get_bits_diff(s);
for (i = 0; i < 2; i++) {
put_bits(&s->pb, 1, s->field_select[0][i]);
mpeg1_encode_motion(s,
s->mv[0][i][0] - s->last_mv[0][i][0],
s->f_code);
mpeg1_encode_motion(s,
s->mv[0][i][1] - (s->last_mv[0][i][1] >> 1),
s->f_code);
s->last_mv[0][i][0] = s->mv[0][i][0];
s->last_mv[0][i][1] = 2 * s->mv[0][i][1];
}
s->mv_bits += get_bits_diff(s);
}
if (cbp) {
if (s->chroma_y_shift) {
put_bits(&s->pb,
ff_mpeg12_mbPatTable[cbp][1],
ff_mpeg12_mbPatTable[cbp][0]);
} else {
put_bits(&s->pb,
ff_mpeg12_mbPatTable[cbp >> 2][1],
ff_mpeg12_mbPatTable[cbp >> 2][0]);
put_sbits(&s->pb, 2, cbp);
}
}
s->f_count++;
} else {
if (s->mv_type == MV_TYPE_16X16) {
if (cbp) { // With coded bloc pattern
if (s->dquant) {
if (s->mv_dir == MV_DIR_FORWARD)
put_mb_modes(s, 6, 3, 1, 0);
else
put_mb_modes(s, 8 - s->mv_dir, 2, 1, 0);
put_qscale(s);
} else {
put_mb_modes(s, 5 - s->mv_dir, 3, 1, 0);
}
} else { // No coded bloc pattern
put_bits(&s->pb, 5 - s->mv_dir, 2);
if (!s->frame_pred_frame_dct)
put_bits(&s->pb, 2, 2); /* motion_type: frame */
s->qscale -= s->dquant;
}
s->misc_bits += get_bits_diff(s);
if (s->mv_dir & MV_DIR_FORWARD) {
mpeg1_encode_motion(s,
s->mv[0][0][0] - s->last_mv[0][0][0],
s->f_code);
mpeg1_encode_motion(s,
s->mv[0][0][1] - s->last_mv[0][0][1],
s->f_code);
s->last_mv[0][0][0] =
s->last_mv[0][1][0] = s->mv[0][0][0];
s->last_mv[0][0][1] =
s->last_mv[0][1][1] = s->mv[0][0][1];
s->f_count++;
}
if (s->mv_dir & MV_DIR_BACKWARD) {
mpeg1_encode_motion(s,
s->mv[1][0][0] - s->last_mv[1][0][0],
s->b_code);
mpeg1_encode_motion(s,
s->mv[1][0][1] - s->last_mv[1][0][1],
s->b_code);
s->last_mv[1][0][0] =
s->last_mv[1][1][0] = s->mv[1][0][0];
s->last_mv[1][0][1] =
s->last_mv[1][1][1] = s->mv[1][0][1];
s->b_count++;
}
} else {
av_assert2(s->mv_type == MV_TYPE_FIELD);
av_assert2(!s->frame_pred_frame_dct);
if (cbp) { // With coded bloc pattern
if (s->dquant) {
if (s->mv_dir == MV_DIR_FORWARD)
put_mb_modes(s, 6, 3, 1, 1);
else
put_mb_modes(s, 8 - s->mv_dir, 2, 1, 1);
put_qscale(s);
} else {
put_mb_modes(s, 5 - s->mv_dir, 3, 1, 1);
}
} else { // No coded bloc pattern
put_bits(&s->pb, 5 - s->mv_dir, 2);
put_bits(&s->pb, 2, 1); /* motion_type: field */
s->qscale -= s->dquant;
}
s->misc_bits += get_bits_diff(s);
if (s->mv_dir & MV_DIR_FORWARD) {
for (i = 0; i < 2; i++) {
put_bits(&s->pb, 1, s->field_select[0][i]);
mpeg1_encode_motion(s,
s->mv[0][i][0] - s->last_mv[0][i][0],
s->f_code);
mpeg1_encode_motion(s,
s->mv[0][i][1] - (s->last_mv[0][i][1] >> 1),
s->f_code);
s->last_mv[0][i][0] = s->mv[0][i][0];
s->last_mv[0][i][1] = s->mv[0][i][1] * 2;
}
s->f_count++;
}
if (s->mv_dir & MV_DIR_BACKWARD) {
for (i = 0; i < 2; i++) {
put_bits(&s->pb, 1, s->field_select[1][i]);
mpeg1_encode_motion(s,
s->mv[1][i][0] - s->last_mv[1][i][0],
s->b_code);
mpeg1_encode_motion(s,
s->mv[1][i][1] - (s->last_mv[1][i][1] >> 1),
s->b_code);
s->last_mv[1][i][0] = s->mv[1][i][0];
s->last_mv[1][i][1] = s->mv[1][i][1] * 2;
}
s->b_count++;
}
}
s->mv_bits += get_bits_diff(s);
if (cbp) {
if (s->chroma_y_shift) {
put_bits(&s->pb,
ff_mpeg12_mbPatTable[cbp][1],
ff_mpeg12_mbPatTable[cbp][0]);
} else {
put_bits(&s->pb,
ff_mpeg12_mbPatTable[cbp >> 2][1],
ff_mpeg12_mbPatTable[cbp >> 2][0]);
put_sbits(&s->pb, 2, cbp);
}
}
}
for (i = 0; i < mb_block_count; i++)
if (cbp & (1 << (mb_block_count - 1 - i)))
mpeg1_encode_block(s, block[i], i);
s->mb_skip_run = 0;
if (s->mb_intra)
s->i_tex_bits += get_bits_diff(s);
else
s->p_tex_bits += get_bits_diff(s);
}
}
void ff_mpeg1_encode_mb(MpegEncContext *s, int16_t block[8][64],
int motion_x, int motion_y)
{
if (s->chroma_format == CHROMA_420)
mpeg1_encode_mb_internal(s, block, motion_x, motion_y, 6);
else
mpeg1_encode_mb_internal(s, block, motion_x, motion_y, 8);
}
av_cold void ff_mpeg1_encode_init(MpegEncContext *s)
{
static int done = 0;
ff_mpeg12_common_init(s);
if (!done) {
int f_code;
int mv;
int i;
done = 1;
ff_rl_init(&ff_rl_mpeg1, ff_mpeg12_static_rl_table_store[0]);
ff_rl_init(&ff_rl_mpeg2, ff_mpeg12_static_rl_table_store[1]);
for (i = 0; i < 64; i++) {
mpeg1_max_level[0][i] = ff_rl_mpeg1.max_level[0][i];
mpeg1_index_run[0][i] = ff_rl_mpeg1.index_run[0][i];
}
init_uni_ac_vlc(&ff_rl_mpeg1, uni_mpeg1_ac_vlc_len);
if (s->intra_vlc_format)
init_uni_ac_vlc(&ff_rl_mpeg2, uni_mpeg2_ac_vlc_len);
/* build unified dc encoding tables */
for (i = -255; i < 256; i++) {
int adiff, index;
int bits, code;
int diff = i;
adiff = FFABS(diff);
if (diff < 0)
diff--;
index = av_log2(2 * adiff);
bits = ff_mpeg12_vlc_dc_lum_bits[index] + index;
code = (ff_mpeg12_vlc_dc_lum_code[index] << index) +
av_mod_uintp2(diff, index);
mpeg1_lum_dc_uni[i + 255] = bits + (code << 8);
bits = ff_mpeg12_vlc_dc_chroma_bits[index] + index;
code = (ff_mpeg12_vlc_dc_chroma_code[index] << index) +
av_mod_uintp2(diff, index);
mpeg1_chr_dc_uni[i + 255] = bits + (code << 8);
}
for (f_code = 1; f_code <= MAX_FCODE; f_code++)
for (mv = -MAX_DMV; mv <= MAX_DMV; mv++) {
int len;
if (mv == 0) {
len = ff_mpeg12_mbMotionVectorTable[0][1];
} else {
int val, bit_size, code;
bit_size = f_code - 1;
val = mv;
if (val < 0)
val = -val;
val--;
code = (val >> bit_size) + 1;
if (code < 17)
len = ff_mpeg12_mbMotionVectorTable[code][1] +
1 + bit_size;
else
len = ff_mpeg12_mbMotionVectorTable[16][1] +
2 + bit_size;
}
mv_penalty[f_code][mv + MAX_DMV] = len;
}
for (f_code = MAX_FCODE; f_code > 0; f_code--)
for (mv = -(8 << f_code); mv < (8 << f_code); mv++)
fcode_tab[mv + MAX_MV] = f_code;
}
s->me.mv_penalty = mv_penalty;
s->fcode_tab = fcode_tab;
if (s->codec_id == AV_CODEC_ID_MPEG1VIDEO) {
s->min_qcoeff = -255;
s->max_qcoeff = 255;
} else {
s->min_qcoeff = -2047;
s->max_qcoeff = 2047;
}
if (s->intra_vlc_format) {
s->intra_ac_vlc_length =
s->intra_ac_vlc_last_length = uni_mpeg2_ac_vlc_len;
} else {
s->intra_ac_vlc_length =
s->intra_ac_vlc_last_length = uni_mpeg1_ac_vlc_len;
}
s->inter_ac_vlc_length =
s->inter_ac_vlc_last_length = uni_mpeg1_ac_vlc_len;
}
#define OFFSET(x) offsetof(MpegEncContext, x)
#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}, 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.", \
OFFSET(drop_frame_timecode), AV_OPT_TYPE_BOOL, { .i64 = 0 }, 0, 1, VE }, \
{ "scan_offset", "Reserve space for SVCD scan offset user data.", \
OFFSET(scan_offset), AV_OPT_TYPE_BOOL, { .i64 = 0 }, 0, 1, VE }, \
{ "timecode_frame_start", "GOP timecode frame start number, in non-drop-frame format", \
OFFSET(timecode_frame_start), AV_OPT_TYPE_INT64, {.i64 = -1 }, -1, INT64_MAX, VE}, \
static const AVOption mpeg1_options[] = {
COMMON_OPTS
FF_MPV_COMMON_OPTS
{ NULL },
};
static const AVOption mpeg2_options[] = {
COMMON_OPTS
{ "non_linear_quant", "Use nonlinear quantizer.", OFFSET(q_scale_type), AV_OPT_TYPE_BOOL, { .i64 = 0 }, 0, 1, VE },
{ "alternate_scan", "Enable alternate scantable.", OFFSET(alternate_scan), AV_OPT_TYPE_BOOL, { .i64 = 0 }, 0, 1, VE },
{ "seq_disp_ext", "Write sequence_display_extension blocks.", OFFSET(seq_disp_ext), AV_OPT_TYPE_INT, { .i64 = -1 }, -1, 1, VE, "seq_disp_ext" },
{ "auto", NULL, 0, AV_OPT_TYPE_CONST, {.i64 = -1}, 0, 0, VE, "seq_disp_ext" },
{ "never", NULL, 0, AV_OPT_TYPE_CONST, {.i64 = 0 }, 0, 0, VE, "seq_disp_ext" },
{ "always", NULL, 0, AV_OPT_TYPE_CONST, {.i64 = 1 }, 0, 0, VE, "seq_disp_ext" },
{ "video_format", "Video_format in the sequence_display_extension indicating the source of the video.", OFFSET(video_format), AV_OPT_TYPE_INT, { .i64 = VIDEO_FORMAT_UNSPECIFIED }, 0, 7, VE, "video_format" },
{ "component", NULL, 0, AV_OPT_TYPE_CONST, {.i64 = VIDEO_FORMAT_COMPONENT }, 0, 0, VE, "video_format" },
{ "pal", NULL, 0, AV_OPT_TYPE_CONST, {.i64 = VIDEO_FORMAT_PAL }, 0, 0, VE, "video_format" },
{ "ntsc", NULL, 0, AV_OPT_TYPE_CONST, {.i64 = VIDEO_FORMAT_NTSC }, 0, 0, VE, "video_format" },
{ "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 },
};
#define mpeg12_class(x) \
static const AVClass mpeg ## x ## _class = { \
.class_name = "mpeg" # x "video encoder", \
.item_name = av_default_item_name, \
.option = mpeg ## x ## _options, \
.version = LIBAVUTIL_VERSION_INT, \
};
mpeg12_class(1)
mpeg12_class(2)
AVCodec ff_mpeg1video_encoder = {
.name = "mpeg1video",
.long_name = NULL_IF_CONFIG_SMALL("MPEG-1 video"),
.type = AVMEDIA_TYPE_VIDEO,
.id = AV_CODEC_ID_MPEG1VIDEO,
.priv_data_size = sizeof(MpegEncContext),
.init = encode_init,
.encode2 = ff_mpv_encode_picture,
.close = ff_mpv_encode_end,
.supported_framerates = ff_mpeg12_frame_rate_tab + 1,
.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,
};
AVCodec ff_mpeg2video_encoder = {
.name = "mpeg2video",
.long_name = NULL_IF_CONFIG_SMALL("MPEG-2 video"),
.type = AVMEDIA_TYPE_VIDEO,
.id = AV_CODEC_ID_MPEG2VIDEO,
.priv_data_size = sizeof(MpegEncContext),
.init = encode_init,
.encode2 = ff_mpv_encode_picture,
.close = ff_mpv_encode_end,
.supported_framerates = ff_mpeg2_frame_rate_tab,
.pix_fmts = (const enum AVPixelFormat[]) { AV_PIX_FMT_YUV420P,
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,
};