mirror of
https://git.ffmpeg.org/ffmpeg.git
synced 2024-12-27 01:42:20 +00:00
a247ac640d
Given that the AVCodec.next pointer has now been removed, most of the AVCodecs are not modified at all any more and can therefore be made const (as this patch does); the only exceptions are the very few codecs for external libraries that have a init_static_data callback. Signed-off-by: Andreas Rheinhardt <andreas.rheinhardt@gmail.com> Signed-off-by: James Almer <jamrial@gmail.com>
1237 lines
48 KiB
C
1237 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 "config.h"
|
|
#include "libavutil/attributes.h"
|
|
#include "libavutil/avassert.h"
|
|
#include "libavutil/log.h"
|
|
#include "libavutil/opt.h"
|
|
#include "libavutil/thread.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"
|
|
|
|
#if CONFIG_MPEG1VIDEO_ENCODER || CONFIG_MPEG2VIDEO_ENCODER
|
|
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];
|
|
|
|
#define A53_MAX_CC_COUNT 0x1f
|
|
#endif /* CONFIG_MPEG1VIDEO_ENCODER || CONFIG_MPEG2VIDEO_ENCODER */
|
|
|
|
av_cold void ff_mpeg1_init_uni_ac_vlc(const 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;
|
|
}
|
|
}
|
|
}
|
|
|
|
#if CONFIG_MPEG1VIDEO_ENCODER || CONFIG_MPEG2VIDEO_ENCODER
|
|
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;
|
|
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 (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 = avctx->pix_fmt == AV_PIX_FMT_YUV420P ? 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 &&
|
|
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(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);
|
|
}
|
|
}
|
|
|
|
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 (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_bytes_count(&s->pb, 0);
|
|
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,
|
|
"Closed Caption size (%"SIZE_SPECIFIER") 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 <= ff_rl_mpeg1.max_level[0][run]) {
|
|
code = ff_rl_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);
|
|
}
|
|
|
|
static av_cold void mpeg12_encode_init_static(void)
|
|
{
|
|
static uint8_t mpeg12_static_rl_table_store[2][2][2*MAX_RUN + MAX_LEVEL + 3];
|
|
|
|
ff_rl_init(&ff_rl_mpeg1, mpeg12_static_rl_table_store[0]);
|
|
ff_rl_init(&ff_rl_mpeg2, mpeg12_static_rl_table_store[1]);
|
|
|
|
ff_mpeg1_init_uni_ac_vlc(&ff_rl_mpeg1, uni_mpeg1_ac_vlc_len);
|
|
ff_mpeg1_init_uni_ac_vlc(&ff_rl_mpeg2, uni_mpeg2_ac_vlc_len);
|
|
|
|
/* build unified dc encoding tables */
|
|
for (int 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 (int f_code = 1; f_code <= MAX_FCODE; f_code++)
|
|
for (int 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 (int f_code = MAX_FCODE; f_code > 0; f_code--)
|
|
for (int mv = -(8 << f_code); mv < (8 << f_code); mv++)
|
|
fcode_tab[mv + MAX_MV] = f_code;
|
|
}
|
|
|
|
av_cold void ff_mpeg1_encode_init(MpegEncContext *s)
|
|
{
|
|
static AVOnce init_static_once = AV_ONCE_INIT;
|
|
|
|
ff_mpeg12_common_init(s);
|
|
|
|
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;
|
|
|
|
ff_thread_once(&init_static_once, mpeg12_encode_init_static);
|
|
}
|
|
|
|
#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 },\
|
|
{ "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}, \
|
|
FF_MPV_COMMON_BFRAME_OPTS
|
|
|
|
static const AVOption mpeg1_options[] = {
|
|
COMMON_OPTS
|
|
FF_MPV_COMMON_OPTS
|
|
#if FF_API_MPEGVIDEO_OPTS
|
|
FF_MPV_DEPRECATED_MPEG_QUANT_OPT
|
|
FF_MPV_DEPRECATED_A53_CC_OPT
|
|
FF_MPV_DEPRECATED_MATRIX_OPT
|
|
#endif
|
|
{ NULL },
|
|
};
|
|
|
|
static const AVOption mpeg2_options[] = {
|
|
COMMON_OPTS
|
|
{ "intra_vlc", "Use MPEG-2 intra VLC table.",
|
|
OFFSET(intra_vlc_format), AV_OPT_TYPE_BOOL, { .i64 = 0 }, 0, 1, VE },
|
|
{ "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 },
|
|
{ "a53cc", "Use A53 Closed Captions (if available)", OFFSET(a53_cc), AV_OPT_TYPE_BOOL, { .i64 = 1 }, 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
|
|
#if FF_API_MPEGVIDEO_OPTS
|
|
{ "mpeg_quant", "Deprecated, does nothing", OFFSET(mpeg_quant),
|
|
AV_OPT_TYPE_INT, {.i64 = 1 }, 0, 1, VE | AV_OPT_FLAG_DEPRECATED },
|
|
FF_MPV_DEPRECATED_MATRIX_OPT
|
|
#endif
|
|
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)
|
|
|
|
const 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_THREADSAFE | FF_CODEC_CAP_INIT_CLEANUP,
|
|
.priv_class = &mpeg1_class,
|
|
};
|
|
|
|
const 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_THREADSAFE | FF_CODEC_CAP_INIT_CLEANUP,
|
|
.priv_class = &mpeg2_class,
|
|
};
|
|
#endif /* CONFIG_MPEG1VIDEO_ENCODER || CONFIG_MPEG2VIDEO_ENCODER */
|