ffmpeg学习
来源:互联网 发布:淘宝美女店主 下海 编辑:程序博客网 时间:2024/06/05 17:57
ffmpeg_纯净版 是2.1.1版本
H264_cavlc.c
中ff_h264_decode_mb_cavlc函数
ff_h264_decode_mb_cavlc函数中
1054行
if(!IS_INTRA16x16(mb_type)){
1081行
if(cbp || IS_INTRA16x16(mb_type)){
581行(加入)
printf("123\n");
(加入)
FILE *tp_dct_rem=fopen("dct.txt","a+");
fprintf(tp_dct_rem,"123");
ffmpeg_非纯净版
Ffmpeg.c:static int output_packet(InputStream *ist, const AVPacket *pkt)
Avcodec.h (libavcodec):int avcodec_decode_video2(AVCodecContext *avctx, AVFrame *picture,...)
H264.c (libavcodec):static int decode_frame(AVCodecContext *avctx, void *data,...)
H264.c (libavcodec):static int decode_nal_units(H264Context *h, const uint8_t *buf, int buf_size,int parse_extradata)
H264.c (libavcodec):static int execute_decode_slices(H264Context *h, int context_count) -> return decode_slice(avctx, &h);
H264.c (libavcodec):static int decode_slice(struct AVCodecContext *avctx, void *arg) -> int ret = ff_h264_decode_mb_cavlc(h);
H264.c (libavcodec): int ret = ff_h264_decode_mb_cavlc(h);
H264.c (libavcodec): ret = ff_h264_decode_mb_cavlc(h);
H264_cavlc.c (libavcodec): int ff_h264_decode_mb_cavlc(H264Context *h) ->decode_luma_residual();decode_residual();
decode_luma_residual() ->decode_residual();
H264_cavlc.c (libavcodec): static int decode_residual(H264Context *h, GetBitContext *gb, int16_t *block, int n, const uint8_t *scantable, const uint32_t *qmul, int max_coeff)
参考:
http://www.douban.com/note/228831821/
http://wenku.baidu.com/link?url=YLSrL9aTK5ATaMXe8fRTDahKqvbqC7QwZ6C15vMxGQ7ga2fGAEep3F1DBqD7IftCi-FFcG_fcfGN9MuplEo_mHWiOiu880zeyQQ6zsa-9wq
AVCodecContext:
这是一个描述编解码器上下文的数据结构,包含了众多编解码器需要的参数信息
typedef struct AVStream:
该结构体描述一个媒体流
AVFormatContext
这个结构体描述了一个媒体文件或媒体流的构成和基本信息
这是FFMpeg中最为基本的一个结构,是其他所有结构的根,是一个多媒体文件或流的根本抽象。
AVPacket定义在avcodec.h中
FFMPEG使用AVPacket来暂存解复用之后、解码之前的媒体数据(一个音/视频帧、一个字幕包等)及附加信息(解码时间戳、显示时间戳、时长等)。
AVFrame是定义在avcodec.h中的一个数据结构:
typedef struct AVFrame {
FF_COMMON_FRAME
} AVFrame;
avcodec_decode_video2
int avcodec_decode_video2(AVCodecContext *avctx, AVFrame *picture, int *got_picture_ptr, AVPacket *avpkt);
解码一个视频帧。got_picture_ptr指示是否有解码数据输出。
输入数据在AVPacket结构中,输出数据在AVFrame结构中。
派生关系
AVFormatContext->AVStream->AVCodecContext->AVCodec
AVOutPutFormator,AVInPutFormat
AVFrame->AVPicture->AVPacket
Coded_block_pattern,即CBP,指亮度和色度分量的各小块的残差的编码方案。
所谓的残差方案包括:
(1) 所有残差(包括DC、AC)都编码。
(2) 只对DC系数编码。
(3) 所有残差(包括DC、AC)都不编码。
对于非帧内16*16的宏块类型:
CodedBlockPatternLuma = coded_block_pattern % 16
CodedBlockPatternChroma = coded_block_pattern / 16
对于帧内16*16的宏块类型,CodedBlockPatternLuma和CodedBlockPatternChroma 的值不是由本句法元素给出,而是通过mb_type得到的。
max_coeff:
number of coefficients in the block
param n :
block index
coeff_token:句法元素
total_coeff:非零系数的数目
uint32_t:32位无符号整数
const uint32_t *qmul
const uint8_t *scantable
static VLC chroma_dc_coeff_token_vlc;
typedef struct VLC {
int bits;
VLC_TYPE (*table)[2]; ///< code, bits
int table_size, table_allocated;
} VLC;
#define VLC_TYPE int16_t
#define CHROMA_DC_COEFF_TOKEN_VLC_BITS 8
以下面这个为主:
static av_always_inline int get_vlc2(GetBitContext *s, VLC_TYPE (*table)[2],int bits, int max_depth)
{
int code;
OPEN_READER(re, s);
UPDATE_CACHE(re, s);
GET_VLC(code, re, s, table, bits, max_depth);
CLOSE_READER(re, s);
return code;
}
#define get_vlc2(s, tab, bits, max) get_vlc_trace(s, tab, bits, max, __FILE__, __PRETTY_FUNCTION__, __LINE__)
total_coeff由coeff_token求得:
total_coeff= coeff_token>>2;
trailing_ones由coeff_token求得:
trailing_ones= coeff_token&3;
static inline unsigned int show_bits(GetBitContext *s, int n)
{
register int tmp;
OPEN_READER(re, s);
av_assert2(n>0 && n<=25);
UPDATE_CACHE(re, s);
tmp = SHOW_UBITS(re, s, n);
return tmp;
}
#ifdef BITSTREAM_READER_LE
# define SHOW_UBITS(name, gb, num) zero_extend(name ## _cache, num)
# define SHOW_SBITS(name, gb, num) sign_extend(name ## _cache, num)
#else
# define SHOW_UBITS(name, gb, num) NEG_USR32(name ## _cache, num)
# define SHOW_SBITS(name, gb, num) NEG_SSR32(name ## _cache, num)
#endif
static inline av_const unsigned zero_extend(unsigned val, unsigned bits)
{
return (val << ((8 * sizeof(int)) - bits)) >> ((8 * sizeof(int)) - bits);
}
static inline void skip_bits(GetBitContext *s, int n)
{
OPEN_READER(re, s);
UPDATE_CACHE(re, s);
LAST_SKIP_BITS(re, s, n);
CLOSE_READER(re, s);
}
#define LAST_SKIP_BITS(name, gb, num) SKIP_COUNTER(name, gb, num)
# define SKIP_COUNTER(name, gb, num) name ## _index += (num)
前3个幅值由i给出:
level[0] = 1-((i&4)>>1);
level[1] = 1-((i&2) );
level[2] = 1-((i&1)<<1);
zeros_left由get_vlc2()求出:
zeros_left = get_vlc2();
run_before由get_vlc2()求出:
run_before= get_vlc2();
level[]由level_code求出:
level[trailing_ones]= level_code;
int pixel_shift; ///< 0 for 8-bit H264, 1 for high-bit-depth H264
#define LUMA_DC_BLOCK_INDEX 48
((type*)block)[*scantable] = level[0];
((type*)block)[*scantable]= level[i];
修改((type*)block)[*scantable]值,都是幅值。
*scantable最大多少?
最大为total_coeff
total_coeff由coeff_token求得:
total_coeff= coeff_token>>2;
coeff_token = get_vlc2();
usage: ffmpeg [options] [[infile options] -i infile]... {[outfile options] outfile}...
服务器上ffmpeg/ffmpeg-最终版本 学习:
//初始化变量
FILE *tp_dct_cjx;
int coeff[16];
int column[16]={0,4,8,12,1,5,9,13,2,6,10,14,3,7,11,15};
memset(coeff,0,sizeof(coeff));
if((tp_dct_cjx=fopen("dct.txt","a+"))==NULL)
{
printf("can not open file\n");
}
//反量化之前取level[0]到coeff[]中
else{
//printf("4'5'6'\n");
if ((h->luma_flag==1)&&(!IS_8x8DCT(h->hua_mb_type)))
{
coeff[column[*scantable]]=level[0];
}
((int16_t*)block)[*scantable] = ((int)(level[0] * qmul[*scantable] + 32))>>6;
//反量化之前取level[i]到coeff[]中
if ((h->luma_flag==1)&&(!IS_8x8DCT(h->hua_mb_type)))
{
coeff[column[*scantable]]=level[i];
}
((int16_t*)block)[*scantable]= ((int)(level[i] * qmul[*scantable] + 32))>>6;
//反量化之前取level[i]到coeff[]中
if ((h->luma_flag==1)&&(!IS_8x8DCT(h->hua_mb_type)))
{
coeff[column[*scantable]]=level[i];
}
((int16_t*)block)[*scantable]= ((int)(level[i] * qmul[*scantable] + 32))>>6;
//把coeff[]中值写入文件dct.txt
if ((h->luma_flag)&&(!IS_8x8DCT(h->hua_mb_type)))
{
for(i=0;i<16;i++)
{
if(i%16==0)
{
fprintf(tp_dct_cjx,"\r\n");
}
fprintf(tp_dct_cjx,"%4d",coeff[i]);
}
}
//关闭文件
fclose(tp_dct_cjx);
return 0;
//if条件h->luma_flag 和 !IS_8x8DCT(h->hua_mb_type)
int hua_mb_type;
int luma_flag;
//Search luma_flag
luma_flag Matches (10 in 3 files) ----
H264.h (libavcodec):int luma_flag;
H264_cavlc.c (libavcodec): if ((h->luma_flag==1)&&(!IS_8x8DCT(h->hua_mb_type)))
H264_cavlc.c (libavcodec): if ((h->luma_flag==1)&&(!IS_8x8DCT(h->hua_mb_type)))
H264_cavlc.c (libavcodec): if ((h->luma_flag==1)&&(!IS_8x8DCT(h->hua_mb_type)))
H264_cavlc.c (libavcodec): if ((h->luma_flag)&&(!IS_8x8DCT(h->hua_mb_type)))
H264_cavlc.c (libavcodec):h->luma_flag=1;
H264_cavlc.c (libavcodec):h->luma_flag=0;
H264_cavlc.c (libavcodec):h->luma_flag=0;
H264_cavlc.c (libavcodec):h->luma_flag=0;
Vaapi_vc1.c (libavcodec): pic_param->range_mapping_fields.bits.luma_flag = v->range_mapy_flag;
//2个函数修改了h->luma_flag值
static av_always_inline int decode_luma_residual(H264Context *h, GetBitContext *gb, const uint8_t *scan, const uint8_t *scan8x8, int pixel_shift, int mb_type, int cbp, int p){
int i4x4, i8x8;
int qscale = p == 0 ? h->qscale : h->chroma_qp[p-1];
h->luma_flag=1;
...
h->luma_flag=0;
}
int ff_h264_decode_mb_cavlc(H264Context *h){
if(cbp&0x30){
h->luma_flag=0;
if(cbp&0x20){
h->luma_flag=0;
//Search hua_mb_type
- hua_mb_type Matches (8 in 2 files) ----
H264.h (libavcodec):int hua_mb_type;
H264_cavlc.c (libavcodec): if ((h->luma_flag==1)&&(!IS_8x8DCT(h->hua_mb_type)))
H264_cavlc.c (libavcodec): if ((h->luma_flag==1)&&(!IS_8x8DCT(h->hua_mb_type)))
H264_cavlc.c (libavcodec): if ((h->luma_flag==1)&&(!IS_8x8DCT(h->hua_mb_type)))
H264_cavlc.c (libavcodec): if ((h->luma_flag)&&(!IS_8x8DCT(h->hua_mb_type)))
H264_cavlc.c (libavcodec):h->hua_mb_type=mb_type;
H264_cavlc.c (libavcodec):h->hua_mb_type=mb_type;
H264_cavlc.c (libavcodec):h->hua_mb_type=mb_type;
//1个函数修改了h->luma_flag值
int ff_h264_decode_mb_cavlc(H264Context *h){
if(h->slice_type_nos == AV_PICTURE_TYPE_B){
if(mb_type < 23){
partition_count= b_mb_type_info[mb_type].partition_count;
mb_type= b_mb_type_info[mb_type].type;
h->hua_mb_type=mb_type;
}else{
mb_type -= 23;
goto decode_intra_mb;
}
}else if(h->slice_type_nos == AV_PICTURE_TYPE_P){
if(mb_type < 5){
partition_count= p_mb_type_info[mb_type].partition_count;
mb_type= p_mb_type_info[mb_type].type;
h->hua_mb_type=mb_type;
}else{
mb_type -= 5;
goto decode_intra_mb;
}
}else{
av_assert2(h->slice_type_nos == AV_PICTURE_TYPE_I);
if(h->slice_type == AV_PICTURE_TYPE_SI && mb_type)
mb_type--;
decode_intra_mb:
if(mb_type > 25){
av_log(h->avctx, AV_LOG_ERROR, "mb_type %d in %c slice too large at %d %d\n", mb_type, av_get_picture_type_char(h->slice_type), h->mb_x, h->mb_y);
return -1;
}
partition_count=0;
cbp= i_mb_type_info[mb_type].cbp;
h->intra16x16_pred_mode= i_mb_type_info[mb_type].pred_mode;
mb_type= i_mb_type_info[mb_type].type;
h->hua_mb_type=mb_type;
}
//if条件
if ((h->luma_flag==1)&&(!IS_8x8DCT(h->hua_mb_type))&&(IS_INTRA4x4(h->hua_mb_type))&&(h->slice_type_nos==AV_PICTURE_TYPE_I))
//i_mb_type_info
static const IMbInfo i_mb_type_info[26] = {
{ MB_TYPE_INTRA4x4, -1, -1 },
{ MB_TYPE_INTRA16x16, 2, 0 },
{ MB_TYPE_INTRA16x16, 1, 0 },
{ MB_TYPE_INTRA16x16, 0, 0 },
{ MB_TYPE_INTRA16x16, 3, 0 },
{ MB_TYPE_INTRA16x16, 2, 16 },
{ MB_TYPE_INTRA16x16, 1, 16 },
{ MB_TYPE_INTRA16x16, 0, 16 },
{ MB_TYPE_INTRA16x16, 3, 16 },
{ MB_TYPE_INTRA16x16, 2, 32 },
{ MB_TYPE_INTRA16x16, 1, 32 },
{ MB_TYPE_INTRA16x16, 0, 32 },
{ MB_TYPE_INTRA16x16, 3, 32 },
{ MB_TYPE_INTRA16x16, 2, 15 + 0 },
{ MB_TYPE_INTRA16x16, 1, 15 + 0 },
{ MB_TYPE_INTRA16x16, 0, 15 + 0 },
{ MB_TYPE_INTRA16x16, 3, 15 + 0 },
{ MB_TYPE_INTRA16x16, 2, 15 + 16 },
{ MB_TYPE_INTRA16x16, 1, 15 + 16 },
{ MB_TYPE_INTRA16x16, 0, 15 + 16 },
{ MB_TYPE_INTRA16x16, 3, 15 + 16 },
{ MB_TYPE_INTRA16x16, 2, 15 + 32 },
{ MB_TYPE_INTRA16x16, 1, 15 + 32 },
{ MB_TYPE_INTRA16x16, 0, 15 + 32 },
{ MB_TYPE_INTRA16x16, 3, 15 + 32 },
{ MB_TYPE_INTRA_PCM, -1, -1 },
};
//IMbInfo结构体
typedef struct IMbInfo {
uint16_t type;
uint8_t pred_mode;
uint8_t cbp;
} IMbInfo;
//PMbInfo结构体
typedef struct PMbInfo {
uint16_t type;
uint8_t partition_count;
} PMbInfo;
//p_mb_type_info
static const PMbInfo p_mb_type_info[5] = {
{ MB_TYPE_16x16 | MB_TYPE_P0L0, 1 },
{ MB_TYPE_16x8 | MB_TYPE_P0L0 | MB_TYPE_P1L0, 2 },
{ MB_TYPE_8x16 | MB_TYPE_P0L0 | MB_TYPE_P1L0, 2 },
{ MB_TYPE_8x8 | MB_TYPE_P0L0 | MB_TYPE_P1L0, 4 },
{ MB_TYPE_8x8 | MB_TYPE_P0L0 | MB_TYPE_P1L0 | MB_TYPE_REF0, 4 },
};
//还有static const PMbInfo p_sub_mb_type_info[4]
static const PMbInfo b_mb_type_info[23]
static const PMbInfo b_sub_mb_type_info[13]
//Avcodec.h中
//所有宏块类型:
//The following defines may change, don't expect compatibility if you use them.
#define MB_TYPE_INTRA4x4 0x0001
#define MB_TYPE_INTRA16x16 0x0002 //FIXME H.264-specific
#define MB_TYPE_INTRA_PCM 0x0004 //FIXME H.264-specific
#define MB_TYPE_16x16 0x0008
#define MB_TYPE_16x8 0x0010
#define MB_TYPE_8x16 0x0020
#define MB_TYPE_8x8 0x0040
#define MB_TYPE_INTERLACED 0x0080
#define MB_TYPE_DIRECT2 0x0100 //FIXME
#define MB_TYPE_ACPRED 0x0200
#define MB_TYPE_GMC 0x0400
#define MB_TYPE_SKIP 0x0800
#define MB_TYPE_P0L0 0x1000
#define MB_TYPE_P1L0 0x2000
#define MB_TYPE_P0L1 0x4000
#define MB_TYPE_P1L1 0x8000
#define MB_TYPE_L0 (MB_TYPE_P0L0 | MB_TYPE_P1L0)
#define MB_TYPE_L1 (MB_TYPE_P0L1 | MB_TYPE_P1L1)
#define MB_TYPE_L0L1 (MB_TYPE_L0 | MB_TYPE_L1)
#define MB_TYPE_QUANT 0x00010000
#define MB_TYPE_CBP 0x00020000
//Note bits 24-31 are reserved for codec specific use (h264 ref0, mpeg1 0mv, ...)
//所以Slice类型
enum AVPictureType {
AV_PICTURE_TYPE_NONE = 0, ///< Undefined
AV_PICTURE_TYPE_I, ///< Intra
AV_PICTURE_TYPE_P, ///< Predicted
AV_PICTURE_TYPE_B, ///< Bi-dir predicted
AV_PICTURE_TYPE_S, ///< S(GMC)-VOP MPEG4
AV_PICTURE_TYPE_SI, ///< Switching Intra
AV_PICTURE_TYPE_SP, ///< Switching Predicted
AV_PICTURE_TYPE_BI, ///< BI type
};
//例子h->slice_type_nos != AV_PICTURE_TYPE_I
IS_16X16(mb_type)
IS_16X8(mb_type)
IS_8X16(mb_type)
IS_INTRA16x16(mb_type)
IS_INTRA4x4(mb_type)
//判断宏块类型
#define MB_TYPE_INTRA MB_TYPE_INTRA4x4 //default mb_type if there is just one type
#define IS_INTRA4x4(a) ((a)&MB_TYPE_INTRA4x4)
#define IS_INTRA16x16(a) ((a)&MB_TYPE_INTRA16x16)
#define IS_PCM(a) ((a)&MB_TYPE_INTRA_PCM)
#define IS_INTRA(a) ((a)&7)
#define IS_INTER(a) ((a)&(MB_TYPE_16x16|MB_TYPE_16x8|MB_TYPE_8x16|MB_TYPE_8x8))
#define IS_SKIP(a) ((a)&MB_TYPE_SKIP)
#define IS_INTRA_PCM(a) ((a)&MB_TYPE_INTRA_PCM)
#define IS_INTERLACED(a) ((a)&MB_TYPE_INTERLACED)
#define IS_DIRECT(a) ((a)&MB_TYPE_DIRECT2)
#define IS_GMC(a) ((a)&MB_TYPE_GMC)
#define IS_16X16(a) ((a)&MB_TYPE_16x16)
#define IS_16X8(a) ((a)&MB_TYPE_16x8)
#define IS_8X16(a) ((a)&MB_TYPE_8x16)
#define IS_8X8(a) ((a)&MB_TYPE_8x8)
#define IS_SUB_8X8(a) ((a)&MB_TYPE_16x16) //note reused
#define IS_SUB_8X4(a) ((a)&MB_TYPE_16x8) //note reused
#define IS_SUB_4X8(a) ((a)&MB_TYPE_8x16) //note reused
#define IS_SUB_4X4(a) ((a)&MB_TYPE_8x8) //note reused
#define IS_ACPRED(a) ((a)&MB_TYPE_ACPRED)
#define IS_QUANT(a) ((a)&MB_TYPE_QUANT)
#define IS_DIR(a, part, list) ((a) & (MB_TYPE_P0L0<<((part)+2*(list))))
#define USES_LIST(a, list) ((a) & ((MB_TYPE_P0L0|MB_TYPE_P1L0)<<(2*(list)))) ///< does this mb use listX, note does not work if subMBs
#define HAS_CBP(a) ((a)&MB_TYPE_CBP)
//IS_8x8DCT解释
#define MB_TYPE_REF0 MB_TYPE_ACPRED // dirty but it fits in 16 bit
#define MB_TYPE_8x8DCT 0x01000000
#define IS_REF0(a) ((a) & MB_TYPE_REF0)
#define IS_8x8DCT(a) ((a) & MB_TYPE_8x8DCT)
enum chroma_format_e
{
CHROMA_400 = 0,
CHROMA_420 = 1,
CHROMA_422 = 2,
CHROMA_444 = 3,
};
经验:修改过后的ffmpeg运行x264编码整个视频之后生成的.264不行。
原因:x264编码时加一个条件 --no-8x8dct 就行。因为*scantable越界超过16 。
调试ffmpeg
./configure --extra-cflags=-g --disable-stripping
avcodec_open2在libavcodec/utils.c
H264_cavlc.c
中ff_h264_decode_mb_cavlc函数
ff_h264_decode_mb_cavlc函数中
1054行
if(!IS_INTRA16x16(mb_type)){
1081行
if(cbp || IS_INTRA16x16(mb_type)){
581行(加入)
printf("123\n");
(加入)
FILE *tp_dct_rem=fopen("dct.txt","a+");
fprintf(tp_dct_rem,"123");
ffmpeg_非纯净版
Ffmpeg.c:static int output_packet(InputStream *ist, const AVPacket *pkt)
Avcodec.h (libavcodec):int avcodec_decode_video2(AVCodecContext *avctx, AVFrame *picture,...)
H264.c (libavcodec):static int decode_frame(AVCodecContext *avctx, void *data,...)
H264.c (libavcodec):static int decode_nal_units(H264Context *h, const uint8_t *buf, int buf_size,int parse_extradata)
H264.c (libavcodec):static int execute_decode_slices(H264Context *h, int context_count) -> return decode_slice(avctx, &h);
H264.c (libavcodec):static int decode_slice(struct AVCodecContext *avctx, void *arg) -> int ret = ff_h264_decode_mb_cavlc(h);
H264.c (libavcodec): int ret = ff_h264_decode_mb_cavlc(h);
H264.c (libavcodec): ret = ff_h264_decode_mb_cavlc(h);
H264_cavlc.c (libavcodec): int ff_h264_decode_mb_cavlc(H264Context *h) ->decode_luma_residual();decode_residual();
decode_luma_residual() ->decode_residual();
H264_cavlc.c (libavcodec): static int decode_residual(H264Context *h, GetBitContext *gb, int16_t *block, int n, const uint8_t *scantable, const uint32_t *qmul, int max_coeff)
参考:
http://www.douban.com/note/228831821/
http://wenku.baidu.com/link?url=YLSrL9aTK5ATaMXe8fRTDahKqvbqC7QwZ6C15vMxGQ7ga2fGAEep3F1DBqD7IftCi-FFcG_fcfGN9MuplEo_mHWiOiu880zeyQQ6zsa-9wq
AVCodecContext:
这是一个描述编解码器上下文的数据结构,包含了众多编解码器需要的参数信息
typedef struct AVStream:
该结构体描述一个媒体流
AVFormatContext
这个结构体描述了一个媒体文件或媒体流的构成和基本信息
这是FFMpeg中最为基本的一个结构,是其他所有结构的根,是一个多媒体文件或流的根本抽象。
AVPacket定义在avcodec.h中
FFMPEG使用AVPacket来暂存解复用之后、解码之前的媒体数据(一个音/视频帧、一个字幕包等)及附加信息(解码时间戳、显示时间戳、时长等)。
AVFrame是定义在avcodec.h中的一个数据结构:
typedef struct AVFrame {
FF_COMMON_FRAME
} AVFrame;
avcodec_decode_video2
int avcodec_decode_video2(AVCodecContext *avctx, AVFrame *picture, int *got_picture_ptr, AVPacket *avpkt);
解码一个视频帧。got_picture_ptr指示是否有解码数据输出。
输入数据在AVPacket结构中,输出数据在AVFrame结构中。
派生关系
AVFormatContext->AVStream->AVCodecContext->AVCodec
AVOutPutFormator,AVInPutFormat
AVFrame->AVPicture->AVPacket
Coded_block_pattern,即CBP,指亮度和色度分量的各小块的残差的编码方案。
所谓的残差方案包括:
(1) 所有残差(包括DC、AC)都编码。
(2) 只对DC系数编码。
(3) 所有残差(包括DC、AC)都不编码。
对于非帧内16*16的宏块类型:
CodedBlockPatternLuma = coded_block_pattern % 16
CodedBlockPatternChroma = coded_block_pattern / 16
对于帧内16*16的宏块类型,CodedBlockPatternLuma和CodedBlockPatternChroma 的值不是由本句法元素给出,而是通过mb_type得到的。
max_coeff:
number of coefficients in the block
param n :
block index
coeff_token:句法元素
total_coeff:非零系数的数目
uint32_t:32位无符号整数
const uint32_t *qmul
const uint8_t *scantable
static VLC chroma_dc_coeff_token_vlc;
typedef struct VLC {
int bits;
VLC_TYPE (*table)[2]; ///< code, bits
int table_size, table_allocated;
} VLC;
#define VLC_TYPE int16_t
#define CHROMA_DC_COEFF_TOKEN_VLC_BITS 8
以下面这个为主:
static av_always_inline int get_vlc2(GetBitContext *s, VLC_TYPE (*table)[2],int bits, int max_depth)
{
int code;
OPEN_READER(re, s);
UPDATE_CACHE(re, s);
GET_VLC(code, re, s, table, bits, max_depth);
CLOSE_READER(re, s);
return code;
}
#define get_vlc2(s, tab, bits, max) get_vlc_trace(s, tab, bits, max, __FILE__, __PRETTY_FUNCTION__, __LINE__)
total_coeff由coeff_token求得:
total_coeff= coeff_token>>2;
trailing_ones由coeff_token求得:
trailing_ones= coeff_token&3;
static inline unsigned int show_bits(GetBitContext *s, int n)
{
register int tmp;
OPEN_READER(re, s);
av_assert2(n>0 && n<=25);
UPDATE_CACHE(re, s);
tmp = SHOW_UBITS(re, s, n);
return tmp;
}
#ifdef BITSTREAM_READER_LE
# define SHOW_UBITS(name, gb, num) zero_extend(name ## _cache, num)
# define SHOW_SBITS(name, gb, num) sign_extend(name ## _cache, num)
#else
# define SHOW_UBITS(name, gb, num) NEG_USR32(name ## _cache, num)
# define SHOW_SBITS(name, gb, num) NEG_SSR32(name ## _cache, num)
#endif
static inline av_const unsigned zero_extend(unsigned val, unsigned bits)
{
return (val << ((8 * sizeof(int)) - bits)) >> ((8 * sizeof(int)) - bits);
}
static inline void skip_bits(GetBitContext *s, int n)
{
OPEN_READER(re, s);
UPDATE_CACHE(re, s);
LAST_SKIP_BITS(re, s, n);
CLOSE_READER(re, s);
}
#define LAST_SKIP_BITS(name, gb, num) SKIP_COUNTER(name, gb, num)
# define SKIP_COUNTER(name, gb, num) name ## _index += (num)
前3个幅值由i给出:
level[0] = 1-((i&4)>>1);
level[1] = 1-((i&2) );
level[2] = 1-((i&1)<<1);
zeros_left由get_vlc2()求出:
zeros_left = get_vlc2();
run_before由get_vlc2()求出:
run_before= get_vlc2();
level[]由level_code求出:
level[trailing_ones]= level_code;
int pixel_shift; ///< 0 for 8-bit H264, 1 for high-bit-depth H264
#define LUMA_DC_BLOCK_INDEX 48
((type*)block)[*scantable] = level[0];
((type*)block)[*scantable]= level[i];
修改((type*)block)[*scantable]值,都是幅值。
*scantable最大多少?
最大为total_coeff
total_coeff由coeff_token求得:
total_coeff= coeff_token>>2;
coeff_token = get_vlc2();
usage: ffmpeg [options] [[infile options] -i infile]... {[outfile options] outfile}...
服务器上ffmpeg/ffmpeg-最终版本 学习:
//初始化变量
FILE *tp_dct_cjx;
int coeff[16];
int column[16]={0,4,8,12,1,5,9,13,2,6,10,14,3,7,11,15};
memset(coeff,0,sizeof(coeff));
if((tp_dct_cjx=fopen("dct.txt","a+"))==NULL)
{
printf("can not open file\n");
}
//反量化之前取level[0]到coeff[]中
else{
//printf("4'5'6'\n");
if ((h->luma_flag==1)&&(!IS_8x8DCT(h->hua_mb_type)))
{
coeff[column[*scantable]]=level[0];
}
((int16_t*)block)[*scantable] = ((int)(level[0] * qmul[*scantable] + 32))>>6;
//反量化之前取level[i]到coeff[]中
if ((h->luma_flag==1)&&(!IS_8x8DCT(h->hua_mb_type)))
{
coeff[column[*scantable]]=level[i];
}
((int16_t*)block)[*scantable]= ((int)(level[i] * qmul[*scantable] + 32))>>6;
//反量化之前取level[i]到coeff[]中
if ((h->luma_flag==1)&&(!IS_8x8DCT(h->hua_mb_type)))
{
coeff[column[*scantable]]=level[i];
}
((int16_t*)block)[*scantable]= ((int)(level[i] * qmul[*scantable] + 32))>>6;
//把coeff[]中值写入文件dct.txt
if ((h->luma_flag)&&(!IS_8x8DCT(h->hua_mb_type)))
{
for(i=0;i<16;i++)
{
if(i%16==0)
{
fprintf(tp_dct_cjx,"\r\n");
}
fprintf(tp_dct_cjx,"%4d",coeff[i]);
}
}
//关闭文件
fclose(tp_dct_cjx);
return 0;
//if条件h->luma_flag 和 !IS_8x8DCT(h->hua_mb_type)
int hua_mb_type;
int luma_flag;
//Search luma_flag
luma_flag Matches (10 in 3 files) ----
H264.h (libavcodec):int luma_flag;
H264_cavlc.c (libavcodec): if ((h->luma_flag==1)&&(!IS_8x8DCT(h->hua_mb_type)))
H264_cavlc.c (libavcodec): if ((h->luma_flag==1)&&(!IS_8x8DCT(h->hua_mb_type)))
H264_cavlc.c (libavcodec): if ((h->luma_flag==1)&&(!IS_8x8DCT(h->hua_mb_type)))
H264_cavlc.c (libavcodec): if ((h->luma_flag)&&(!IS_8x8DCT(h->hua_mb_type)))
H264_cavlc.c (libavcodec):h->luma_flag=1;
H264_cavlc.c (libavcodec):h->luma_flag=0;
H264_cavlc.c (libavcodec):h->luma_flag=0;
H264_cavlc.c (libavcodec):h->luma_flag=0;
Vaapi_vc1.c (libavcodec): pic_param->range_mapping_fields.bits.luma_flag = v->range_mapy_flag;
//2个函数修改了h->luma_flag值
static av_always_inline int decode_luma_residual(H264Context *h, GetBitContext *gb, const uint8_t *scan, const uint8_t *scan8x8, int pixel_shift, int mb_type, int cbp, int p){
int i4x4, i8x8;
int qscale = p == 0 ? h->qscale : h->chroma_qp[p-1];
h->luma_flag=1;
...
h->luma_flag=0;
}
int ff_h264_decode_mb_cavlc(H264Context *h){
if(cbp&0x30){
h->luma_flag=0;
if(cbp&0x20){
h->luma_flag=0;
//Search hua_mb_type
- hua_mb_type Matches (8 in 2 files) ----
H264.h (libavcodec):int hua_mb_type;
H264_cavlc.c (libavcodec): if ((h->luma_flag==1)&&(!IS_8x8DCT(h->hua_mb_type)))
H264_cavlc.c (libavcodec): if ((h->luma_flag==1)&&(!IS_8x8DCT(h->hua_mb_type)))
H264_cavlc.c (libavcodec): if ((h->luma_flag==1)&&(!IS_8x8DCT(h->hua_mb_type)))
H264_cavlc.c (libavcodec): if ((h->luma_flag)&&(!IS_8x8DCT(h->hua_mb_type)))
H264_cavlc.c (libavcodec):h->hua_mb_type=mb_type;
H264_cavlc.c (libavcodec):h->hua_mb_type=mb_type;
H264_cavlc.c (libavcodec):h->hua_mb_type=mb_type;
//1个函数修改了h->luma_flag值
int ff_h264_decode_mb_cavlc(H264Context *h){
if(h->slice_type_nos == AV_PICTURE_TYPE_B){
if(mb_type < 23){
partition_count= b_mb_type_info[mb_type].partition_count;
mb_type= b_mb_type_info[mb_type].type;
h->hua_mb_type=mb_type;
}else{
mb_type -= 23;
goto decode_intra_mb;
}
}else if(h->slice_type_nos == AV_PICTURE_TYPE_P){
if(mb_type < 5){
partition_count= p_mb_type_info[mb_type].partition_count;
mb_type= p_mb_type_info[mb_type].type;
h->hua_mb_type=mb_type;
}else{
mb_type -= 5;
goto decode_intra_mb;
}
}else{
av_assert2(h->slice_type_nos == AV_PICTURE_TYPE_I);
if(h->slice_type == AV_PICTURE_TYPE_SI && mb_type)
mb_type--;
decode_intra_mb:
if(mb_type > 25){
av_log(h->avctx, AV_LOG_ERROR, "mb_type %d in %c slice too large at %d %d\n", mb_type, av_get_picture_type_char(h->slice_type), h->mb_x, h->mb_y);
return -1;
}
partition_count=0;
cbp= i_mb_type_info[mb_type].cbp;
h->intra16x16_pred_mode= i_mb_type_info[mb_type].pred_mode;
mb_type= i_mb_type_info[mb_type].type;
h->hua_mb_type=mb_type;
}
//if条件
if ((h->luma_flag==1)&&(!IS_8x8DCT(h->hua_mb_type))&&(IS_INTRA4x4(h->hua_mb_type))&&(h->slice_type_nos==AV_PICTURE_TYPE_I))
//i_mb_type_info
static const IMbInfo i_mb_type_info[26] = {
{ MB_TYPE_INTRA4x4, -1, -1 },
{ MB_TYPE_INTRA16x16, 2, 0 },
{ MB_TYPE_INTRA16x16, 1, 0 },
{ MB_TYPE_INTRA16x16, 0, 0 },
{ MB_TYPE_INTRA16x16, 3, 0 },
{ MB_TYPE_INTRA16x16, 2, 16 },
{ MB_TYPE_INTRA16x16, 1, 16 },
{ MB_TYPE_INTRA16x16, 0, 16 },
{ MB_TYPE_INTRA16x16, 3, 16 },
{ MB_TYPE_INTRA16x16, 2, 32 },
{ MB_TYPE_INTRA16x16, 1, 32 },
{ MB_TYPE_INTRA16x16, 0, 32 },
{ MB_TYPE_INTRA16x16, 3, 32 },
{ MB_TYPE_INTRA16x16, 2, 15 + 0 },
{ MB_TYPE_INTRA16x16, 1, 15 + 0 },
{ MB_TYPE_INTRA16x16, 0, 15 + 0 },
{ MB_TYPE_INTRA16x16, 3, 15 + 0 },
{ MB_TYPE_INTRA16x16, 2, 15 + 16 },
{ MB_TYPE_INTRA16x16, 1, 15 + 16 },
{ MB_TYPE_INTRA16x16, 0, 15 + 16 },
{ MB_TYPE_INTRA16x16, 3, 15 + 16 },
{ MB_TYPE_INTRA16x16, 2, 15 + 32 },
{ MB_TYPE_INTRA16x16, 1, 15 + 32 },
{ MB_TYPE_INTRA16x16, 0, 15 + 32 },
{ MB_TYPE_INTRA16x16, 3, 15 + 32 },
{ MB_TYPE_INTRA_PCM, -1, -1 },
};
//IMbInfo结构体
typedef struct IMbInfo {
uint16_t type;
uint8_t pred_mode;
uint8_t cbp;
} IMbInfo;
//PMbInfo结构体
typedef struct PMbInfo {
uint16_t type;
uint8_t partition_count;
} PMbInfo;
//p_mb_type_info
static const PMbInfo p_mb_type_info[5] = {
{ MB_TYPE_16x16 | MB_TYPE_P0L0, 1 },
{ MB_TYPE_16x8 | MB_TYPE_P0L0 | MB_TYPE_P1L0, 2 },
{ MB_TYPE_8x16 | MB_TYPE_P0L0 | MB_TYPE_P1L0, 2 },
{ MB_TYPE_8x8 | MB_TYPE_P0L0 | MB_TYPE_P1L0, 4 },
{ MB_TYPE_8x8 | MB_TYPE_P0L0 | MB_TYPE_P1L0 | MB_TYPE_REF0, 4 },
};
//还有static const PMbInfo p_sub_mb_type_info[4]
static const PMbInfo b_mb_type_info[23]
static const PMbInfo b_sub_mb_type_info[13]
//Avcodec.h中
//所有宏块类型:
//The following defines may change, don't expect compatibility if you use them.
#define MB_TYPE_INTRA4x4 0x0001
#define MB_TYPE_INTRA16x16 0x0002 //FIXME H.264-specific
#define MB_TYPE_INTRA_PCM 0x0004 //FIXME H.264-specific
#define MB_TYPE_16x16 0x0008
#define MB_TYPE_16x8 0x0010
#define MB_TYPE_8x16 0x0020
#define MB_TYPE_8x8 0x0040
#define MB_TYPE_INTERLACED 0x0080
#define MB_TYPE_DIRECT2 0x0100 //FIXME
#define MB_TYPE_ACPRED 0x0200
#define MB_TYPE_GMC 0x0400
#define MB_TYPE_SKIP 0x0800
#define MB_TYPE_P0L0 0x1000
#define MB_TYPE_P1L0 0x2000
#define MB_TYPE_P0L1 0x4000
#define MB_TYPE_P1L1 0x8000
#define MB_TYPE_L0 (MB_TYPE_P0L0 | MB_TYPE_P1L0)
#define MB_TYPE_L1 (MB_TYPE_P0L1 | MB_TYPE_P1L1)
#define MB_TYPE_L0L1 (MB_TYPE_L0 | MB_TYPE_L1)
#define MB_TYPE_QUANT 0x00010000
#define MB_TYPE_CBP 0x00020000
//Note bits 24-31 are reserved for codec specific use (h264 ref0, mpeg1 0mv, ...)
//所以Slice类型
enum AVPictureType {
AV_PICTURE_TYPE_NONE = 0, ///< Undefined
AV_PICTURE_TYPE_I, ///< Intra
AV_PICTURE_TYPE_P, ///< Predicted
AV_PICTURE_TYPE_B, ///< Bi-dir predicted
AV_PICTURE_TYPE_S, ///< S(GMC)-VOP MPEG4
AV_PICTURE_TYPE_SI, ///< Switching Intra
AV_PICTURE_TYPE_SP, ///< Switching Predicted
AV_PICTURE_TYPE_BI, ///< BI type
};
//例子h->slice_type_nos != AV_PICTURE_TYPE_I
IS_16X16(mb_type)
IS_16X8(mb_type)
IS_8X16(mb_type)
IS_INTRA16x16(mb_type)
IS_INTRA4x4(mb_type)
//判断宏块类型
#define MB_TYPE_INTRA MB_TYPE_INTRA4x4 //default mb_type if there is just one type
#define IS_INTRA4x4(a) ((a)&MB_TYPE_INTRA4x4)
#define IS_INTRA16x16(a) ((a)&MB_TYPE_INTRA16x16)
#define IS_PCM(a) ((a)&MB_TYPE_INTRA_PCM)
#define IS_INTRA(a) ((a)&7)
#define IS_INTER(a) ((a)&(MB_TYPE_16x16|MB_TYPE_16x8|MB_TYPE_8x16|MB_TYPE_8x8))
#define IS_SKIP(a) ((a)&MB_TYPE_SKIP)
#define IS_INTRA_PCM(a) ((a)&MB_TYPE_INTRA_PCM)
#define IS_INTERLACED(a) ((a)&MB_TYPE_INTERLACED)
#define IS_DIRECT(a) ((a)&MB_TYPE_DIRECT2)
#define IS_GMC(a) ((a)&MB_TYPE_GMC)
#define IS_16X16(a) ((a)&MB_TYPE_16x16)
#define IS_16X8(a) ((a)&MB_TYPE_16x8)
#define IS_8X16(a) ((a)&MB_TYPE_8x16)
#define IS_8X8(a) ((a)&MB_TYPE_8x8)
#define IS_SUB_8X8(a) ((a)&MB_TYPE_16x16) //note reused
#define IS_SUB_8X4(a) ((a)&MB_TYPE_16x8) //note reused
#define IS_SUB_4X8(a) ((a)&MB_TYPE_8x16) //note reused
#define IS_SUB_4X4(a) ((a)&MB_TYPE_8x8) //note reused
#define IS_ACPRED(a) ((a)&MB_TYPE_ACPRED)
#define IS_QUANT(a) ((a)&MB_TYPE_QUANT)
#define IS_DIR(a, part, list) ((a) & (MB_TYPE_P0L0<<((part)+2*(list))))
#define USES_LIST(a, list) ((a) & ((MB_TYPE_P0L0|MB_TYPE_P1L0)<<(2*(list)))) ///< does this mb use listX, note does not work if subMBs
#define HAS_CBP(a) ((a)&MB_TYPE_CBP)
//IS_8x8DCT解释
#define MB_TYPE_REF0 MB_TYPE_ACPRED // dirty but it fits in 16 bit
#define MB_TYPE_8x8DCT 0x01000000
#define IS_REF0(a) ((a) & MB_TYPE_REF0)
#define IS_8x8DCT(a) ((a) & MB_TYPE_8x8DCT)
enum chroma_format_e
{
CHROMA_400 = 0,
CHROMA_420 = 1,
CHROMA_422 = 2,
CHROMA_444 = 3,
};
经验:修改过后的ffmpeg运行x264编码整个视频之后生成的.264不行。
原因:x264编码时加一个条件 --no-8x8dct 就行。因为*scantable越界超过16 。
调试ffmpeg
./configure --extra-cflags=-g --disable-stripping
avcodec_open2在libavcodec/utils.c
0 0
- FFMPEG学习【ffmpeg工具】
- ffmpeg学习
- 学习ffmpeg
- FFMPEG学习
- FFMPEG学习
- ffmpeg学习
- ffmpeg 学习
- FFMPEG学习
- ffmpeg学习
- ffmpeg学习
- ffmpeg学习
- 开始学习ffmpeg
- FFMPEG 学习笔记
- 学习ffmpeg tutoial
- FFmpeg 学习笔记(一)
- FFmpeg 学习笔记(二)
- ffmpeg Tutorial学习
- 学习FFmpeg API
- setXfermode属性
- sprintf的怪异行为
- JAVA多线程实现和应用总结
- mysql 触发器 自动补全字段
- CC2530低功耗笔记-备忘
- ffmpeg学习
- 2004 TCO QR3 div1 1000(简单条件概率)
- select
- MySQL在大型网站的应用架构演变
- [原创] 微软、Google、腾讯、摩根士丹利IT 实习面试经历
- Android Studio 命令行Gradle编译
- ffmpeg使用方法
- 把QQ聊天记录插入数据库中
- Android ListView 按钮点击分页显示