2012-02-18 14:28:43 +01:00
|
|
|
/*
|
|
|
|
|
* MSMPEG4 encoder backend
|
|
|
|
|
* Copyright (c) 2001 Fabrice Bellard
|
|
|
|
|
* Copyright (c) 2002-2004 Michael Niedermayer <michaelni@gmx.at>
|
|
|
|
|
*
|
|
|
|
|
* msmpeg4v1 & v2 stuff by Michael Niedermayer <michaelni@gmx.at>
|
|
|
|
|
*
|
2012-03-03 00:09:47 +01:00
|
|
|
* This file is part of FFmpeg.
|
2012-02-18 14:28:43 +01:00
|
|
|
*
|
2012-03-03 00:09:47 +01:00
|
|
|
* FFmpeg is free software; you can redistribute it and/or
|
2012-02-18 14:28:43 +01:00
|
|
|
* 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.
|
|
|
|
|
*
|
2012-03-03 00:09:47 +01:00
|
|
|
* FFmpeg is distributed in the hope that it will be useful,
|
2012-02-18 14:28:43 +01:00
|
|
|
* 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
|
2012-03-03 00:09:47 +01:00
|
|
|
* License along with FFmpeg; if not, write to the Free Software
|
2012-02-18 14:28:43 +01:00
|
|
|
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* @file
|
|
|
|
|
* MSMPEG4 encoder backend
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
#include <stdint.h>
|
|
|
|
|
#include <string.h>
|
|
|
|
|
|
2025-03-15 07:25:15 +01:00
|
|
|
#define NO_SLICE_THREADING_HERE
|
|
|
|
|
|
2013-02-01 10:31:59 +01:00
|
|
|
#include "libavutil/attributes.h"
|
2012-02-18 14:28:43 +01:00
|
|
|
#include "libavutil/avutil.h"
|
2020-12-10 07:26:31 +01:00
|
|
|
#include "libavutil/thread.h"
|
2022-03-16 18:18:28 +01:00
|
|
|
#include "codec_internal.h"
|
2012-02-18 14:28:43 +01:00
|
|
|
#include "mpegvideo.h"
|
2022-01-28 01:14:42 +01:00
|
|
|
#include "mpegvideoenc.h"
|
2012-02-18 14:28:43 +01:00
|
|
|
#include "h263.h"
|
2022-01-28 00:59:24 +01:00
|
|
|
#include "h263data.h"
|
2012-02-18 14:28:43 +01:00
|
|
|
#include "mpeg4video.h"
|
|
|
|
|
#include "msmpeg4.h"
|
|
|
|
|
#include "msmpeg4data.h"
|
2022-10-30 16:32:00 +01:00
|
|
|
#include "msmpeg4_vc1_data.h"
|
2022-01-27 23:55:02 +01:00
|
|
|
#include "msmpeg4enc.h"
|
2012-02-18 14:28:43 +01:00
|
|
|
#include "put_bits.h"
|
|
|
|
|
#include "rl.h"
|
|
|
|
|
|
|
|
|
|
static uint8_t rl_length[NB_RL_TABLES][MAX_LEVEL+1][MAX_RUN+1][2];
|
|
|
|
|
|
2025-03-15 08:25:24 +01:00
|
|
|
// The lowest 8 bits of each entry are length, the other bits are the code.
|
|
|
|
|
// The index of the (mx, my) entry is (mx * 64) + my.
|
|
|
|
|
static uint32_t mv_vector_tables[2][4096];
|
|
|
|
|
|
2012-02-18 14:28:43 +01:00
|
|
|
/* build the table which associate a (x,y) motion vector to a vlc */
|
2025-03-15 11:08:38 +01:00
|
|
|
static av_cold void init_mv_table(const uint16_t mv_table[], const uint8_t mv_table_lens[],
|
|
|
|
|
uint32_t mv_vector_table[4096],
|
2025-03-15 08:25:24 +01:00
|
|
|
unsigned escape_code, int escape_length)
|
2012-02-18 14:28:43 +01:00
|
|
|
{
|
2025-03-15 08:25:24 +01:00
|
|
|
for (int i = 0; i < 4096; i++) {
|
|
|
|
|
// Initialize to the table to "escaped". This code is equivalent to
|
|
|
|
|
// the following double loop (with x and y ranging over 0..63):
|
|
|
|
|
// tab[x * 64 + y] = (esc_code << 20) | (x << 14) | (y << 8) | esc_length
|
|
|
|
|
mv_vector_table[i] = (escape_code << 20) | (i << 8) | escape_length;
|
|
|
|
|
}
|
2012-02-18 14:28:43 +01:00
|
|
|
|
2025-03-15 11:08:38 +01:00
|
|
|
for (uint32_t i = 0, code = 0; i < MSMPEG4_MV_TABLES_NB_ELEMS; i++) {
|
|
|
|
|
int sym = mv_table[i];
|
|
|
|
|
int len = mv_table_lens[i];
|
|
|
|
|
int x = sym >> 8;
|
|
|
|
|
int y = sym & 0xFF;
|
|
|
|
|
// We ignore the escape value here and restore it after the loop.
|
|
|
|
|
mv_vector_table[(x << 6) | y] = (code >> (24 - len)) | len;
|
|
|
|
|
code += 1U << (32 - len);
|
2012-02-18 14:28:43 +01:00
|
|
|
}
|
2025-03-15 11:08:38 +01:00
|
|
|
mv_vector_table[0] = (escape_code << 20) | escape_length;
|
2012-02-18 14:28:43 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void ff_msmpeg4_code012(PutBitContext *pb, int n)
|
|
|
|
|
{
|
|
|
|
|
if (n == 0) {
|
|
|
|
|
put_bits(pb, 1, 0);
|
|
|
|
|
} else {
|
2024-06-10 00:11:05 +02:00
|
|
|
put_bits(pb, 2, 2 | (n >= 2));
|
2012-02-18 14:28:43 +01:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2020-12-10 07:26:31 +01:00
|
|
|
static int get_size_of_code(const RLTable *rl, int last, int run,
|
|
|
|
|
int level, int intra)
|
|
|
|
|
{
|
2012-02-18 14:28:43 +01:00
|
|
|
int size=0;
|
|
|
|
|
int code;
|
|
|
|
|
int run_diff= intra ? 0 : 1;
|
|
|
|
|
|
|
|
|
|
code = get_rl_index(rl, last, run, level);
|
|
|
|
|
size+= rl->table_vlc[code][1];
|
|
|
|
|
if (code == rl->n) {
|
|
|
|
|
int level1, run1;
|
|
|
|
|
|
|
|
|
|
level1 = level - rl->max_level[last][run];
|
|
|
|
|
if (level1 < 1)
|
|
|
|
|
goto esc2;
|
|
|
|
|
code = get_rl_index(rl, last, run, level1);
|
|
|
|
|
if (code == rl->n) {
|
|
|
|
|
esc2:
|
|
|
|
|
size++;
|
|
|
|
|
if (level > MAX_LEVEL)
|
|
|
|
|
goto esc3;
|
|
|
|
|
run1 = run - rl->max_run[last][level] - run_diff;
|
|
|
|
|
if (run1 < 0)
|
|
|
|
|
goto esc3;
|
|
|
|
|
code = get_rl_index(rl, last, run1, level);
|
|
|
|
|
if (code == rl->n) {
|
|
|
|
|
esc3:
|
|
|
|
|
/* third escape */
|
|
|
|
|
size+=1+1+6+8;
|
|
|
|
|
} else {
|
|
|
|
|
/* second escape */
|
|
|
|
|
size+= 1+1+ rl->table_vlc[code][1];
|
|
|
|
|
}
|
|
|
|
|
} else {
|
|
|
|
|
/* first escape */
|
|
|
|
|
size+= 1+1+ rl->table_vlc[code][1];
|
|
|
|
|
}
|
|
|
|
|
} else {
|
|
|
|
|
size++;
|
|
|
|
|
}
|
|
|
|
|
return size;
|
|
|
|
|
}
|
|
|
|
|
|
2020-12-10 07:26:31 +01:00
|
|
|
static av_cold void msmpeg4_encode_init_static(void)
|
2012-02-18 14:28:43 +01:00
|
|
|
{
|
2025-03-15 11:08:38 +01:00
|
|
|
init_mv_table(ff_msmp4_mv_table0, ff_msmp4_mv_table0_lens,
|
|
|
|
|
mv_vector_tables[0], 0x0000, 8 + 12);
|
|
|
|
|
init_mv_table(ff_msmp4_mv_table1, ff_msmp4_mv_table1_lens,
|
|
|
|
|
mv_vector_tables[1], 0x000b, 4 + 12);
|
2020-12-10 07:33:46 +01:00
|
|
|
|
|
|
|
|
for (int i = 0; i < NB_RL_TABLES; i++) {
|
|
|
|
|
for (int level = 1; level <= MAX_LEVEL; level++) {
|
|
|
|
|
for (int run = 0; run <= MAX_RUN; run++) {
|
|
|
|
|
for (int last = 0; last < 2; last++) {
|
|
|
|
|
rl_length[i][level][run][last] = get_size_of_code(&ff_rl_table[i], last, run, level, 0);
|
2012-02-18 14:28:43 +01:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
2020-12-10 07:33:46 +01:00
|
|
|
}
|
2020-12-10 07:26:31 +01:00
|
|
|
}
|
|
|
|
|
|
2022-01-28 00:21:32 +01:00
|
|
|
static void find_best_tables(MSMPEG4EncContext *ms)
|
2012-02-18 14:28:43 +01:00
|
|
|
{
|
2025-02-28 18:56:15 +01:00
|
|
|
MpegEncContext *const s = &ms->m.s;
|
2012-02-18 14:28:43 +01:00
|
|
|
int i;
|
2012-03-03 00:09:47 +01:00
|
|
|
int best = 0, best_size = INT_MAX;
|
|
|
|
|
int chroma_best = 0, best_chroma_size = INT_MAX;
|
2012-02-18 14:28:43 +01:00
|
|
|
|
|
|
|
|
for(i=0; i<3; i++){
|
|
|
|
|
int level;
|
|
|
|
|
int chroma_size=0;
|
|
|
|
|
int size=0;
|
|
|
|
|
|
|
|
|
|
if(i>0){// ;)
|
|
|
|
|
size++;
|
|
|
|
|
chroma_size++;
|
|
|
|
|
}
|
|
|
|
|
for(level=0; level<=MAX_LEVEL; level++){
|
|
|
|
|
int run;
|
|
|
|
|
for(run=0; run<=MAX_RUN; run++){
|
|
|
|
|
int last;
|
|
|
|
|
const int last_size= size + chroma_size;
|
|
|
|
|
for(last=0; last<2; last++){
|
2022-01-28 00:21:32 +01:00
|
|
|
int inter_count = ms->ac_stats[0][0][level][run][last] + ms->ac_stats[0][1][level][run][last];
|
|
|
|
|
int intra_luma_count = ms->ac_stats[1][0][level][run][last];
|
|
|
|
|
int intra_chroma_count= ms->ac_stats[1][1][level][run][last];
|
2012-02-18 14:28:43 +01:00
|
|
|
|
|
|
|
|
if(s->pict_type==AV_PICTURE_TYPE_I){
|
|
|
|
|
size += intra_luma_count *rl_length[i ][level][run][last];
|
|
|
|
|
chroma_size+= intra_chroma_count*rl_length[i+3][level][run][last];
|
|
|
|
|
}else{
|
|
|
|
|
size+= intra_luma_count *rl_length[i ][level][run][last]
|
|
|
|
|
+intra_chroma_count*rl_length[i+3][level][run][last]
|
|
|
|
|
+inter_count *rl_length[i+3][level][run][last];
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
if(last_size == size+chroma_size) break;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
if(size<best_size){
|
|
|
|
|
best_size= size;
|
|
|
|
|
best= i;
|
|
|
|
|
}
|
|
|
|
|
if(chroma_size<best_chroma_size){
|
|
|
|
|
best_chroma_size= chroma_size;
|
|
|
|
|
chroma_best= i;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if(s->pict_type==AV_PICTURE_TYPE_P) chroma_best= best;
|
|
|
|
|
|
2022-01-28 00:21:32 +01:00
|
|
|
memset(ms->ac_stats, 0, sizeof(ms->ac_stats));
|
2012-02-18 14:28:43 +01:00
|
|
|
|
2025-03-18 13:21:23 +01:00
|
|
|
ms->rl_table_index = best;
|
|
|
|
|
ms->rl_chroma_table_index = chroma_best;
|
2012-02-18 14:28:43 +01:00
|
|
|
|
|
|
|
|
if(s->pict_type != s->last_non_b_pict_type){
|
2025-03-18 13:21:23 +01:00
|
|
|
ms->rl_table_index = 2;
|
2012-02-18 14:28:43 +01:00
|
|
|
if(s->pict_type==AV_PICTURE_TYPE_I)
|
2025-03-18 13:21:23 +01:00
|
|
|
ms->rl_chroma_table_index = 1;
|
2012-02-18 14:28:43 +01:00
|
|
|
else
|
2025-03-18 13:21:23 +01:00
|
|
|
ms->rl_chroma_table_index = 2;
|
2012-02-18 14:28:43 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* write MSMPEG4 compatible frame header */
|
2025-03-03 23:35:01 +01:00
|
|
|
static int msmpeg4_encode_picture_header(MPVMainEncContext *const m)
|
2012-02-18 14:28:43 +01:00
|
|
|
{
|
2025-03-03 23:35:01 +01:00
|
|
|
MSMPEG4EncContext *const ms = (MSMPEG4EncContext*)m;
|
|
|
|
|
MpegEncContext *const s = &m->s;
|
2022-01-28 00:21:32 +01:00
|
|
|
|
|
|
|
|
find_best_tables(ms);
|
2012-02-18 14:28:43 +01:00
|
|
|
|
2020-10-26 13:36:06 +01:00
|
|
|
align_put_bits(&s->pb);
|
2012-02-18 14:28:43 +01:00
|
|
|
put_bits(&s->pb, 2, s->pict_type - 1);
|
|
|
|
|
|
|
|
|
|
put_bits(&s->pb, 5, s->qscale);
|
2024-04-28 23:18:35 +02:00
|
|
|
if (s->msmpeg4_version <= MSMP4_V2) {
|
2025-03-18 13:21:23 +01:00
|
|
|
ms->rl_table_index = 2;
|
|
|
|
|
ms->rl_chroma_table_index = 2;
|
2012-02-18 14:28:43 +01:00
|
|
|
}
|
|
|
|
|
|
2025-03-18 13:21:23 +01:00
|
|
|
ms->dc_table_index = 1;
|
|
|
|
|
ms->mv_table_index = 1; /* only if P-frame */
|
|
|
|
|
ms->use_skip_mb_code = 1; /* only if P-frame */
|
|
|
|
|
ms->per_mb_rl_table = 0;
|
2024-04-28 23:18:35 +02:00
|
|
|
if (s->msmpeg4_version == MSMP4_WMV1)
|
2025-03-15 07:25:15 +01:00
|
|
|
s->inter_intra_pred = s->width * s->height < 320*240 &&
|
|
|
|
|
m->bit_rate <= II_BITRATE &&
|
|
|
|
|
s->pict_type == AV_PICTURE_TYPE_P;
|
|
|
|
|
ff_dlog(s->avctx, "%d %"PRId64" %d %d %d\n", s->pict_type, m->bit_rate,
|
2012-08-21 12:41:40 +02:00
|
|
|
s->inter_intra_pred, s->width, s->height);
|
2012-02-18 14:28:43 +01:00
|
|
|
|
|
|
|
|
if (s->pict_type == AV_PICTURE_TYPE_I) {
|
|
|
|
|
s->slice_height= s->mb_height/1;
|
|
|
|
|
put_bits(&s->pb, 5, 0x16 + s->mb_height/s->slice_height);
|
|
|
|
|
|
2024-04-28 23:18:35 +02:00
|
|
|
if (s->msmpeg4_version == MSMP4_WMV1) {
|
2012-02-18 14:28:43 +01:00
|
|
|
ff_msmpeg4_encode_ext_header(s);
|
2025-03-15 07:25:15 +01:00
|
|
|
if (m->bit_rate > MBAC_BITRATE)
|
2025-03-18 13:21:23 +01:00
|
|
|
put_bits(&s->pb, 1, ms->per_mb_rl_table);
|
2012-02-18 14:28:43 +01:00
|
|
|
}
|
|
|
|
|
|
2024-04-28 23:18:35 +02:00
|
|
|
if (s->msmpeg4_version > MSMP4_V2) {
|
2025-03-18 13:21:23 +01:00
|
|
|
if (!ms->per_mb_rl_table){
|
|
|
|
|
ff_msmpeg4_code012(&s->pb, ms->rl_chroma_table_index);
|
|
|
|
|
ff_msmpeg4_code012(&s->pb, ms->rl_table_index);
|
2012-02-18 14:28:43 +01:00
|
|
|
}
|
|
|
|
|
|
2025-03-18 13:21:23 +01:00
|
|
|
put_bits(&s->pb, 1, ms->dc_table_index);
|
2012-02-18 14:28:43 +01:00
|
|
|
}
|
|
|
|
|
} else {
|
2025-03-18 13:21:23 +01:00
|
|
|
put_bits(&s->pb, 1, ms->use_skip_mb_code);
|
2012-02-18 14:28:43 +01:00
|
|
|
|
2025-03-15 07:25:15 +01:00
|
|
|
if (s->msmpeg4_version == MSMP4_WMV1 && m->bit_rate > MBAC_BITRATE)
|
2025-03-18 13:21:23 +01:00
|
|
|
put_bits(&s->pb, 1, ms->per_mb_rl_table);
|
2012-02-18 14:28:43 +01:00
|
|
|
|
2024-04-28 23:18:35 +02:00
|
|
|
if (s->msmpeg4_version > MSMP4_V2) {
|
2025-03-18 13:21:23 +01:00
|
|
|
if (!ms->per_mb_rl_table)
|
|
|
|
|
ff_msmpeg4_code012(&s->pb, ms->rl_table_index);
|
2012-02-18 14:28:43 +01:00
|
|
|
|
2025-03-18 13:21:23 +01:00
|
|
|
put_bits(&s->pb, 1, ms->dc_table_index);
|
2012-02-18 14:28:43 +01:00
|
|
|
|
2025-03-18 13:21:23 +01:00
|
|
|
put_bits(&s->pb, 1, ms->mv_table_index);
|
2012-02-18 14:28:43 +01:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2025-03-18 13:21:23 +01:00
|
|
|
s->esc3_level_length = 0;
|
|
|
|
|
ms->esc3_run_length = 0;
|
2025-03-03 23:35:01 +01:00
|
|
|
|
|
|
|
|
return 0;
|
2012-02-18 14:28:43 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void ff_msmpeg4_encode_ext_header(MpegEncContext * s)
|
|
|
|
|
{
|
2025-03-15 07:25:15 +01:00
|
|
|
const MPVMainEncContext *const m = slice_to_mainenc(s);
|
2023-05-04 11:45:29 +02:00
|
|
|
unsigned fps;
|
|
|
|
|
|
|
|
|
|
if (s->avctx->framerate.num > 0 && s->avctx->framerate.den > 0)
|
|
|
|
|
fps = s->avctx->framerate.num / s->avctx->framerate.den;
|
2023-07-22 19:24:15 +02:00
|
|
|
else {
|
2023-05-04 11:50:48 +02:00
|
|
|
FF_DISABLE_DEPRECATION_WARNINGS
|
|
|
|
|
fps = s->avctx->time_base.den / s->avctx->time_base.num
|
|
|
|
|
#if FF_API_TICKS_PER_FRAME
|
|
|
|
|
/ FFMAX(s->avctx->ticks_per_frame, 1)
|
|
|
|
|
#endif
|
|
|
|
|
;
|
|
|
|
|
FF_ENABLE_DEPRECATION_WARNINGS
|
2023-07-22 19:24:15 +02:00
|
|
|
}
|
2023-05-04 11:45:29 +02:00
|
|
|
|
2022-10-02 23:38:01 +02:00
|
|
|
put_bits(&s->pb, 5, FFMIN(fps, 31)); //yes 29.97 -> 29
|
2012-02-18 14:28:43 +01:00
|
|
|
|
2025-03-15 07:25:15 +01:00
|
|
|
put_bits(&s->pb, 11, FFMIN(m->bit_rate / 1024, 2047));
|
2012-02-18 14:28:43 +01:00
|
|
|
|
2024-04-28 23:18:35 +02:00
|
|
|
if (s->msmpeg4_version >= MSMP4_V3)
|
2022-10-02 23:38:01 +02:00
|
|
|
put_bits(&s->pb, 1, s->flipflop_rounding);
|
|
|
|
|
else
|
|
|
|
|
av_assert0(!s->flipflop_rounding);
|
2012-02-18 14:28:43 +01:00
|
|
|
}
|
|
|
|
|
|
2025-03-18 13:21:23 +01:00
|
|
|
void ff_msmpeg4_encode_motion(MSMPEG4EncContext *const ms,
|
2012-02-18 14:28:43 +01:00
|
|
|
int mx, int my)
|
|
|
|
|
{
|
2025-03-18 13:21:23 +01:00
|
|
|
MpegEncContext *const s = &ms->m.s;
|
|
|
|
|
const uint32_t *const mv_vector_table = mv_vector_tables[ms->mv_table_index];
|
2025-03-15 08:25:24 +01:00
|
|
|
uint32_t code;
|
2012-02-18 14:28:43 +01:00
|
|
|
|
|
|
|
|
/* modulo encoding */
|
|
|
|
|
/* WARNING : you cannot reach all the MVs even with the modulo
|
|
|
|
|
encoding. This is a somewhat strange compromise they took !!! */
|
|
|
|
|
if (mx <= -64)
|
|
|
|
|
mx += 64;
|
|
|
|
|
else if (mx >= 64)
|
|
|
|
|
mx -= 64;
|
|
|
|
|
if (my <= -64)
|
|
|
|
|
my += 64;
|
|
|
|
|
else if (my >= 64)
|
|
|
|
|
my -= 64;
|
|
|
|
|
|
|
|
|
|
mx += 32;
|
|
|
|
|
my += 32;
|
2025-03-15 08:25:24 +01:00
|
|
|
|
|
|
|
|
code = mv_vector_table[(mx << 6) | my];
|
|
|
|
|
put_bits(&s->pb, code & 0xff, code >> 8);
|
2012-02-18 14:28:43 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void ff_msmpeg4_handle_slices(MpegEncContext *s){
|
|
|
|
|
if (s->mb_x == 0) {
|
|
|
|
|
if (s->slice_height && (s->mb_y % s->slice_height) == 0) {
|
2024-04-28 23:18:35 +02:00
|
|
|
if (s->msmpeg4_version < MSMP4_WMV1) {
|
2012-02-18 14:28:43 +01:00
|
|
|
ff_mpeg4_clean_buffers(s);
|
|
|
|
|
}
|
|
|
|
|
s->first_slice_line = 1;
|
|
|
|
|
} else {
|
|
|
|
|
s->first_slice_line = 0;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void msmpeg4v2_encode_motion(MpegEncContext * s, int val)
|
|
|
|
|
{
|
|
|
|
|
int range, bit_size, sign, code, bits;
|
|
|
|
|
|
|
|
|
|
if (val == 0) {
|
2025-03-07 15:42:18 +01:00
|
|
|
/* zero vector; corresponds to ff_mvtab[0] */
|
|
|
|
|
put_bits(&s->pb, 1, 0x1);
|
2012-02-18 14:28:43 +01:00
|
|
|
} else {
|
|
|
|
|
bit_size = s->f_code - 1;
|
|
|
|
|
range = 1 << bit_size;
|
|
|
|
|
if (val <= -64)
|
|
|
|
|
val += 64;
|
|
|
|
|
else if (val >= 64)
|
|
|
|
|
val -= 64;
|
|
|
|
|
|
|
|
|
|
if (val >= 0) {
|
|
|
|
|
sign = 0;
|
|
|
|
|
} else {
|
|
|
|
|
val = -val;
|
|
|
|
|
sign = 1;
|
|
|
|
|
}
|
|
|
|
|
val--;
|
|
|
|
|
code = (val >> bit_size) + 1;
|
|
|
|
|
bits = val & (range - 1);
|
|
|
|
|
|
|
|
|
|
put_bits(&s->pb, ff_mvtab[code][1] + 1, (ff_mvtab[code][0] << 1) | sign);
|
|
|
|
|
if (bit_size > 0) {
|
|
|
|
|
put_bits(&s->pb, bit_size, bits);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2025-03-04 19:09:24 +01:00
|
|
|
static void msmpeg4_encode_mb(MpegEncContext *const s,
|
|
|
|
|
int16_t block[][64],
|
|
|
|
|
int motion_x, int motion_y)
|
2012-02-18 14:28:43 +01:00
|
|
|
{
|
2025-03-18 13:21:23 +01:00
|
|
|
MSMPEG4EncContext *const ms = mpv_to_msmpeg4(s);
|
2012-02-18 14:28:43 +01:00
|
|
|
int cbp, coded_cbp, i;
|
|
|
|
|
int pred_x, pred_y;
|
|
|
|
|
|
|
|
|
|
ff_msmpeg4_handle_slices(s);
|
|
|
|
|
|
|
|
|
|
if (!s->mb_intra) {
|
|
|
|
|
/* compute cbp */
|
|
|
|
|
cbp = 0;
|
|
|
|
|
for (i = 0; i < 6; i++) {
|
|
|
|
|
if (s->block_last_index[i] >= 0)
|
|
|
|
|
cbp |= 1 << (5 - i);
|
|
|
|
|
}
|
2025-03-18 13:21:23 +01:00
|
|
|
if (ms->use_skip_mb_code && (cbp | motion_x | motion_y) == 0) {
|
2012-02-18 14:28:43 +01:00
|
|
|
/* skip macroblock */
|
|
|
|
|
put_bits(&s->pb, 1, 1);
|
|
|
|
|
s->last_bits++;
|
|
|
|
|
s->misc_bits++;
|
|
|
|
|
|
|
|
|
|
return;
|
|
|
|
|
}
|
2025-03-18 13:21:23 +01:00
|
|
|
if (ms->use_skip_mb_code)
|
2012-02-18 14:28:43 +01:00
|
|
|
put_bits(&s->pb, 1, 0); /* mb coded */
|
|
|
|
|
|
2024-04-28 23:18:35 +02:00
|
|
|
if (s->msmpeg4_version <= MSMP4_V2) {
|
2012-02-18 14:28:43 +01:00
|
|
|
put_bits(&s->pb,
|
|
|
|
|
ff_v2_mb_type[cbp&3][1],
|
|
|
|
|
ff_v2_mb_type[cbp&3][0]);
|
|
|
|
|
if((cbp&3) != 3) coded_cbp= cbp ^ 0x3C;
|
|
|
|
|
else coded_cbp= cbp;
|
|
|
|
|
|
|
|
|
|
put_bits(&s->pb,
|
|
|
|
|
ff_h263_cbpy_tab[coded_cbp>>2][1],
|
|
|
|
|
ff_h263_cbpy_tab[coded_cbp>>2][0]);
|
|
|
|
|
|
|
|
|
|
s->misc_bits += get_bits_diff(s);
|
|
|
|
|
|
|
|
|
|
ff_h263_pred_motion(s, 0, 0, &pred_x, &pred_y);
|
|
|
|
|
msmpeg4v2_encode_motion(s, motion_x - pred_x);
|
|
|
|
|
msmpeg4v2_encode_motion(s, motion_y - pred_y);
|
|
|
|
|
}else{
|
|
|
|
|
put_bits(&s->pb,
|
|
|
|
|
ff_table_mb_non_intra[cbp + 64][1],
|
|
|
|
|
ff_table_mb_non_intra[cbp + 64][0]);
|
|
|
|
|
|
|
|
|
|
s->misc_bits += get_bits_diff(s);
|
|
|
|
|
|
|
|
|
|
/* motion vector */
|
|
|
|
|
ff_h263_pred_motion(s, 0, 0, &pred_x, &pred_y);
|
2025-03-18 13:21:23 +01:00
|
|
|
ff_msmpeg4_encode_motion(ms, motion_x - pred_x,
|
|
|
|
|
motion_y - pred_y);
|
2012-02-18 14:28:43 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
s->mv_bits += get_bits_diff(s);
|
|
|
|
|
|
|
|
|
|
for (i = 0; i < 6; i++) {
|
|
|
|
|
ff_msmpeg4_encode_block(s, block[i], i);
|
|
|
|
|
}
|
|
|
|
|
s->p_tex_bits += get_bits_diff(s);
|
|
|
|
|
} else {
|
|
|
|
|
/* compute cbp */
|
|
|
|
|
cbp = 0;
|
2024-04-20 22:11:55 +02:00
|
|
|
for (int i = 0; i < 6; i++) {
|
|
|
|
|
int val = (s->block_last_index[i] >= 1);
|
2012-02-18 14:28:43 +01:00
|
|
|
cbp |= val << (5 - i);
|
|
|
|
|
}
|
2024-04-28 23:18:35 +02:00
|
|
|
if (s->msmpeg4_version <= MSMP4_V2) {
|
2012-02-18 14:28:43 +01:00
|
|
|
if (s->pict_type == AV_PICTURE_TYPE_I) {
|
|
|
|
|
put_bits(&s->pb,
|
|
|
|
|
ff_v2_intra_cbpc[cbp&3][1], ff_v2_intra_cbpc[cbp&3][0]);
|
|
|
|
|
} else {
|
2025-03-18 13:21:23 +01:00
|
|
|
if (ms->use_skip_mb_code)
|
2012-02-18 14:28:43 +01:00
|
|
|
put_bits(&s->pb, 1, 0); /* mb coded */
|
|
|
|
|
put_bits(&s->pb,
|
|
|
|
|
ff_v2_mb_type[(cbp&3) + 4][1],
|
|
|
|
|
ff_v2_mb_type[(cbp&3) + 4][0]);
|
|
|
|
|
}
|
|
|
|
|
put_bits(&s->pb, 1, 0); /* no AC prediction yet */
|
|
|
|
|
put_bits(&s->pb,
|
|
|
|
|
ff_h263_cbpy_tab[cbp>>2][1],
|
|
|
|
|
ff_h263_cbpy_tab[cbp>>2][0]);
|
|
|
|
|
}else{
|
|
|
|
|
if (s->pict_type == AV_PICTURE_TYPE_I) {
|
2024-04-20 22:11:55 +02:00
|
|
|
/* compute coded_cbp; the 0x3 corresponds to chroma cbp;
|
|
|
|
|
* luma coded_cbp are set in the loop below */
|
|
|
|
|
coded_cbp = cbp & 0x3;
|
|
|
|
|
for (int i = 0; i < 4; i++) {
|
|
|
|
|
uint8_t *coded_block;
|
|
|
|
|
int pred = ff_msmpeg4_coded_block_pred(s, i, &coded_block);
|
|
|
|
|
int val = (s->block_last_index[i] >= 1);
|
|
|
|
|
*coded_block = val;
|
|
|
|
|
val ^= pred;
|
|
|
|
|
coded_cbp |= val << (5 - i);
|
|
|
|
|
}
|
|
|
|
|
|
2012-02-18 14:28:43 +01:00
|
|
|
put_bits(&s->pb,
|
|
|
|
|
ff_msmp4_mb_i_table[coded_cbp][1], ff_msmp4_mb_i_table[coded_cbp][0]);
|
|
|
|
|
} else {
|
2025-03-18 13:21:23 +01:00
|
|
|
if (ms->use_skip_mb_code)
|
2012-02-18 14:28:43 +01:00
|
|
|
put_bits(&s->pb, 1, 0); /* mb coded */
|
|
|
|
|
put_bits(&s->pb,
|
|
|
|
|
ff_table_mb_non_intra[cbp][1],
|
|
|
|
|
ff_table_mb_non_intra[cbp][0]);
|
|
|
|
|
}
|
|
|
|
|
put_bits(&s->pb, 1, 0); /* no AC prediction yet */
|
|
|
|
|
if(s->inter_intra_pred){
|
|
|
|
|
s->h263_aic_dir=0;
|
|
|
|
|
put_bits(&s->pb, ff_table_inter_intra[s->h263_aic_dir][1], ff_table_inter_intra[s->h263_aic_dir][0]);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
s->misc_bits += get_bits_diff(s);
|
|
|
|
|
|
|
|
|
|
for (i = 0; i < 6; i++) {
|
|
|
|
|
ff_msmpeg4_encode_block(s, block[i], i);
|
|
|
|
|
}
|
|
|
|
|
s->i_tex_bits += get_bits_diff(s);
|
|
|
|
|
s->i_count++;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2025-03-18 13:21:23 +01:00
|
|
|
static void msmpeg4_encode_dc(MSMPEG4EncContext *const ms, int level, int n, int *dir_ptr)
|
2012-02-18 14:28:43 +01:00
|
|
|
{
|
2025-03-18 13:21:23 +01:00
|
|
|
MpegEncContext *const s = &ms->m.s;
|
2012-02-18 14:28:43 +01:00
|
|
|
int sign, code;
|
2021-04-08 14:40:04 +02:00
|
|
|
int pred;
|
2012-02-18 14:28:43 +01:00
|
|
|
|
|
|
|
|
int16_t *dc_val;
|
|
|
|
|
pred = ff_msmpeg4_pred_dc(s, n, &dc_val, dir_ptr);
|
|
|
|
|
|
|
|
|
|
/* update predictor */
|
|
|
|
|
if (n < 4) {
|
|
|
|
|
*dc_val = level * s->y_dc_scale;
|
|
|
|
|
} else {
|
|
|
|
|
*dc_val = level * s->c_dc_scale;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* do the prediction */
|
|
|
|
|
level -= pred;
|
|
|
|
|
|
2024-04-28 23:18:35 +02:00
|
|
|
if (s->msmpeg4_version <= MSMP4_V2) {
|
2012-02-18 14:28:43 +01:00
|
|
|
if (n < 4) {
|
|
|
|
|
put_bits(&s->pb,
|
|
|
|
|
ff_v2_dc_lum_table[level + 256][1],
|
|
|
|
|
ff_v2_dc_lum_table[level + 256][0]);
|
|
|
|
|
}else{
|
|
|
|
|
put_bits(&s->pb,
|
|
|
|
|
ff_v2_dc_chroma_table[level + 256][1],
|
|
|
|
|
ff_v2_dc_chroma_table[level + 256][0]);
|
|
|
|
|
}
|
|
|
|
|
}else{
|
|
|
|
|
sign = 0;
|
|
|
|
|
if (level < 0) {
|
|
|
|
|
level = -level;
|
|
|
|
|
sign = 1;
|
|
|
|
|
}
|
|
|
|
|
code = level;
|
|
|
|
|
if (code > DC_MAX)
|
|
|
|
|
code = DC_MAX;
|
|
|
|
|
|
2025-03-18 13:21:23 +01:00
|
|
|
put_bits(&s->pb, ff_msmp4_dc_tables[ms->dc_table_index][n >= 4][code][1],
|
|
|
|
|
ff_msmp4_dc_tables[ms->dc_table_index][n >= 4][code][0]);
|
2012-02-18 14:28:43 +01:00
|
|
|
|
|
|
|
|
if (code == DC_MAX)
|
2021-04-08 14:40:04 +02:00
|
|
|
put_bits(&s->pb, 8, level);
|
2012-02-18 14:28:43 +01:00
|
|
|
|
|
|
|
|
if (level != 0) {
|
|
|
|
|
put_bits(&s->pb, 1, sign);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2016-04-27 13:45:23 -04:00
|
|
|
/* Encoding of a block; very similar to MPEG-4 except for a different
|
|
|
|
|
* escape coding (same as H.263) and more VLC tables. */
|
2013-01-20 01:02:29 +01:00
|
|
|
void ff_msmpeg4_encode_block(MpegEncContext * s, int16_t * block, int n)
|
2012-02-18 14:28:43 +01:00
|
|
|
{
|
2022-01-28 00:21:32 +01:00
|
|
|
MSMPEG4EncContext *const ms = (MSMPEG4EncContext*)s;
|
2012-02-18 14:28:43 +01:00
|
|
|
int level, run, last, i, j, last_index;
|
|
|
|
|
int last_non_zero, sign, slevel;
|
|
|
|
|
int code, run_diff, dc_pred_dir;
|
|
|
|
|
const RLTable *rl;
|
|
|
|
|
const uint8_t *scantable;
|
|
|
|
|
|
|
|
|
|
if (s->mb_intra) {
|
2025-03-18 13:21:23 +01:00
|
|
|
msmpeg4_encode_dc(ms, block[0], n, &dc_pred_dir);
|
2012-02-18 14:28:43 +01:00
|
|
|
i = 1;
|
|
|
|
|
if (n < 4) {
|
2025-03-18 13:21:23 +01:00
|
|
|
rl = &ff_rl_table[ms->rl_table_index];
|
2012-02-18 14:28:43 +01:00
|
|
|
} else {
|
2025-03-18 13:21:23 +01:00
|
|
|
rl = &ff_rl_table[3 + ms->rl_chroma_table_index];
|
2012-02-18 14:28:43 +01:00
|
|
|
}
|
2024-04-28 23:18:35 +02:00
|
|
|
run_diff = s->msmpeg4_version >= MSMP4_WMV1;
|
2012-02-18 14:28:43 +01:00
|
|
|
scantable= s->intra_scantable.permutated;
|
|
|
|
|
} else {
|
|
|
|
|
i = 0;
|
2025-03-18 13:21:23 +01:00
|
|
|
rl = &ff_rl_table[3 + ms->rl_table_index];
|
2024-04-28 23:18:35 +02:00
|
|
|
run_diff = s->msmpeg4_version > MSMP4_V2;
|
2012-02-18 14:28:43 +01:00
|
|
|
scantable= s->inter_scantable.permutated;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* recalculate block_last_index for M$ wmv1 */
|
2024-04-28 23:18:35 +02:00
|
|
|
if (s->msmpeg4_version >= MSMP4_WMV1 && s->block_last_index[n] > 0) {
|
2012-02-18 14:28:43 +01:00
|
|
|
for(last_index=63; last_index>=0; last_index--){
|
|
|
|
|
if(block[scantable[last_index]]) break;
|
|
|
|
|
}
|
|
|
|
|
s->block_last_index[n]= last_index;
|
|
|
|
|
}else
|
|
|
|
|
last_index = s->block_last_index[n];
|
|
|
|
|
/* AC coefs */
|
|
|
|
|
last_non_zero = i - 1;
|
|
|
|
|
for (; i <= last_index; i++) {
|
|
|
|
|
j = scantable[i];
|
|
|
|
|
level = block[j];
|
|
|
|
|
if (level) {
|
|
|
|
|
run = i - last_non_zero - 1;
|
|
|
|
|
last = (i == last_index);
|
|
|
|
|
sign = 0;
|
|
|
|
|
slevel = level;
|
|
|
|
|
if (level < 0) {
|
|
|
|
|
sign = 1;
|
|
|
|
|
level = -level;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if(level<=MAX_LEVEL && run<=MAX_RUN){
|
2022-01-28 00:21:32 +01:00
|
|
|
ms->ac_stats[s->mb_intra][n>3][level][run][last]++;
|
2012-02-18 14:28:43 +01:00
|
|
|
}
|
|
|
|
|
|
2022-01-28 00:21:32 +01:00
|
|
|
ms->ac_stats[s->mb_intra][n > 3][40][63][0]++; //esc3 like
|
2012-02-18 14:28:43 +01:00
|
|
|
|
|
|
|
|
code = get_rl_index(rl, last, run, level);
|
|
|
|
|
put_bits(&s->pb, rl->table_vlc[code][1], rl->table_vlc[code][0]);
|
|
|
|
|
if (code == rl->n) {
|
|
|
|
|
int level1, run1;
|
|
|
|
|
|
|
|
|
|
level1 = level - rl->max_level[last][run];
|
|
|
|
|
if (level1 < 1)
|
|
|
|
|
goto esc2;
|
|
|
|
|
code = get_rl_index(rl, last, run, level1);
|
|
|
|
|
if (code == rl->n) {
|
|
|
|
|
esc2:
|
|
|
|
|
put_bits(&s->pb, 1, 0);
|
|
|
|
|
if (level > MAX_LEVEL)
|
|
|
|
|
goto esc3;
|
|
|
|
|
run1 = run - rl->max_run[last][level] - run_diff;
|
|
|
|
|
if (run1 < 0)
|
|
|
|
|
goto esc3;
|
|
|
|
|
code = get_rl_index(rl, last, run1+1, level);
|
2024-04-28 23:18:35 +02:00
|
|
|
if (s->msmpeg4_version == MSMP4_WMV1 && code == rl->n)
|
2012-02-18 14:28:43 +01:00
|
|
|
goto esc3;
|
|
|
|
|
code = get_rl_index(rl, last, run1, level);
|
|
|
|
|
if (code == rl->n) {
|
|
|
|
|
esc3:
|
|
|
|
|
/* third escape */
|
|
|
|
|
put_bits(&s->pb, 1, 0);
|
|
|
|
|
put_bits(&s->pb, 1, last);
|
2024-04-28 23:18:35 +02:00
|
|
|
if (s->msmpeg4_version >= MSMP4_WMV1) {
|
2025-03-18 13:21:23 +01:00
|
|
|
if (s->esc3_level_length == 0) {
|
|
|
|
|
s->esc3_level_length = 8;
|
|
|
|
|
ms->esc3_run_length = 6;
|
2012-02-18 14:28:43 +01:00
|
|
|
//ESCLVLSZ + ESCRUNSZ
|
|
|
|
|
if(s->qscale<8)
|
2021-04-08 14:40:04 +02:00
|
|
|
put_bits(&s->pb, 6, 3);
|
2012-02-18 14:28:43 +01:00
|
|
|
else
|
|
|
|
|
put_bits(&s->pb, 8, 3);
|
|
|
|
|
}
|
2025-03-18 13:21:23 +01:00
|
|
|
put_bits(&s->pb, ms->esc3_run_length, run);
|
2012-02-18 14:28:43 +01:00
|
|
|
put_bits(&s->pb, 1, sign);
|
|
|
|
|
put_bits(&s->pb, s->esc3_level_length, level);
|
|
|
|
|
}else{
|
|
|
|
|
put_bits(&s->pb, 6, run);
|
|
|
|
|
put_sbits(&s->pb, 8, slevel);
|
|
|
|
|
}
|
|
|
|
|
} else {
|
|
|
|
|
/* second escape */
|
|
|
|
|
put_bits(&s->pb, 1, 1);
|
|
|
|
|
put_bits(&s->pb, rl->table_vlc[code][1], rl->table_vlc[code][0]);
|
|
|
|
|
put_bits(&s->pb, 1, sign);
|
|
|
|
|
}
|
|
|
|
|
} else {
|
|
|
|
|
/* first escape */
|
|
|
|
|
put_bits(&s->pb, 1, 1);
|
|
|
|
|
put_bits(&s->pb, rl->table_vlc[code][1], rl->table_vlc[code][0]);
|
|
|
|
|
put_bits(&s->pb, 1, sign);
|
|
|
|
|
}
|
|
|
|
|
} else {
|
|
|
|
|
put_bits(&s->pb, 1, sign);
|
|
|
|
|
}
|
|
|
|
|
last_non_zero = i;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
2022-01-25 14:58:22 +01:00
|
|
|
|
2025-03-03 23:35:01 +01:00
|
|
|
av_cold void ff_msmpeg4_encode_init(MPVMainEncContext *const m)
|
|
|
|
|
{
|
|
|
|
|
MpegEncContext *const s = &m->s;
|
|
|
|
|
static AVOnce init_static_once = AV_ONCE_INIT;
|
|
|
|
|
|
|
|
|
|
ff_msmpeg4_common_init(s);
|
|
|
|
|
|
2025-03-04 19:09:24 +01:00
|
|
|
if (s->msmpeg4_version <= MSMP4_WMV1) {
|
2025-03-03 23:35:01 +01:00
|
|
|
m->encode_picture_header = msmpeg4_encode_picture_header;
|
2025-03-04 19:09:24 +01:00
|
|
|
s->encode_mb = msmpeg4_encode_mb;
|
|
|
|
|
}
|
2025-03-03 23:35:01 +01:00
|
|
|
|
|
|
|
|
if (s->msmpeg4_version >= MSMP4_WMV1) {
|
|
|
|
|
s->min_qcoeff = -255;
|
|
|
|
|
s->max_qcoeff = 255;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* init various encoding tables */
|
|
|
|
|
ff_thread_once(&init_static_once, msmpeg4_encode_init_static);
|
|
|
|
|
}
|
|
|
|
|
|
2022-03-16 21:09:54 +01:00
|
|
|
const FFCodec ff_msmpeg4v2_encoder = {
|
|
|
|
|
.p.name = "msmpeg4v2",
|
2022-08-29 13:38:02 +02:00
|
|
|
CODEC_LONG_NAME("MPEG-4 part 2 Microsoft variant version 2"),
|
2022-03-16 21:09:54 +01:00
|
|
|
.p.type = AVMEDIA_TYPE_VIDEO,
|
|
|
|
|
.p.id = AV_CODEC_ID_MSMPEG4V2,
|
2025-03-07 01:19:27 +01:00
|
|
|
CODEC_PIXFMTS(AV_PIX_FMT_YUV420P),
|
avcodec/internal: add FFCodec.color_ranges
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)
2023-10-11 16:09:33 +02:00
|
|
|
.color_ranges = AVCOL_RANGE_MPEG,
|
2022-03-16 21:09:54 +01:00
|
|
|
.p.priv_class = &ff_mpv_enc_class,
|
2024-06-30 17:44:46 +02:00
|
|
|
.p.capabilities = AV_CODEC_CAP_DR1 | AV_CODEC_CAP_ENCODER_REORDERED_OPAQUE,
|
2022-07-10 00:05:45 +02:00
|
|
|
.caps_internal = FF_CODEC_CAP_INIT_CLEANUP,
|
2022-01-28 00:21:32 +01:00
|
|
|
.priv_data_size = sizeof(MSMPEG4EncContext),
|
2022-01-25 14:58:22 +01:00
|
|
|
.init = ff_mpv_encode_init,
|
2022-03-30 23:28:24 +02:00
|
|
|
FF_CODEC_ENCODE_CB(ff_mpv_encode_picture),
|
2022-01-25 14:58:22 +01:00
|
|
|
.close = ff_mpv_encode_end,
|
|
|
|
|
};
|
|
|
|
|
|
2022-03-16 21:09:54 +01:00
|
|
|
const FFCodec ff_msmpeg4v3_encoder = {
|
|
|
|
|
.p.name = "msmpeg4",
|
2022-08-29 13:38:02 +02:00
|
|
|
CODEC_LONG_NAME("MPEG-4 part 2 Microsoft variant version 3"),
|
2022-03-16 21:09:54 +01:00
|
|
|
.p.type = AVMEDIA_TYPE_VIDEO,
|
|
|
|
|
.p.id = AV_CODEC_ID_MSMPEG4V3,
|
2025-03-07 01:19:27 +01:00
|
|
|
CODEC_PIXFMTS(AV_PIX_FMT_YUV420P),
|
avcodec/internal: add FFCodec.color_ranges
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)
2023-10-11 16:09:33 +02:00
|
|
|
.color_ranges = AVCOL_RANGE_MPEG,
|
2022-03-16 21:09:54 +01:00
|
|
|
.p.priv_class = &ff_mpv_enc_class,
|
2024-06-30 17:44:46 +02:00
|
|
|
.p.capabilities = AV_CODEC_CAP_DR1 | AV_CODEC_CAP_ENCODER_REORDERED_OPAQUE,
|
2022-07-10 00:05:45 +02:00
|
|
|
.caps_internal = FF_CODEC_CAP_INIT_CLEANUP,
|
2022-01-28 00:21:32 +01:00
|
|
|
.priv_data_size = sizeof(MSMPEG4EncContext),
|
2022-01-25 14:58:22 +01:00
|
|
|
.init = ff_mpv_encode_init,
|
2022-03-30 23:28:24 +02:00
|
|
|
FF_CODEC_ENCODE_CB(ff_mpv_encode_picture),
|
2022-01-25 14:58:22 +01:00
|
|
|
.close = ff_mpv_encode_end,
|
|
|
|
|
};
|
|
|
|
|
|
2022-03-16 21:09:54 +01:00
|
|
|
const FFCodec ff_wmv1_encoder = {
|
|
|
|
|
.p.name = "wmv1",
|
2022-08-29 13:38:02 +02:00
|
|
|
CODEC_LONG_NAME("Windows Media Video 7"),
|
2022-03-16 21:09:54 +01:00
|
|
|
.p.type = AVMEDIA_TYPE_VIDEO,
|
|
|
|
|
.p.id = AV_CODEC_ID_WMV1,
|
2025-03-07 01:19:27 +01:00
|
|
|
CODEC_PIXFMTS(AV_PIX_FMT_YUV420P),
|
avcodec/internal: add FFCodec.color_ranges
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)
2023-10-11 16:09:33 +02:00
|
|
|
.color_ranges = AVCOL_RANGE_MPEG,
|
2022-03-16 21:09:54 +01:00
|
|
|
.p.priv_class = &ff_mpv_enc_class,
|
2024-06-30 17:44:46 +02:00
|
|
|
.p.capabilities = AV_CODEC_CAP_DR1 | AV_CODEC_CAP_ENCODER_REORDERED_OPAQUE,
|
2022-07-10 00:05:45 +02:00
|
|
|
.caps_internal = FF_CODEC_CAP_INIT_CLEANUP,
|
2022-01-28 00:21:32 +01:00
|
|
|
.priv_data_size = sizeof(MSMPEG4EncContext),
|
2022-01-25 14:58:22 +01:00
|
|
|
.init = ff_mpv_encode_init,
|
2022-03-30 23:28:24 +02:00
|
|
|
FF_CODEC_ENCODE_CB(ff_mpv_encode_picture),
|
2022-01-25 14:58:22 +01:00
|
|
|
.close = ff_mpv_encode_end,
|
|
|
|
|
};
|