📄 mpeg12.c
字号:
/*
* MPEG1 codec / MPEG2 decoder
* 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 mpeg12.c
* MPEG1/2 codec
*/
//#define DEBUG
#include "avcodec.h"
#include "dsputil.h"
#include "mpegvideo.h"
#include "mpeg12data.h"
//#undef NDEBUG
//#include <assert.h>
#define DC_VLC_BITS 9
#define MV_VLC_BITS 9
#define MBINCR_VLC_BITS 9
#define MB_PAT_VLC_BITS 9
#define MB_PTYPE_VLC_BITS 6
#define MB_BTYPE_VLC_BITS 6
#define TEX_VLC_BITS 9
#ifdef CONFIG_ENCODERS
static void mpeg1_encode_block(MpegEncContext *s,
DCTELEM *block,
int component);
static void mpeg1_encode_motion(MpegEncContext *s, int val, int f_or_b_code); // RAL: f_code parameter added
#endif //CONFIG_ENCODERS
static inline int mpeg1_decode_block_inter(MpegEncContext *s,
DCTELEM *block,
int n);
static inline int mpeg1_decode_block_intra(MpegEncContext *s,
DCTELEM *block,
int n);
static inline int mpeg1_fast_decode_block_inter(MpegEncContext *s, DCTELEM *block, int n);
static inline int mpeg2_decode_block_non_intra(MpegEncContext *s,
DCTELEM *block,
int n);
static inline int mpeg2_decode_block_intra(MpegEncContext *s,
DCTELEM *block,
int n);
static inline int mpeg2_fast_decode_block_non_intra(MpegEncContext *s, DCTELEM *block, int n);
static inline int mpeg2_fast_decode_block_intra(MpegEncContext *s, DCTELEM *block, int n);
static int mpeg_decode_motion(MpegEncContext *s, int fcode, int pred);
static void exchange_uv(MpegEncContext *s);
#ifdef HAVE_XVMC
extern int XVMC_field_start(MpegEncContext *s, AVCodecContext *avctx);
extern int XVMC_field_end(MpegEncContext *s);
extern void XVMC_pack_pblocks(MpegEncContext *s,int cbp);
extern void XVMC_init_block(MpegEncContext *s);//set s->block
#endif
static const enum PixelFormat pixfmt_yuv_420[]= {PIX_FMT_YUV420P,-1};
static const enum PixelFormat pixfmt_yuv_422[]= {PIX_FMT_YUV422P,-1};
static const enum PixelFormat pixfmt_yuv_444[]= {PIX_FMT_YUV444P,-1};
static const enum PixelFormat pixfmt_xvmc_mpg2_420[] = {
PIX_FMT_XVMC_MPEG2_IDCT,
PIX_FMT_XVMC_MPEG2_MC,
-1};
#ifdef CONFIG_ENCODERS
static uint8_t mv_penalty[MAX_FCODE+1][MAX_MV*2+1];
static uint8_t fcode_tab[MAX_MV*2+1];
static uint8_t uni_mpeg1_ac_vlc_len [64*64*2];
static uint8_t uni_mpeg2_ac_vlc_len [64*64*2];
/* simple include everything table for dc, first byte is bits number next 3 are code*/
static uint32_t mpeg1_lum_dc_uni[512];
static uint32_t mpeg1_chr_dc_uni[512];
static uint8_t mpeg1_index_run[2][64];
static int8_t mpeg1_max_level[2][64];
#endif //CONFIG_ENCODERS
static uint8_t static_rl_table_store[2][2][2*MAX_RUN + MAX_LEVEL + 3];
static void init_2d_vlc_rl(RLTable *rl, int use_static)
{
int i;
init_vlc(&rl->vlc, TEX_VLC_BITS, rl->n + 2,
&rl->table_vlc[0][1], 4, 2,
&rl->table_vlc[0][0], 4, 2, use_static);
if(use_static)
rl->rl_vlc[0]= av_mallocz_static(rl->vlc.table_size*sizeof(RL_VLC_ELEM));
else
rl->rl_vlc[0]= av_malloc(rl->vlc.table_size*sizeof(RL_VLC_ELEM));
for(i=0; i<rl->vlc.table_size; i++){
int code= rl->vlc.table[i][0];
int len = rl->vlc.table[i][1];
int level, run;
if(len==0){ // illegal code
run= 65;
level= MAX_LEVEL;
}else if(len<0){ //more bits needed
run= 0;
level= code;
}else{
if(code==rl->n){ //esc
run= 65;
level= 0;
}else if(code==rl->n+1){ //eob
run= 0;
level= 127;
}else{
run= rl->table_run [code] + 1;
level= rl->table_level[code];
}
}
rl->rl_vlc[0][i].len= len;
rl->rl_vlc[0][i].level= level;
rl->rl_vlc[0][i].run= run;
}
}
#ifdef CONFIG_ENCODERS
static void init_uni_ac_vlc(RLTable *rl, uint8_t *uni_ac_vlc_len){
int i;
for(i=0; i<128; i++){
int level= i-64;
int run;
for(run=0; run<64; run++){
int len, bits, code;
int alevel= FFABS(level);
int sign= (level>>31)&1;
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 */) {
/* store the vlc & sign at once */
len= rl->table_vlc[code][1]+1;
bits= (rl->table_vlc[code][0]<<1) + sign;
} else {
len= rl->table_vlc[111/*rl->n*/][1]+6;
bits= rl->table_vlc[111/*rl->n*/][0]<<6;
bits|= run;
if (alevel < 128) {
bits<<=8; len+=8;
bits|= level & 0xff;
} else {
bits<<=16; len+=16;
bits|= level & 0xff;
if (level < 0) {
bits|= 0x8001 + level + 255;
} else {
bits|= level & 0xffff;
}
}
}
uni_ac_vlc_len [UNI_AC_ENC_INDEX(run, i)]= len;
}
}
}
static int find_frame_rate_index(MpegEncContext *s){
int i;
int64_t dmin= INT64_MAX;
int64_t d;
for(i=1;i<14;i++) {
int64_t n0= 1001LL/ff_frame_rate_tab[i].den*ff_frame_rate_tab[i].num*s->avctx->time_base.num;
int64_t n1= 1001LL*s->avctx->time_base.den;
if(s->avctx->strict_std_compliance > FF_COMPLIANCE_INOFFICIAL && i>=9) break;
d = FFABS(n0 - n1);
if(d < dmin){
dmin=d;
s->frame_rate_index= i;
}
}
if(dmin)
return -1;
else
return 0;
}
static int encode_init(AVCodecContext *avctx)
{
MpegEncContext *s = avctx->priv_data;
if(MPV_encode_init(avctx) < 0)
return -1;
if(find_frame_rate_index(s) < 0){
if(s->strict_std_compliance > FF_COMPLIANCE_EXPERIMENTAL){
av_log(avctx, AV_LOG_ERROR, "MPEG1/2 does not support %d/%d fps\n", avctx->time_base.den, avctx->time_base.num);
return -1;
}else{
av_log(avctx, AV_LOG_INFO, "MPEG1/2 does not support %d/%d fps, there may be AV sync issues\n", avctx->time_base.den, avctx->time_base.num);
}
}
if(avctx->profile == FF_PROFILE_UNKNOWN){
if(avctx->level != FF_LEVEL_UNKNOWN){
av_log(avctx, AV_LOG_ERROR, "Set profile and level\n");
return -1;
}
avctx->profile = s->chroma_format == CHROMA_420 ? 4 : 0; /* Main or 4:2:2 */
}
if(avctx->level == FF_LEVEL_UNKNOWN){
if(avctx->profile == 0){ /* 4:2:2 */
if(avctx->width <= 720 && avctx->height <= 608) avctx->level = 5; /* Main */
else avctx->level = 2; /* High */
}else{
if(avctx->profile != 1 && s->chroma_format != CHROMA_420){
av_log(avctx, AV_LOG_ERROR, "Only High(1) and 4:2:2(0) profiles support 4:2:2 color sampling\n");
return -1;
}
if(avctx->width <= 720 && avctx->height <= 576) avctx->level = 8; /* Main */
else if(avctx->width <= 1440) avctx->level = 6; /* High 1440 */
else avctx->level = 4; /* High */
}
}
if((avctx->flags2 & CODEC_FLAG2_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 -1;
}
return 0;
}
static void put_header(MpegEncContext *s, int header)
{
align_put_bits(&s->pb);
put_bits(&s->pb, 16, header>>16);
put_bits(&s->pb, 16, header&0xFFFF);
}
/* put sequence header if needed */
static void mpeg1_encode_sequence_header(MpegEncContext *s)
{
unsigned int vbv_buffer_size;
unsigned int fps, v;
int i;
uint64_t time_code;
float best_aspect_error= 1E10;
float aspect_ratio= av_q2d(s->avctx->sample_aspect_ratio);
int constraint_parameter_flag;
if(aspect_ratio==0.0) aspect_ratio= 1.0; //pixel aspect 1:1 (VGA)
if (s->current_picture.key_frame) {
AVRational framerate= ff_frame_rate_tab[s->frame_rate_index];
/* mpeg1 header repeated every gop */
put_header(s, SEQ_START_CODE);
put_bits(&s->pb, 12, s->width);
put_bits(&s->pb, 12, s->height);
for(i=1; i<15; i++){
float error= aspect_ratio;
if(s->codec_id == CODEC_ID_MPEG1VIDEO || i <=1)
error-= 1.0/mpeg1_aspect[i];
else
error-= av_q2d(mpeg2_aspect[i])*s->height/s->width;
error= FFABS(error);
if(error < 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 == 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_bits(&s->pb, 18, v & 0x3FFFF);
put_bits(&s->pb, 1, 1); /* marker */
put_bits(&s->pb, 10, vbv_buffer_size & 0x3FF);
constraint_parameter_flag=
s->width <= 768 && s->height <= 576 &&
s->mb_width * s->mb_height <= 396 &&
s->mb_width * s->mb_height * framerate.num <= framerate.den*396*25 &&
framerate.num <= framerate.den*30 &&
s->avctx->me_range && s->avctx->me_range < 128 &&
vbv_buffer_size <= 20 &&
v <= 1856000/400 &&
s->codec_id == 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 == CODEC_ID_MPEG2VIDEO){
put_header(s, EXT_START_CODE);
put_bits(&s->pb, 4, 1); //seq ext
put_bits(&s->pb, 1, s->avctx->profile == 0); //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
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -