mirror of
https://git.ffmpeg.org/ffmpeg.git
synced 2024-12-17 21:14:47 +00:00
703288cec6
I went through all codecs and put them into five basic categories: 1. JPEG range only 2. MPEG range only 3. Explicitly tagged 4. Broken (codec supports both but encoder ignores tags) 5. N/A (headerless or pseudo-formats) Filters in category 5 remain untouched. The rest gain an explicit assignment of their supported color ranges, with codecs in category 4 being set to MPEG-only for safety. It might be considered redundant to distinguish between 0 (category 5) and MPEG+JPEG (category 3), but in doing so we effectively communicate that we can guarantee that these tags will be encoded, which is distinct from the situation where there are some codecs that simply don't have tagging or implied semantics (e.g. rawvideo). A full list of codecs follows: JPEG range only: - amv - roqvideo MPEG range only: - asv1, asv2 - avui - cfhd - cljr - dnxhd - dvvideo - ffv1 - flv - h261, h263, h263p - {h263,vp8}_v4l2m2m - huffyuv, ffvhuff - jpeg2000 - libopenjpeg - libtheora - libwebp, libwebp_anim - libx262 - libxavs, libxavs2 - libxvid - mpeg1video, mpeg2video - mpeg2_qsv - mpeg2_vaapi - mpeg4, msmpeg4, msmpeg4v2, wmv1, wmv2 - mpeg4_omx - prores, prores_aw, prores_ks - rv10, rv20 - snow - speedhq - svq1 - tiff - utvideo Explicitly tagged (MPEG/JPEG): - {av1,h264,hevc}_nvenc - {av1,h264,hevc}_vaapi - {av1,h264,hevc,vp8,vp9,mpeg4}_mediacodec - {av1,h264,hevc,vp9}_qsv - h264_amf - {h264,hevc,prores}_videotoolbox - libaom-av1 - libkvazaar - libopenh264 - librav1e - libsvtav1 - libvpx, libvpx-vp9 - libx264 - libx265 - ljpeg - mjpeg - vc2 Broken (encoder ignores tags): - {av1,hevc}_amf - {h264,hevc,mpeg4}_v4l2m2m - h264_omx - libxeve - magicyuv - {vp8,vp9,mjpeg}_vaapi N/A: - ayuv, yuv4, y41p, v308, v210, v410, v408 (headerless) - pgmyuv (headerless) - rawvideo, bitpacked (headerless) - vnull, wrapped_avframe (pseudocodecs)
1402 lines
50 KiB
C
1402 lines
50 KiB
C
/*
|
|
* MPEG-4 encoder
|
|
* Copyright (c) 2000,2001 Fabrice Bellard
|
|
* Copyright (c) 2002-2010 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
|
|
*/
|
|
|
|
#include "libavutil/attributes.h"
|
|
#include "libavutil/log.h"
|
|
#include "libavutil/mem.h"
|
|
#include "libavutil/opt.h"
|
|
#include "libavutil/thread.h"
|
|
#include "codec_internal.h"
|
|
#include "mpegvideo.h"
|
|
#include "h263.h"
|
|
#include "h263enc.h"
|
|
#include "mpeg4video.h"
|
|
#include "mpeg4videodata.h"
|
|
#include "mpeg4videodefs.h"
|
|
#include "mpeg4videoenc.h"
|
|
#include "mpegvideoenc.h"
|
|
#include "profiles.h"
|
|
#include "version.h"
|
|
|
|
/* The uni_DCtab_* tables below contain unified bits+length tables to encode DC
|
|
* differences in MPEG-4. Unified in the sense that the specification specifies
|
|
* this encoding in several steps. */
|
|
static uint8_t uni_DCtab_lum_len[512];
|
|
static uint8_t uni_DCtab_chrom_len[512];
|
|
static uint16_t uni_DCtab_lum_bits[512];
|
|
static uint16_t uni_DCtab_chrom_bits[512];
|
|
|
|
/* Unified encoding tables for run length encoding of coefficients.
|
|
* Unified in the sense that the specification specifies the encoding in several steps. */
|
|
static uint32_t uni_mpeg4_intra_rl_bits[64 * 64 * 2 * 2];
|
|
static uint8_t uni_mpeg4_intra_rl_len[64 * 64 * 2 * 2];
|
|
static uint32_t uni_mpeg4_inter_rl_bits[64 * 64 * 2 * 2];
|
|
static uint8_t uni_mpeg4_inter_rl_len[64 * 64 * 2 * 2];
|
|
|
|
//#define UNI_MPEG4_ENC_INDEX(last, run, level) ((last) * 128 + (run) * 256 + (level))
|
|
//#define UNI_MPEG4_ENC_INDEX(last, run, level) ((last) * 128 * 64 + (run) + (level) * 64)
|
|
#define UNI_MPEG4_ENC_INDEX(last, run, level) ((last) * 128 * 64 + (run) * 128 + (level))
|
|
|
|
/* MPEG-4
|
|
* inter
|
|
* max level: 24/6
|
|
* max run: 53/63
|
|
*
|
|
* intra
|
|
* max level: 53/16
|
|
* max run: 29/41
|
|
*/
|
|
|
|
/**
|
|
* Return the number of bits that encoding the 8x8 block in block would need.
|
|
* @param[in] block_last_index last index in scantable order that refers to a non zero element in block.
|
|
*/
|
|
static inline int get_block_rate(MpegEncContext *s, int16_t block[64],
|
|
int block_last_index, const uint8_t scantable[64])
|
|
{
|
|
int last = 0;
|
|
int j;
|
|
int rate = 0;
|
|
|
|
for (j = 1; j <= block_last_index; j++) {
|
|
const int index = scantable[j];
|
|
int level = block[index];
|
|
if (level) {
|
|
level += 64;
|
|
if ((level & (~127)) == 0) {
|
|
if (j < block_last_index)
|
|
rate += s->intra_ac_vlc_length[UNI_AC_ENC_INDEX(j - last - 1, level)];
|
|
else
|
|
rate += s->intra_ac_vlc_last_length[UNI_AC_ENC_INDEX(j - last - 1, level)];
|
|
} else
|
|
rate += s->ac_esc_length;
|
|
|
|
last = j;
|
|
}
|
|
}
|
|
|
|
return rate;
|
|
}
|
|
|
|
/**
|
|
* Restore the ac coefficients in block that have been changed by decide_ac_pred().
|
|
* This function also restores s->block_last_index.
|
|
* @param[in,out] block MB coefficients, these will be restored
|
|
* @param[in] dir ac prediction direction for each 8x8 block
|
|
* @param[out] st scantable for each 8x8 block
|
|
* @param[in] zigzag_last_index index referring to the last non zero coefficient in zigzag order
|
|
*/
|
|
static inline void restore_ac_coeffs(MpegEncContext *s, int16_t block[6][64],
|
|
const int dir[6], const uint8_t *st[6],
|
|
const int zigzag_last_index[6])
|
|
{
|
|
int i, n;
|
|
memcpy(s->block_last_index, zigzag_last_index, sizeof(int) * 6);
|
|
|
|
for (n = 0; n < 6; n++) {
|
|
int16_t *ac_val = &s->ac_val[0][0][0] + s->block_index[n] * 16;
|
|
|
|
st[n] = s->intra_scantable.permutated;
|
|
if (dir[n]) {
|
|
/* top prediction */
|
|
for (i = 1; i < 8; i++)
|
|
block[n][s->idsp.idct_permutation[i]] = ac_val[i + 8];
|
|
} else {
|
|
/* left prediction */
|
|
for (i = 1; i < 8; i++)
|
|
block[n][s->idsp.idct_permutation[i << 3]] = ac_val[i];
|
|
}
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Return the optimal value (0 or 1) for the ac_pred element for the given MB in MPEG-4.
|
|
* This function will also update s->block_last_index and s->ac_val.
|
|
* @param[in,out] block MB coefficients, these will be updated if 1 is returned
|
|
* @param[in] dir ac prediction direction for each 8x8 block
|
|
* @param[out] st scantable for each 8x8 block
|
|
* @param[out] zigzag_last_index index referring to the last non zero coefficient in zigzag order
|
|
*/
|
|
static inline int decide_ac_pred(MpegEncContext *s, int16_t block[6][64],
|
|
const int dir[6], const uint8_t *st[6],
|
|
int zigzag_last_index[6])
|
|
{
|
|
int score = 0;
|
|
int i, n;
|
|
const int8_t *const qscale_table = s->cur_pic.qscale_table;
|
|
|
|
memcpy(zigzag_last_index, s->block_last_index, sizeof(int) * 6);
|
|
|
|
for (n = 0; n < 6; n++) {
|
|
int16_t *ac_val, *ac_val1;
|
|
|
|
score -= get_block_rate(s, block[n], s->block_last_index[n],
|
|
s->intra_scantable.permutated);
|
|
|
|
ac_val = &s->ac_val[0][0][0] + s->block_index[n] * 16;
|
|
ac_val1 = ac_val;
|
|
if (dir[n]) {
|
|
const int xy = s->mb_x + s->mb_y * s->mb_stride - s->mb_stride;
|
|
/* top prediction */
|
|
ac_val -= s->block_wrap[n] * 16;
|
|
if (s->mb_y == 0 || s->qscale == qscale_table[xy] || n == 2 || n == 3) {
|
|
/* same qscale */
|
|
for (i = 1; i < 8; i++) {
|
|
const int level = block[n][s->idsp.idct_permutation[i]];
|
|
block[n][s->idsp.idct_permutation[i]] = level - ac_val[i + 8];
|
|
ac_val1[i] = block[n][s->idsp.idct_permutation[i << 3]];
|
|
ac_val1[i + 8] = level;
|
|
}
|
|
} else {
|
|
/* different qscale, we must rescale */
|
|
for (i = 1; i < 8; i++) {
|
|
const int level = block[n][s->idsp.idct_permutation[i]];
|
|
block[n][s->idsp.idct_permutation[i]] = level - ROUNDED_DIV(ac_val[i + 8] * qscale_table[xy], s->qscale);
|
|
ac_val1[i] = block[n][s->idsp.idct_permutation[i << 3]];
|
|
ac_val1[i + 8] = level;
|
|
}
|
|
}
|
|
st[n] = s->permutated_intra_h_scantable;
|
|
} else {
|
|
const int xy = s->mb_x - 1 + s->mb_y * s->mb_stride;
|
|
/* left prediction */
|
|
ac_val -= 16;
|
|
if (s->mb_x == 0 || s->qscale == qscale_table[xy] || n == 1 || n == 3) {
|
|
/* same qscale */
|
|
for (i = 1; i < 8; i++) {
|
|
const int level = block[n][s->idsp.idct_permutation[i << 3]];
|
|
block[n][s->idsp.idct_permutation[i << 3]] = level - ac_val[i];
|
|
ac_val1[i] = level;
|
|
ac_val1[i + 8] = block[n][s->idsp.idct_permutation[i]];
|
|
}
|
|
} else {
|
|
/* different qscale, we must rescale */
|
|
for (i = 1; i < 8; i++) {
|
|
const int level = block[n][s->idsp.idct_permutation[i << 3]];
|
|
block[n][s->idsp.idct_permutation[i << 3]] = level - ROUNDED_DIV(ac_val[i] * qscale_table[xy], s->qscale);
|
|
ac_val1[i] = level;
|
|
ac_val1[i + 8] = block[n][s->idsp.idct_permutation[i]];
|
|
}
|
|
}
|
|
st[n] = s->permutated_intra_v_scantable;
|
|
}
|
|
|
|
for (i = 63; i > 0; i--) // FIXME optimize
|
|
if (block[n][st[n][i]])
|
|
break;
|
|
s->block_last_index[n] = i;
|
|
|
|
score += get_block_rate(s, block[n], s->block_last_index[n], st[n]);
|
|
}
|
|
|
|
if (score < 0) {
|
|
return 1;
|
|
} else {
|
|
restore_ac_coeffs(s, block, dir, st, zigzag_last_index);
|
|
return 0;
|
|
}
|
|
}
|
|
|
|
/**
|
|
* modify mb_type & qscale so that encoding is actually possible in MPEG-4
|
|
*/
|
|
void ff_clean_mpeg4_qscales(MpegEncContext *s)
|
|
{
|
|
int i;
|
|
int8_t *const qscale_table = s->cur_pic.qscale_table;
|
|
|
|
ff_clean_h263_qscales(s);
|
|
|
|
if (s->pict_type == AV_PICTURE_TYPE_B) {
|
|
int odd = 0;
|
|
/* ok, come on, this isn't funny anymore, there's more code for
|
|
* handling this MPEG-4 mess than for the actual adaptive quantization */
|
|
|
|
for (i = 0; i < s->mb_num; i++) {
|
|
int mb_xy = s->mb_index2xy[i];
|
|
odd += qscale_table[mb_xy] & 1;
|
|
}
|
|
|
|
if (2 * odd > s->mb_num)
|
|
odd = 1;
|
|
else
|
|
odd = 0;
|
|
|
|
for (i = 0; i < s->mb_num; i++) {
|
|
int mb_xy = s->mb_index2xy[i];
|
|
if ((qscale_table[mb_xy] & 1) != odd)
|
|
qscale_table[mb_xy]++;
|
|
if (qscale_table[mb_xy] > 31)
|
|
qscale_table[mb_xy] = 31;
|
|
}
|
|
|
|
for (i = 1; i < s->mb_num; i++) {
|
|
int mb_xy = s->mb_index2xy[i];
|
|
if (qscale_table[mb_xy] != qscale_table[s->mb_index2xy[i - 1]] &&
|
|
(s->mb_type[mb_xy] & CANDIDATE_MB_TYPE_DIRECT)) {
|
|
s->mb_type[mb_xy] |= CANDIDATE_MB_TYPE_BIDIR;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Encode the dc value.
|
|
* @param n block index (0-3 are luma, 4-5 are chroma)
|
|
*/
|
|
static inline void mpeg4_encode_dc(PutBitContext *s, int level, int n)
|
|
{
|
|
/* DC will overflow if level is outside the [-255,255] range. */
|
|
level += 256;
|
|
if (n < 4) {
|
|
/* luminance */
|
|
put_bits(s, uni_DCtab_lum_len[level], uni_DCtab_lum_bits[level]);
|
|
} else {
|
|
/* chrominance */
|
|
put_bits(s, uni_DCtab_chrom_len[level], uni_DCtab_chrom_bits[level]);
|
|
}
|
|
}
|
|
|
|
static inline int mpeg4_get_dc_length(int level, int n)
|
|
{
|
|
if (n < 4)
|
|
return uni_DCtab_lum_len[level + 256];
|
|
else
|
|
return uni_DCtab_chrom_len[level + 256];
|
|
}
|
|
|
|
/**
|
|
* Encode an 8x8 block.
|
|
* @param n block index (0-3 are luma, 4-5 are chroma)
|
|
*/
|
|
static inline void mpeg4_encode_block(const MpegEncContext *s,
|
|
const int16_t *block, int n, int intra_dc,
|
|
const uint8_t *scan_table, PutBitContext *dc_pb,
|
|
PutBitContext *ac_pb)
|
|
{
|
|
int i, last_non_zero;
|
|
const uint32_t *bits_tab;
|
|
const uint8_t *len_tab;
|
|
const int last_index = s->block_last_index[n];
|
|
|
|
if (s->mb_intra) { // Note gcc (3.2.1 at least) will optimize this away
|
|
/* MPEG-4 based DC predictor */
|
|
mpeg4_encode_dc(dc_pb, intra_dc, n);
|
|
if (last_index < 1)
|
|
return;
|
|
i = 1;
|
|
bits_tab = uni_mpeg4_intra_rl_bits;
|
|
len_tab = uni_mpeg4_intra_rl_len;
|
|
} else {
|
|
if (last_index < 0)
|
|
return;
|
|
i = 0;
|
|
bits_tab = uni_mpeg4_inter_rl_bits;
|
|
len_tab = uni_mpeg4_inter_rl_len;
|
|
}
|
|
|
|
/* AC coefs */
|
|
last_non_zero = i - 1;
|
|
for (; i < last_index; i++) {
|
|
int level = block[scan_table[i]];
|
|
if (level) {
|
|
int run = i - last_non_zero - 1;
|
|
level += 64;
|
|
if ((level & (~127)) == 0) {
|
|
const int index = UNI_MPEG4_ENC_INDEX(0, run, level);
|
|
put_bits(ac_pb, len_tab[index], bits_tab[index]);
|
|
} else { // ESC3
|
|
put_bits(ac_pb,
|
|
7 + 2 + 1 + 6 + 1 + 12 + 1,
|
|
(3 << 23) + (3 << 21) + (0 << 20) + (run << 14) +
|
|
(1 << 13) + (((level - 64) & 0xfff) << 1) + 1);
|
|
}
|
|
last_non_zero = i;
|
|
}
|
|
}
|
|
/* if (i <= last_index) */ {
|
|
int level = block[scan_table[i]];
|
|
int run = i - last_non_zero - 1;
|
|
level += 64;
|
|
if ((level & (~127)) == 0) {
|
|
const int index = UNI_MPEG4_ENC_INDEX(1, run, level);
|
|
put_bits(ac_pb, len_tab[index], bits_tab[index]);
|
|
} else { // ESC3
|
|
put_bits(ac_pb,
|
|
7 + 2 + 1 + 6 + 1 + 12 + 1,
|
|
(3 << 23) + (3 << 21) + (1 << 20) + (run << 14) +
|
|
(1 << 13) + (((level - 64) & 0xfff) << 1) + 1);
|
|
}
|
|
}
|
|
}
|
|
|
|
static int mpeg4_get_block_length(MpegEncContext *s,
|
|
const int16_t *block, int n,
|
|
int intra_dc, const uint8_t *scan_table)
|
|
{
|
|
int i, last_non_zero;
|
|
const uint8_t *len_tab;
|
|
const int last_index = s->block_last_index[n];
|
|
int len = 0;
|
|
|
|
if (s->mb_intra) { // Note gcc (3.2.1 at least) will optimize this away
|
|
/* MPEG-4 based DC predictor */
|
|
len += mpeg4_get_dc_length(intra_dc, n);
|
|
if (last_index < 1)
|
|
return len;
|
|
i = 1;
|
|
len_tab = uni_mpeg4_intra_rl_len;
|
|
} else {
|
|
if (last_index < 0)
|
|
return 0;
|
|
i = 0;
|
|
len_tab = uni_mpeg4_inter_rl_len;
|
|
}
|
|
|
|
/* AC coefs */
|
|
last_non_zero = i - 1;
|
|
for (; i < last_index; i++) {
|
|
int level = block[scan_table[i]];
|
|
if (level) {
|
|
int run = i - last_non_zero - 1;
|
|
level += 64;
|
|
if ((level & (~127)) == 0) {
|
|
const int index = UNI_MPEG4_ENC_INDEX(0, run, level);
|
|
len += len_tab[index];
|
|
} else { // ESC3
|
|
len += 7 + 2 + 1 + 6 + 1 + 12 + 1;
|
|
}
|
|
last_non_zero = i;
|
|
}
|
|
}
|
|
/* if (i <= last_index) */ {
|
|
int level = block[scan_table[i]];
|
|
int run = i - last_non_zero - 1;
|
|
level += 64;
|
|
if ((level & (~127)) == 0) {
|
|
const int index = UNI_MPEG4_ENC_INDEX(1, run, level);
|
|
len += len_tab[index];
|
|
} else { // ESC3
|
|
len += 7 + 2 + 1 + 6 + 1 + 12 + 1;
|
|
}
|
|
}
|
|
|
|
return len;
|
|
}
|
|
|
|
static inline void mpeg4_encode_blocks(MpegEncContext *s,
|
|
const int16_t block[6][64],
|
|
const int intra_dc[6],
|
|
const uint8_t * const *scan_table,
|
|
PutBitContext *dc_pb,
|
|
PutBitContext *ac_pb)
|
|
{
|
|
int i;
|
|
|
|
if (scan_table) {
|
|
if (s->avctx->flags2 & AV_CODEC_FLAG2_NO_OUTPUT) {
|
|
for (i = 0; i < 6; i++)
|
|
skip_put_bits(&s->pb,
|
|
mpeg4_get_block_length(s, block[i], i,
|
|
intra_dc[i], scan_table[i]));
|
|
} else {
|
|
/* encode each block */
|
|
for (i = 0; i < 6; i++)
|
|
mpeg4_encode_block(s, block[i], i,
|
|
intra_dc[i], scan_table[i], dc_pb, ac_pb);
|
|
}
|
|
} else {
|
|
if (s->avctx->flags2 & AV_CODEC_FLAG2_NO_OUTPUT) {
|
|
for (i = 0; i < 6; i++)
|
|
skip_put_bits(&s->pb,
|
|
mpeg4_get_block_length(s, block[i], i, 0,
|
|
s->intra_scantable.permutated));
|
|
} else {
|
|
/* encode each block */
|
|
for (i = 0; i < 6; i++)
|
|
mpeg4_encode_block(s, block[i], i, 0,
|
|
s->intra_scantable.permutated, dc_pb, ac_pb);
|
|
}
|
|
}
|
|
}
|
|
|
|
static inline int get_b_cbp(MpegEncContext *s, int16_t block[6][64],
|
|
int motion_x, int motion_y, int mb_type)
|
|
{
|
|
int cbp = 0, i;
|
|
|
|
if (s->mpv_flags & FF_MPV_FLAG_CBP_RD) {
|
|
int score = 0;
|
|
const int lambda = s->lambda2 >> (FF_LAMBDA_SHIFT - 6);
|
|
|
|
for (i = 0; i < 6; i++) {
|
|
if (s->coded_score[i] < 0) {
|
|
score += s->coded_score[i];
|
|
cbp |= 1 << (5 - i);
|
|
}
|
|
}
|
|
|
|
if (cbp) {
|
|
int zero_score = -6;
|
|
if ((motion_x | motion_y | s->dquant | mb_type) == 0)
|
|
zero_score -= 4; // 2 * MV + mb_type + cbp bit
|
|
|
|
zero_score *= lambda;
|
|
if (zero_score <= score)
|
|
cbp = 0;
|
|
}
|
|
|
|
for (i = 0; i < 6; i++) {
|
|
if (s->block_last_index[i] >= 0 && ((cbp >> (5 - i)) & 1) == 0) {
|
|
s->block_last_index[i] = -1;
|
|
s->bdsp.clear_block(s->block[i]);
|
|
}
|
|
}
|
|
} else {
|
|
for (i = 0; i < 6; i++) {
|
|
if (s->block_last_index[i] >= 0)
|
|
cbp |= 1 << (5 - i);
|
|
}
|
|
}
|
|
return cbp;
|
|
}
|
|
|
|
// FIXME this is duplicated to h263.c
|
|
static const int dquant_code[5] = { 1, 0, 9, 2, 3 };
|
|
|
|
void ff_mpeg4_encode_mb(MpegEncContext *s, int16_t block[6][64],
|
|
int motion_x, int motion_y)
|
|
{
|
|
int cbpc, cbpy, pred_x, pred_y;
|
|
PutBitContext *const pb2 = s->data_partitioning ? &s->pb2 : &s->pb;
|
|
PutBitContext *const tex_pb = s->data_partitioning && s->pict_type != AV_PICTURE_TYPE_B ? &s->tex_pb : &s->pb;
|
|
PutBitContext *const dc_pb = s->data_partitioning && s->pict_type != AV_PICTURE_TYPE_I ? &s->pb2 : &s->pb;
|
|
const int interleaved_stats = (s->avctx->flags & AV_CODEC_FLAG_PASS1) && !s->data_partitioning ? 1 : 0;
|
|
|
|
if (!s->mb_intra) {
|
|
int i, cbp;
|
|
|
|
if (s->pict_type == AV_PICTURE_TYPE_B) {
|
|
/* convert from mv_dir to type */
|
|
static const int mb_type_table[8] = { -1, 3, 2, 1, -1, -1, -1, 0 };
|
|
int mb_type = mb_type_table[s->mv_dir];
|
|
|
|
if (s->mb_x == 0) {
|
|
for (i = 0; i < 2; i++)
|
|
s->last_mv[i][0][0] =
|
|
s->last_mv[i][0][1] =
|
|
s->last_mv[i][1][0] =
|
|
s->last_mv[i][1][1] = 0;
|
|
}
|
|
|
|
av_assert2(s->dquant >= -2 && s->dquant <= 2);
|
|
av_assert2((s->dquant & 1) == 0);
|
|
av_assert2(mb_type >= 0);
|
|
|
|
/* nothing to do if this MB was skipped in the next P-frame */
|
|
if (s->next_pic.mbskip_table[s->mb_y * s->mb_stride + s->mb_x]) { // FIXME avoid DCT & ...
|
|
s->mv[0][0][0] =
|
|
s->mv[0][0][1] =
|
|
s->mv[1][0][0] =
|
|
s->mv[1][0][1] = 0;
|
|
s->mv_dir = MV_DIR_FORWARD; // doesn't matter
|
|
s->qscale -= s->dquant;
|
|
// s->mb_skipped = 1;
|
|
|
|
return;
|
|
}
|
|
|
|
cbp = get_b_cbp(s, block, motion_x, motion_y, mb_type);
|
|
|
|
if ((cbp | motion_x | motion_y | mb_type) == 0) {
|
|
/* direct MB with MV={0,0} */
|
|
av_assert2(s->dquant == 0);
|
|
|
|
put_bits(&s->pb, 1, 1); /* mb not coded modb1=1 */
|
|
|
|
if (interleaved_stats) {
|
|
s->misc_bits++;
|
|
s->last_bits++;
|
|
}
|
|
return;
|
|
}
|
|
|
|
put_bits(&s->pb, 1, 0); /* mb coded modb1=0 */
|
|
put_bits(&s->pb, 1, cbp ? 0 : 1); /* modb2 */ // FIXME merge
|
|
put_bits(&s->pb, mb_type + 1, 1); // this table is so simple that we don't need it :)
|
|
if (cbp)
|
|
put_bits(&s->pb, 6, cbp);
|
|
|
|
if (cbp && mb_type) {
|
|
if (s->dquant)
|
|
put_bits(&s->pb, 2, (s->dquant >> 2) + 3);
|
|
else
|
|
put_bits(&s->pb, 1, 0);
|
|
} else
|
|
s->qscale -= s->dquant;
|
|
|
|
if (!s->progressive_sequence) {
|
|
if (cbp)
|
|
put_bits(&s->pb, 1, s->interlaced_dct);
|
|
if (mb_type) // not direct mode
|
|
put_bits(&s->pb, 1, s->mv_type == MV_TYPE_FIELD);
|
|
}
|
|
|
|
if (interleaved_stats)
|
|
s->misc_bits += get_bits_diff(s);
|
|
|
|
if (!mb_type) {
|
|
av_assert2(s->mv_dir & MV_DIRECT);
|
|
ff_h263_encode_motion_vector(s, motion_x, motion_y, 1);
|
|
} else {
|
|
av_assert2(mb_type > 0 && mb_type < 4);
|
|
if (s->mv_type != MV_TYPE_FIELD) {
|
|
if (s->mv_dir & MV_DIR_FORWARD) {
|
|
ff_h263_encode_motion_vector(s,
|
|
s->mv[0][0][0] - s->last_mv[0][0][0],
|
|
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];
|
|
}
|
|
if (s->mv_dir & MV_DIR_BACKWARD) {
|
|
ff_h263_encode_motion_vector(s,
|
|
s->mv[1][0][0] - s->last_mv[1][0][0],
|
|
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];
|
|
}
|
|
} else {
|
|
if (s->mv_dir & MV_DIR_FORWARD) {
|
|
put_bits(&s->pb, 1, s->field_select[0][0]);
|
|
put_bits(&s->pb, 1, s->field_select[0][1]);
|
|
}
|
|
if (s->mv_dir & MV_DIR_BACKWARD) {
|
|
put_bits(&s->pb, 1, s->field_select[1][0]);
|
|
put_bits(&s->pb, 1, s->field_select[1][1]);
|
|
}
|
|
if (s->mv_dir & MV_DIR_FORWARD) {
|
|
for (i = 0; i < 2; i++) {
|
|
ff_h263_encode_motion_vector(s,
|
|
s->mv[0][i][0] - s->last_mv[0][i][0],
|
|
s->mv[0][i][1] - s->last_mv[0][i][1] / 2,
|
|
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;
|
|
}
|
|
}
|
|
if (s->mv_dir & MV_DIR_BACKWARD) {
|
|
for (i = 0; i < 2; i++) {
|
|
ff_h263_encode_motion_vector(s,
|
|
s->mv[1][i][0] - s->last_mv[1][i][0],
|
|
s->mv[1][i][1] - s->last_mv[1][i][1] / 2,
|
|
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;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
if (interleaved_stats)
|
|
s->mv_bits += get_bits_diff(s);
|
|
|
|
mpeg4_encode_blocks(s, block, NULL, NULL, NULL, &s->pb);
|
|
|
|
if (interleaved_stats)
|
|
s->p_tex_bits += get_bits_diff(s);
|
|
} else { /* s->pict_type==AV_PICTURE_TYPE_B */
|
|
cbp = get_p_cbp(s, block, motion_x, motion_y);
|
|
|
|
if ((cbp | motion_x | motion_y | s->dquant) == 0 &&
|
|
s->mv_type == MV_TYPE_16X16) {
|
|
/* Check if the B-frames can skip it too, as we must skip it
|
|
* if we skip here why didn't they just compress
|
|
* the skip-mb bits instead of reusing them ?! */
|
|
if (s->max_b_frames > 0) {
|
|
int i;
|
|
int x, y, offset;
|
|
const uint8_t *p_pic;
|
|
|
|
x = s->mb_x * 16;
|
|
y = s->mb_y * 16;
|
|
|
|
offset = x + y * s->linesize;
|
|
p_pic = s->new_pic->data[0] + offset;
|
|
|
|
s->mb_skipped = 1;
|
|
for (i = 0; i < s->max_b_frames; i++) {
|
|
const uint8_t *b_pic;
|
|
int diff;
|
|
const MPVPicture *pic = s->reordered_input_picture[i + 1];
|
|
|
|
if (!pic || pic->f->pict_type != AV_PICTURE_TYPE_B)
|
|
break;
|
|
|
|
b_pic = pic->f->data[0] + offset;
|
|
if (!pic->shared)
|
|
b_pic += INPLACE_OFFSET;
|
|
|
|
if (x + 16 > s->width || y + 16 > s->height) {
|
|
int x1, y1;
|
|
int xe = FFMIN(16, s->width - x);
|
|
int ye = FFMIN(16, s->height - y);
|
|
diff = 0;
|
|
for (y1 = 0; y1 < ye; y1++) {
|
|
for (x1 = 0; x1 < xe; x1++) {
|
|
diff += FFABS(p_pic[x1 + y1 * s->linesize] - b_pic[x1 + y1 * s->linesize]);
|
|
}
|
|
}
|
|
diff = diff * 256 / (xe * ye);
|
|
} else {
|
|
diff = s->sad_cmp[0](NULL, p_pic, b_pic, s->linesize, 16);
|
|
}
|
|
if (diff > s->qscale * 70) { // FIXME check that 70 is optimal
|
|
s->mb_skipped = 0;
|
|
break;
|
|
}
|
|
}
|
|
} else
|
|
s->mb_skipped = 1;
|
|
|
|
if (s->mb_skipped == 1) {
|
|
/* skip macroblock */
|
|
put_bits(&s->pb, 1, 1);
|
|
|
|
if (interleaved_stats) {
|
|
s->misc_bits++;
|
|
s->last_bits++;
|
|
}
|
|
|
|
return;
|
|
}
|
|
}
|
|
|
|
put_bits(&s->pb, 1, 0); /* mb coded */
|
|
cbpc = cbp & 3;
|
|
cbpy = cbp >> 2;
|
|
cbpy ^= 0xf;
|
|
if (s->mv_type == MV_TYPE_16X16) {
|
|
if (s->dquant)
|
|
cbpc += 8;
|
|
put_bits(&s->pb,
|
|
ff_h263_inter_MCBPC_bits[cbpc],
|
|
ff_h263_inter_MCBPC_code[cbpc]);
|
|
|
|
put_bits(pb2, ff_h263_cbpy_tab[cbpy][1], ff_h263_cbpy_tab[cbpy][0]);
|
|
if (s->dquant)
|
|
put_bits(pb2, 2, dquant_code[s->dquant + 2]);
|
|
|
|
if (!s->progressive_sequence) {
|
|
if (cbp)
|
|
put_bits(pb2, 1, s->interlaced_dct);
|
|
put_bits(pb2, 1, 0);
|
|
}
|
|
|
|
if (interleaved_stats)
|
|
s->misc_bits += get_bits_diff(s);
|
|
|
|
/* motion vectors: 16x16 mode */
|
|
ff_h263_pred_motion(s, 0, 0, &pred_x, &pred_y);
|
|
|
|
ff_h263_encode_motion_vector(s,
|
|
motion_x - pred_x,
|
|
motion_y - pred_y,
|
|
s->f_code);
|
|
} else if (s->mv_type == MV_TYPE_FIELD) {
|
|
if (s->dquant)
|
|
cbpc += 8;
|
|
put_bits(&s->pb,
|
|
ff_h263_inter_MCBPC_bits[cbpc],
|
|
ff_h263_inter_MCBPC_code[cbpc]);
|
|
|
|
put_bits(pb2, ff_h263_cbpy_tab[cbpy][1], ff_h263_cbpy_tab[cbpy][0]);
|
|
if (s->dquant)
|
|
put_bits(pb2, 2, dquant_code[s->dquant + 2]);
|
|
|
|
av_assert2(!s->progressive_sequence);
|
|
if (cbp)
|
|
put_bits(pb2, 1, s->interlaced_dct);
|
|
put_bits(pb2, 1, 1);
|
|
|
|
if (interleaved_stats)
|
|
s->misc_bits += get_bits_diff(s);
|
|
|
|
/* motion vectors: 16x8 interlaced mode */
|
|
ff_h263_pred_motion(s, 0, 0, &pred_x, &pred_y);
|
|
pred_y /= 2;
|
|
|
|
put_bits(&s->pb, 1, s->field_select[0][0]);
|
|
put_bits(&s->pb, 1, s->field_select[0][1]);
|
|
|
|
ff_h263_encode_motion_vector(s,
|
|
s->mv[0][0][0] - pred_x,
|
|
s->mv[0][0][1] - pred_y,
|
|
s->f_code);
|
|
ff_h263_encode_motion_vector(s,
|
|
s->mv[0][1][0] - pred_x,
|
|
s->mv[0][1][1] - pred_y,
|
|
s->f_code);
|
|
} else {
|
|
av_assert2(s->mv_type == MV_TYPE_8X8);
|
|
put_bits(&s->pb,
|
|
ff_h263_inter_MCBPC_bits[cbpc + 16],
|
|
ff_h263_inter_MCBPC_code[cbpc + 16]);
|
|
put_bits(pb2, ff_h263_cbpy_tab[cbpy][1], ff_h263_cbpy_tab[cbpy][0]);
|
|
|
|
if (!s->progressive_sequence && cbp)
|
|
put_bits(pb2, 1, s->interlaced_dct);
|
|
|
|
if (interleaved_stats)
|
|
s->misc_bits += get_bits_diff(s);
|
|
|
|
for (i = 0; i < 4; i++) {
|
|
/* motion vectors: 8x8 mode*/
|
|
ff_h263_pred_motion(s, i, 0, &pred_x, &pred_y);
|
|
|
|
ff_h263_encode_motion_vector(s,
|
|
s->cur_pic.motion_val[0][s->block_index[i]][0] - pred_x,
|
|
s->cur_pic.motion_val[0][s->block_index[i]][1] - pred_y,
|
|
s->f_code);
|
|
}
|
|
}
|
|
|
|
if (interleaved_stats)
|
|
s->mv_bits += get_bits_diff(s);
|
|
|
|
mpeg4_encode_blocks(s, block, NULL, NULL, NULL, tex_pb);
|
|
|
|
if (interleaved_stats)
|
|
s->p_tex_bits += get_bits_diff(s);
|
|
}
|
|
} else {
|
|
int cbp;
|
|
int dc_diff[6]; // dc values with the dc prediction subtracted
|
|
int dir[6]; // prediction direction
|
|
int zigzag_last_index[6];
|
|
const uint8_t *scan_table[6];
|
|
int i;
|
|
|
|
for (i = 0; i < 6; i++)
|
|
dc_diff[i] = ff_mpeg4_pred_dc(s, i, block[i][0], &dir[i], 1);
|
|
|
|
if (s->avctx->flags & AV_CODEC_FLAG_AC_PRED) {
|
|
s->ac_pred = decide_ac_pred(s, block, dir, scan_table, zigzag_last_index);
|
|
} else {
|
|
for (i = 0; i < 6; i++)
|
|
scan_table[i] = s->intra_scantable.permutated;
|
|
}
|
|
|
|
/* compute cbp */
|
|
cbp = 0;
|
|
for (i = 0; i < 6; i++)
|
|
if (s->block_last_index[i] >= 1)
|
|
cbp |= 1 << (5 - i);
|
|
|
|
cbpc = cbp & 3;
|
|
if (s->pict_type == AV_PICTURE_TYPE_I) {
|
|
if (s->dquant)
|
|
cbpc += 4;
|
|
put_bits(&s->pb,
|
|
ff_h263_intra_MCBPC_bits[cbpc],
|
|
ff_h263_intra_MCBPC_code[cbpc]);
|
|
} else {
|
|
if (s->dquant)
|
|
cbpc += 8;
|
|
put_bits(&s->pb, 1, 0); /* mb coded */
|
|
put_bits(&s->pb,
|
|
ff_h263_inter_MCBPC_bits[cbpc + 4],
|
|
ff_h263_inter_MCBPC_code[cbpc + 4]);
|
|
}
|
|
put_bits(pb2, 1, s->ac_pred);
|
|
cbpy = cbp >> 2;
|
|
put_bits(pb2, ff_h263_cbpy_tab[cbpy][1], ff_h263_cbpy_tab[cbpy][0]);
|
|
if (s->dquant)
|
|
put_bits(dc_pb, 2, dquant_code[s->dquant + 2]);
|
|
|
|
if (!s->progressive_sequence)
|
|
put_bits(dc_pb, 1, s->interlaced_dct);
|
|
|
|
if (interleaved_stats)
|
|
s->misc_bits += get_bits_diff(s);
|
|
|
|
mpeg4_encode_blocks(s, block, dc_diff, scan_table, dc_pb, tex_pb);
|
|
|
|
if (interleaved_stats)
|
|
s->i_tex_bits += get_bits_diff(s);
|
|
s->i_count++;
|
|
|
|
/* restore ac coeffs & last_index stuff
|
|
* if we messed them up with the prediction */
|
|
if (s->ac_pred)
|
|
restore_ac_coeffs(s, block, dir, scan_table, zigzag_last_index);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* add MPEG-4 stuffing bits (01...1)
|
|
*/
|
|
void ff_mpeg4_stuffing(PutBitContext *pbc)
|
|
{
|
|
int length = 8 - (put_bits_count(pbc) & 7);
|
|
|
|
put_bits(pbc, length, (1 << (length - 1)) - 1);
|
|
}
|
|
|
|
/* must be called before writing the header */
|
|
void ff_set_mpeg4_time(MpegEncContext *s)
|
|
{
|
|
if (s->pict_type == AV_PICTURE_TYPE_B) {
|
|
ff_mpeg4_init_direct_mv(s);
|
|
} else {
|
|
s->last_time_base = s->time_base;
|
|
s->time_base = FFUDIV(s->time, s->avctx->time_base.den);
|
|
}
|
|
}
|
|
|
|
static void mpeg4_encode_gop_header(MpegEncContext *s)
|
|
{
|
|
int64_t hours, minutes, seconds;
|
|
int64_t time;
|
|
|
|
put_bits32(&s->pb, GOP_STARTCODE);
|
|
|
|
time = s->cur_pic.ptr->f->pts;
|
|
if (s->reordered_input_picture[1])
|
|
time = FFMIN(time, s->reordered_input_picture[1]->f->pts);
|
|
time = time * s->avctx->time_base.num;
|
|
s->last_time_base = FFUDIV(time, s->avctx->time_base.den);
|
|
|
|
seconds = FFUDIV(time, s->avctx->time_base.den);
|
|
minutes = FFUDIV(seconds, 60); seconds = FFUMOD(seconds, 60);
|
|
hours = FFUDIV(minutes, 60); minutes = FFUMOD(minutes, 60);
|
|
hours = FFUMOD(hours , 24);
|
|
|
|
put_bits(&s->pb, 5, hours);
|
|
put_bits(&s->pb, 6, minutes);
|
|
put_bits(&s->pb, 1, 1);
|
|
put_bits(&s->pb, 6, seconds);
|
|
|
|
put_bits(&s->pb, 1, !!(s->avctx->flags & AV_CODEC_FLAG_CLOSED_GOP));
|
|
put_bits(&s->pb, 1, 0); // broken link == NO
|
|
|
|
ff_mpeg4_stuffing(&s->pb);
|
|
}
|
|
|
|
static void mpeg4_encode_visual_object_header(MpegEncContext *s)
|
|
{
|
|
int profile_and_level_indication;
|
|
int vo_ver_id;
|
|
|
|
if (s->avctx->profile != AV_PROFILE_UNKNOWN) {
|
|
profile_and_level_indication = s->avctx->profile << 4;
|
|
} else if (s->max_b_frames || s->quarter_sample) {
|
|
profile_and_level_indication = 0xF0; // adv simple
|
|
} else {
|
|
profile_and_level_indication = 0x00; // simple
|
|
}
|
|
|
|
if (s->avctx->level != AV_LEVEL_UNKNOWN)
|
|
profile_and_level_indication |= s->avctx->level;
|
|
else
|
|
profile_and_level_indication |= 1; // level 1
|
|
|
|
if (profile_and_level_indication >> 4 == 0xF)
|
|
vo_ver_id = 5;
|
|
else
|
|
vo_ver_id = 1;
|
|
|
|
// FIXME levels
|
|
|
|
put_bits32(&s->pb, VOS_STARTCODE);
|
|
|
|
put_bits(&s->pb, 8, profile_and_level_indication);
|
|
|
|
put_bits32(&s->pb, VISUAL_OBJ_STARTCODE);
|
|
|
|
put_bits(&s->pb, 1, 1);
|
|
put_bits(&s->pb, 4, vo_ver_id);
|
|
put_bits(&s->pb, 3, 1); // priority
|
|
|
|
put_bits(&s->pb, 4, 1); // visual obj type== video obj
|
|
|
|
put_bits(&s->pb, 1, 0); // video signal type == no clue // FIXME
|
|
|
|
ff_mpeg4_stuffing(&s->pb);
|
|
}
|
|
|
|
static void mpeg4_encode_vol_header(MpegEncContext *s,
|
|
int vo_number,
|
|
int vol_number)
|
|
{
|
|
int vo_ver_id, vo_type, aspect_ratio_info;
|
|
|
|
if (s->max_b_frames || s->quarter_sample) {
|
|
vo_ver_id = 5;
|
|
vo_type = ADV_SIMPLE_VO_TYPE;
|
|
} else {
|
|
vo_ver_id = 1;
|
|
vo_type = SIMPLE_VO_TYPE;
|
|
}
|
|
|
|
put_bits32(&s->pb, 0x100 + vo_number); /* video obj */
|
|
put_bits32(&s->pb, 0x120 + vol_number); /* video obj layer */
|
|
|
|
put_bits(&s->pb, 1, 0); /* random access vol */
|
|
put_bits(&s->pb, 8, vo_type); /* video obj type indication */
|
|
if (s->workaround_bugs & FF_BUG_MS) {
|
|
put_bits(&s->pb, 1, 0); /* is obj layer id= no */
|
|
} else {
|
|
put_bits(&s->pb, 1, 1); /* is obj layer id= yes */
|
|
put_bits(&s->pb, 4, vo_ver_id); /* is obj layer ver id */
|
|
put_bits(&s->pb, 3, 1); /* is obj layer priority */
|
|
}
|
|
|
|
aspect_ratio_info = ff_h263_aspect_to_info(s->avctx->sample_aspect_ratio);
|
|
|
|
put_bits(&s->pb, 4, aspect_ratio_info); /* aspect ratio info */
|
|
if (aspect_ratio_info == FF_ASPECT_EXTENDED) {
|
|
av_reduce(&s->avctx->sample_aspect_ratio.num, &s->avctx->sample_aspect_ratio.den,
|
|
s->avctx->sample_aspect_ratio.num, s->avctx->sample_aspect_ratio.den, 255);
|
|
put_bits(&s->pb, 8, s->avctx->sample_aspect_ratio.num);
|
|
put_bits(&s->pb, 8, s->avctx->sample_aspect_ratio.den);
|
|
}
|
|
|
|
if (s->workaround_bugs & FF_BUG_MS) {
|
|
put_bits(&s->pb, 1, 0); /* vol control parameters= no @@@ */
|
|
} else {
|
|
put_bits(&s->pb, 1, 1); /* vol control parameters= yes */
|
|
put_bits(&s->pb, 2, 1); /* chroma format YUV 420/YV12 */
|
|
put_bits(&s->pb, 1, s->low_delay);
|
|
put_bits(&s->pb, 1, 0); /* vbv parameters= no */
|
|
}
|
|
|
|
put_bits(&s->pb, 2, RECT_SHAPE); /* vol shape= rectangle */
|
|
put_bits(&s->pb, 1, 1); /* marker bit */
|
|
|
|
put_bits(&s->pb, 16, s->avctx->time_base.den);
|
|
if (s->time_increment_bits < 1)
|
|
s->time_increment_bits = 1;
|
|
put_bits(&s->pb, 1, 1); /* marker bit */
|
|
put_bits(&s->pb, 1, 0); /* fixed vop rate=no */
|
|
put_bits(&s->pb, 1, 1); /* marker bit */
|
|
put_bits(&s->pb, 13, s->width); /* vol width */
|
|
put_bits(&s->pb, 1, 1); /* marker bit */
|
|
put_bits(&s->pb, 13, s->height); /* vol height */
|
|
put_bits(&s->pb, 1, 1); /* marker bit */
|
|
put_bits(&s->pb, 1, s->progressive_sequence ? 0 : 1);
|
|
put_bits(&s->pb, 1, 1); /* obmc disable */
|
|
if (vo_ver_id == 1)
|
|
put_bits(&s->pb, 1, 0); /* sprite enable */
|
|
else
|
|
put_bits(&s->pb, 2, 0); /* sprite enable */
|
|
|
|
put_bits(&s->pb, 1, 0); /* not 8 bit == false */
|
|
put_bits(&s->pb, 1, s->mpeg_quant); /* quant type = (0 = H.263 style) */
|
|
|
|
if (s->mpeg_quant) {
|
|
ff_write_quant_matrix(&s->pb, s->avctx->intra_matrix);
|
|
ff_write_quant_matrix(&s->pb, s->avctx->inter_matrix);
|
|
}
|
|
|
|
if (vo_ver_id != 1)
|
|
put_bits(&s->pb, 1, s->quarter_sample);
|
|
put_bits(&s->pb, 1, 1); /* complexity estimation disable */
|
|
put_bits(&s->pb, 1, s->rtp_mode ? 0 : 1); /* resync marker disable */
|
|
put_bits(&s->pb, 1, s->data_partitioning ? 1 : 0);
|
|
if (s->data_partitioning)
|
|
put_bits(&s->pb, 1, 0); /* no rvlc */
|
|
|
|
if (vo_ver_id != 1) {
|
|
put_bits(&s->pb, 1, 0); /* newpred */
|
|
put_bits(&s->pb, 1, 0); /* reduced res vop */
|
|
}
|
|
put_bits(&s->pb, 1, 0); /* scalability */
|
|
|
|
ff_mpeg4_stuffing(&s->pb);
|
|
|
|
/* user data */
|
|
if (!(s->avctx->flags & AV_CODEC_FLAG_BITEXACT)) {
|
|
put_bits32(&s->pb, USER_DATA_STARTCODE);
|
|
ff_put_string(&s->pb, LIBAVCODEC_IDENT, 0);
|
|
}
|
|
}
|
|
|
|
/* write MPEG-4 VOP header */
|
|
int ff_mpeg4_encode_picture_header(MpegEncContext *s)
|
|
{
|
|
uint64_t time_incr;
|
|
int64_t time_div, time_mod;
|
|
|
|
if (s->pict_type == AV_PICTURE_TYPE_I) {
|
|
if (!(s->avctx->flags & AV_CODEC_FLAG_GLOBAL_HEADER)) {
|
|
if (s->avctx->strict_std_compliance < FF_COMPLIANCE_VERY_STRICT) // HACK, the reference sw is buggy
|
|
mpeg4_encode_visual_object_header(s);
|
|
if (s->avctx->strict_std_compliance < FF_COMPLIANCE_VERY_STRICT || s->picture_number == 0) // HACK, the reference sw is buggy
|
|
mpeg4_encode_vol_header(s, 0, 0);
|
|
}
|
|
if (!(s->workaround_bugs & FF_BUG_MS))
|
|
mpeg4_encode_gop_header(s);
|
|
}
|
|
|
|
s->partitioned_frame = s->data_partitioning && s->pict_type != AV_PICTURE_TYPE_B;
|
|
|
|
put_bits32(&s->pb, VOP_STARTCODE); /* vop header */
|
|
put_bits(&s->pb, 2, s->pict_type - 1); /* pict type: I = 0 , P = 1 */
|
|
|
|
time_div = FFUDIV(s->time, s->avctx->time_base.den);
|
|
time_mod = FFUMOD(s->time, s->avctx->time_base.den);
|
|
time_incr = time_div - s->last_time_base;
|
|
|
|
// This limits the frame duration to max 1 day
|
|
if (time_incr > 3600*24) {
|
|
av_log(s->avctx, AV_LOG_ERROR, "time_incr %"PRIu64" too large\n", time_incr);
|
|
return AVERROR(EINVAL);
|
|
}
|
|
while (time_incr--)
|
|
put_bits(&s->pb, 1, 1);
|
|
|
|
put_bits(&s->pb, 1, 0);
|
|
|
|
put_bits(&s->pb, 1, 1); /* marker */
|
|
put_bits(&s->pb, s->time_increment_bits, time_mod); /* time increment */
|
|
put_bits(&s->pb, 1, 1); /* marker */
|
|
put_bits(&s->pb, 1, 1); /* vop coded */
|
|
if (s->pict_type == AV_PICTURE_TYPE_P) {
|
|
put_bits(&s->pb, 1, s->no_rounding); /* rounding type */
|
|
}
|
|
put_bits(&s->pb, 3, 0); /* intra dc VLC threshold */
|
|
if (!s->progressive_sequence) {
|
|
put_bits(&s->pb, 1, !!(s->cur_pic.ptr->f->flags & AV_FRAME_FLAG_TOP_FIELD_FIRST));
|
|
put_bits(&s->pb, 1, s->alternate_scan);
|
|
}
|
|
// FIXME sprite stuff
|
|
|
|
put_bits(&s->pb, 5, s->qscale);
|
|
|
|
if (s->pict_type != AV_PICTURE_TYPE_I)
|
|
put_bits(&s->pb, 3, s->f_code); /* fcode_for */
|
|
if (s->pict_type == AV_PICTURE_TYPE_B)
|
|
put_bits(&s->pb, 3, s->b_code); /* fcode_back */
|
|
|
|
return 0;
|
|
}
|
|
|
|
static av_cold void init_uni_dc_tab(void)
|
|
{
|
|
int level, uni_code, uni_len;
|
|
|
|
for (level = -256; level < 256; level++) {
|
|
int size, v, l;
|
|
/* find number of bits */
|
|
size = 0;
|
|
v = abs(level);
|
|
while (v) {
|
|
v >>= 1;
|
|
size++;
|
|
}
|
|
|
|
if (level < 0)
|
|
l = (-level) ^ ((1 << size) - 1);
|
|
else
|
|
l = level;
|
|
|
|
/* luminance */
|
|
uni_code = ff_mpeg4_DCtab_lum[size][0];
|
|
uni_len = ff_mpeg4_DCtab_lum[size][1];
|
|
|
|
if (size > 0) {
|
|
uni_code <<= size;
|
|
uni_code |= l;
|
|
uni_len += size;
|
|
if (size > 8) {
|
|
uni_code <<= 1;
|
|
uni_code |= 1;
|
|
uni_len++;
|
|
}
|
|
}
|
|
uni_DCtab_lum_bits[level + 256] = uni_code;
|
|
uni_DCtab_lum_len[level + 256] = uni_len;
|
|
|
|
/* chrominance */
|
|
uni_code = ff_mpeg4_DCtab_chrom[size][0];
|
|
uni_len = ff_mpeg4_DCtab_chrom[size][1];
|
|
|
|
if (size > 0) {
|
|
uni_code <<= size;
|
|
uni_code |= l;
|
|
uni_len += size;
|
|
if (size > 8) {
|
|
uni_code <<= 1;
|
|
uni_code |= 1;
|
|
uni_len++;
|
|
}
|
|
}
|
|
uni_DCtab_chrom_bits[level + 256] = uni_code;
|
|
uni_DCtab_chrom_len[level + 256] = uni_len;
|
|
}
|
|
}
|
|
|
|
static av_cold void init_uni_mpeg4_rl_tab(RLTable *rl, uint32_t *bits_tab,
|
|
uint8_t *len_tab)
|
|
{
|
|
int slevel, run, last;
|
|
|
|
av_assert0(MAX_LEVEL >= 64);
|
|
av_assert0(MAX_RUN >= 63);
|
|
|
|
for (slevel = -64; slevel < 64; slevel++) {
|
|
if (slevel == 0)
|
|
continue;
|
|
for (run = 0; run < 64; run++) {
|
|
for (last = 0; last <= 1; last++) {
|
|
const int index = UNI_MPEG4_ENC_INDEX(last, run, slevel + 64);
|
|
int level = slevel < 0 ? -slevel : slevel;
|
|
int sign = slevel < 0 ? 1 : 0;
|
|
int bits, len, code;
|
|
int level1, run1;
|
|
|
|
len_tab[index] = 100;
|
|
|
|
/* ESC0 */
|
|
code = get_rl_index(rl, last, run, level);
|
|
bits = rl->table_vlc[code][0];
|
|
len = rl->table_vlc[code][1];
|
|
bits = bits * 2 + sign;
|
|
len++;
|
|
|
|
if (code != rl->n && len < len_tab[index]) {
|
|
bits_tab[index] = bits;
|
|
len_tab[index] = len;
|
|
}
|
|
/* ESC1 */
|
|
bits = rl->table_vlc[rl->n][0];
|
|
len = rl->table_vlc[rl->n][1];
|
|
bits = bits * 2;
|
|
len++; // esc1
|
|
level1 = level - rl->max_level[last][run];
|
|
if (level1 > 0) {
|
|
code = get_rl_index(rl, last, run, level1);
|
|
bits <<= rl->table_vlc[code][1];
|
|
len += rl->table_vlc[code][1];
|
|
bits += rl->table_vlc[code][0];
|
|
bits = bits * 2 + sign;
|
|
len++;
|
|
|
|
if (code != rl->n && len < len_tab[index]) {
|
|
bits_tab[index] = bits;
|
|
len_tab[index] = len;
|
|
}
|
|
}
|
|
/* ESC2 */
|
|
bits = rl->table_vlc[rl->n][0];
|
|
len = rl->table_vlc[rl->n][1];
|
|
bits = bits * 4 + 2;
|
|
len += 2; // esc2
|
|
run1 = run - rl->max_run[last][level] - 1;
|
|
if (run1 >= 0) {
|
|
code = get_rl_index(rl, last, run1, level);
|
|
bits <<= rl->table_vlc[code][1];
|
|
len += rl->table_vlc[code][1];
|
|
bits += rl->table_vlc[code][0];
|
|
bits = bits * 2 + sign;
|
|
len++;
|
|
|
|
if (code != rl->n && len < len_tab[index]) {
|
|
bits_tab[index] = bits;
|
|
len_tab[index] = len;
|
|
}
|
|
}
|
|
/* ESC3 */
|
|
bits = rl->table_vlc[rl->n][0];
|
|
len = rl->table_vlc[rl->n][1];
|
|
bits = bits * 4 + 3;
|
|
len += 2; // esc3
|
|
bits = bits * 2 + last;
|
|
len++;
|
|
bits = bits * 64 + run;
|
|
len += 6;
|
|
bits = bits * 2 + 1;
|
|
len++; // marker
|
|
bits = bits * 4096 + (slevel & 0xfff);
|
|
len += 12;
|
|
bits = bits * 2 + 1;
|
|
len++; // marker
|
|
|
|
if (len < len_tab[index]) {
|
|
bits_tab[index] = bits;
|
|
len_tab[index] = len;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
static av_cold void mpeg4_encode_init_static(void)
|
|
{
|
|
init_uni_dc_tab();
|
|
|
|
ff_mpeg4_init_rl_intra();
|
|
|
|
init_uni_mpeg4_rl_tab(&ff_mpeg4_rl_intra, uni_mpeg4_intra_rl_bits, uni_mpeg4_intra_rl_len);
|
|
init_uni_mpeg4_rl_tab(&ff_h263_rl_inter, uni_mpeg4_inter_rl_bits, uni_mpeg4_inter_rl_len);
|
|
}
|
|
|
|
static av_cold int encode_init(AVCodecContext *avctx)
|
|
{
|
|
static AVOnce init_static_once = AV_ONCE_INIT;
|
|
MpegEncContext *s = avctx->priv_data;
|
|
int ret;
|
|
|
|
if (avctx->width >= (1<<13) || avctx->height >= (1<<13)) {
|
|
av_log(avctx, AV_LOG_ERROR, "dimensions too large for MPEG-4\n");
|
|
return AVERROR(EINVAL);
|
|
}
|
|
|
|
ff_qpeldsp_init(&s->qdsp);
|
|
if ((ret = ff_mpv_encode_init(avctx)) < 0)
|
|
return ret;
|
|
|
|
ff_thread_once(&init_static_once, mpeg4_encode_init_static);
|
|
|
|
s->min_qcoeff = -2048;
|
|
s->max_qcoeff = 2047;
|
|
s->intra_ac_vlc_length = uni_mpeg4_intra_rl_len;
|
|
s->intra_ac_vlc_last_length = uni_mpeg4_intra_rl_len + 128 * 64;
|
|
s->inter_ac_vlc_length = uni_mpeg4_inter_rl_len;
|
|
s->inter_ac_vlc_last_length = uni_mpeg4_inter_rl_len + 128 * 64;
|
|
s->luma_dc_vlc_length = uni_DCtab_lum_len;
|
|
s->ac_esc_length = 7 + 2 + 1 + 6 + 1 + 12 + 1;
|
|
s->y_dc_scale_table = ff_mpeg4_y_dc_scale_table;
|
|
s->c_dc_scale_table = ff_mpeg4_c_dc_scale_table;
|
|
|
|
if (s->avctx->flags & AV_CODEC_FLAG_GLOBAL_HEADER) {
|
|
s->avctx->extradata = av_malloc(1024);
|
|
if (!s->avctx->extradata)
|
|
return AVERROR(ENOMEM);
|
|
init_put_bits(&s->pb, s->avctx->extradata, 1024);
|
|
|
|
if (!(s->workaround_bugs & FF_BUG_MS))
|
|
mpeg4_encode_visual_object_header(s);
|
|
mpeg4_encode_vol_header(s, 0, 0);
|
|
|
|
// ff_mpeg4_stuffing(&s->pb); ?
|
|
flush_put_bits(&s->pb);
|
|
s->avctx->extradata_size = put_bytes_output(&s->pb);
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
void ff_mpeg4_init_partitions(MpegEncContext *s)
|
|
{
|
|
uint8_t *start = put_bits_ptr(&s->pb);
|
|
uint8_t *end = s->pb.buf_end;
|
|
int size = end - start;
|
|
int pb_size = (((intptr_t)start + size / 3) & (~3)) - (intptr_t)start;
|
|
int tex_size = (size - 2 * pb_size) & (~3);
|
|
|
|
set_put_bits_buffer_size(&s->pb, pb_size);
|
|
init_put_bits(&s->tex_pb, start + pb_size, tex_size);
|
|
init_put_bits(&s->pb2, start + pb_size + tex_size, pb_size);
|
|
}
|
|
|
|
void ff_mpeg4_merge_partitions(MpegEncContext *s)
|
|
{
|
|
const int pb2_len = put_bits_count(&s->pb2);
|
|
const int tex_pb_len = put_bits_count(&s->tex_pb);
|
|
const int bits = put_bits_count(&s->pb);
|
|
|
|
if (s->pict_type == AV_PICTURE_TYPE_I) {
|
|
put_bits(&s->pb, 19, DC_MARKER);
|
|
s->misc_bits += 19 + pb2_len + bits - s->last_bits;
|
|
s->i_tex_bits += tex_pb_len;
|
|
} else {
|
|
put_bits(&s->pb, 17, MOTION_MARKER);
|
|
s->misc_bits += 17 + pb2_len;
|
|
s->mv_bits += bits - s->last_bits;
|
|
s->p_tex_bits += tex_pb_len;
|
|
}
|
|
|
|
flush_put_bits(&s->pb2);
|
|
flush_put_bits(&s->tex_pb);
|
|
|
|
set_put_bits_buffer_size(&s->pb, s->pb2.buf_end - s->pb.buf);
|
|
ff_copy_bits(&s->pb, s->pb2.buf, pb2_len);
|
|
ff_copy_bits(&s->pb, s->tex_pb.buf, tex_pb_len);
|
|
s->last_bits = put_bits_count(&s->pb);
|
|
}
|
|
|
|
void ff_mpeg4_encode_video_packet_header(MpegEncContext *s)
|
|
{
|
|
int mb_num_bits = av_log2(s->mb_num - 1) + 1;
|
|
|
|
put_bits(&s->pb, ff_mpeg4_get_video_packet_prefix_length(s), 0);
|
|
put_bits(&s->pb, 1, 1);
|
|
|
|
put_bits(&s->pb, mb_num_bits, s->mb_x + s->mb_y * s->mb_width);
|
|
put_bits(&s->pb, 5 /* quant_precision */, s->qscale);
|
|
put_bits(&s->pb, 1, 0); /* no HEC */
|
|
}
|
|
|
|
#define OFFSET(x) offsetof(MpegEncContext, x)
|
|
#define VE AV_OPT_FLAG_VIDEO_PARAM | AV_OPT_FLAG_ENCODING_PARAM
|
|
static const AVOption options[] = {
|
|
{ "data_partitioning", "Use data partitioning.", OFFSET(data_partitioning), 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 },
|
|
{ "mpeg_quant", "Use MPEG quantizers instead of H.263",
|
|
OFFSET(mpeg_quant), AV_OPT_TYPE_INT, {.i64 = 0 }, 0, 1, VE },
|
|
FF_MPV_COMMON_BFRAME_OPTS
|
|
FF_MPV_COMMON_OPTS
|
|
FF_MPV_COMMON_MOTION_EST_OPTS
|
|
FF_MPEG4_PROFILE_OPTS
|
|
{ NULL },
|
|
};
|
|
|
|
static const AVClass mpeg4enc_class = {
|
|
.class_name = "MPEG4 encoder",
|
|
.item_name = av_default_item_name,
|
|
.option = options,
|
|
.version = LIBAVUTIL_VERSION_INT,
|
|
};
|
|
|
|
const FFCodec ff_mpeg4_encoder = {
|
|
.p.name = "mpeg4",
|
|
CODEC_LONG_NAME("MPEG-4 part 2"),
|
|
.p.type = AVMEDIA_TYPE_VIDEO,
|
|
.p.id = AV_CODEC_ID_MPEG4,
|
|
.priv_data_size = sizeof(MpegEncContext),
|
|
.init = encode_init,
|
|
FF_CODEC_ENCODE_CB(ff_mpv_encode_picture),
|
|
.close = ff_mpv_encode_end,
|
|
.p.pix_fmts = (const enum AVPixelFormat[]) { AV_PIX_FMT_YUV420P, AV_PIX_FMT_NONE },
|
|
.color_ranges = AVCOL_RANGE_MPEG,
|
|
.p.capabilities = AV_CODEC_CAP_DELAY | AV_CODEC_CAP_SLICE_THREADS |
|
|
AV_CODEC_CAP_ENCODER_REORDERED_OPAQUE,
|
|
.caps_internal = FF_CODEC_CAP_INIT_CLEANUP,
|
|
.p.priv_class = &mpeg4enc_class,
|
|
};
|