探測資料結構: /** This structure contains the data a format has to probe a file. */ typedef struct AVProbeData { const char *filename; unsigned char *buf; /**< Buffer must have AVPROBE_PADDING_SIZE of extra allocated bytes filled with zero. */ int buf_size; /**< Size of buf except extra allocated bytes */ } AVProbeData;
|
h264的探測函式:
static int h264_probe(AVProbeData *p) { uint32_t code= -1; int sps=0, pps=0, idr=0, res=0, sli=0; int i;
for(i=0; i<p->buf_size; i++){ code = (code<<8) + p->buf[i]; if ((code & 0xffffff00) == 0x100) { int ref_idc= (code>>5)&3; int type = code & 0x1F; static const int8_t ref_zero[32]={ 2, 0, 0, 0, 0,-1, 1,-1, -1, 1, 1, 1, 1,-1, 2, 2, 2, 2, 2, 0, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2 };
if(code & 0x80) //forbidden bit return 0;
if(ref_zero[type] == 1 && ref_idc) return 0; if(ref_zero[type] ==-1 && !ref_idc) return 0; if(ref_zero[type] == 2) res++;
switch(type){ case 1: sli++; break; case 5: idr++; break; case 7: if(p->buf[i+2]&0x0F) return 0; sps++; break; case 8: pps++; break; } } } if(sps && pps && (idr||sli>3) && res<(sps+pps+idr)) return AVPROBE_SCORE_MAX/2+1; // +1 for .mpg return 0; }
|
影片讀首部函式:
static int video_read_header(AVFormatContext *s, AVFormatParameters *ap) { AVStream *st;
st = av_new_stream(s, 0); if (!st) return AVERROR(ENOMEM);
st->codec->codec_type = AVMEDIA_TYPE_VIDEO; st->codec->codec_id = s->iformat->value; st->need_parsing = AVSTREAM_PARSE_FULL;
/* for MJPEG, specify frame rate */ /* for MPEG-4 specify it, too (most MPEG-4 streams do not have the fixed_vop_rate set ...)*/ if (ap->time_base.num) { st->codec->time_base= ap->time_base; } else if ( st->codec->codec_id == CODEC_ID_MJPEG || st->codec->codec_id == CODEC_ID_MPEG4 || st->codec->codec_id == CODEC_ID_DIRAC || st->codec->codec_id == CODEC_ID_DNXHD || st->codec->codec_id == CODEC_ID_H264) { st->codec->time_base= (AVRational){1,25}; } av_set_pts_info(st, 64, 1, 1200000);
return 0; }
|
原始地讀實際的包函式:
int ff_raw_read_partial_packet(AVFormatContext *s, AVPacket *pkt) { int ret, size;
size = RAW_PACKET_SIZE;
if (av_new_packet(pkt, size) < 0) return AVERROR(ENOMEM);
pkt->pos= url_ftell(s->pb); pkt->stream_index = 0; ret = get_partial_buffer(s->pb, pkt->data, size); if (ret < 0) { av_free_packet(pkt); return ret; } pkt->size = ret; return ret; }
|
原始地寫包函式: static int raw_write_packet(struct AVFormatContext *s, AVPacket *pkt) { put_buffer(s->pb, pkt->data, pkt->size); put_flush_packet(s->pb); return 0; }
|
h264混合器:
AVOutputFormat h264_muxer = { "h264", NULL_IF_CONFIG_SMALL("raw H.264 video format"), NULL, "h264", 0, CODEC_ID_NONE, CODEC_ID_H264, NULL, raw_write_packet, .flags= AVFMT_NOTIMESTAMPS, };
|
h264分離器:
AVInputFormat h264_demuxer = { "h264", NULL_IF_CONFIG_SMALL("raw H.264 video format"), 0, h264_probe, video_read_header, ff_raw_read_partial_packet, .flags= AVFMT_GENERIC_INDEX, .extensions = "h26l,h264,264", //FIXME remove after writing mpeg4_probe .value = CODEC_ID_H264, }
|
libavformat/allformats.c檔案的av_register_all函式註冊了h264分離器和混合器:
#define REGISTER_MUXER(X,x) { extern AVOutputFormat x##_muxer; if(CONFIG_##X##_MUXER) av_register_output_format(&x##_muxer); }
#define REGISTER_DEMUXER(X,x) { extern AVInputFormat x##_demuxer; if(CONFIG_##X##_DEMUXER) av_register_input_format(&x##_demuxer); }
#define REGISTER_MUXDEMUX(X,x) REGISTER_MUXER(X,x); REGISTER_DEMUXER(X,x)
|
void av_register_all(void) { /* 省略部分程式碼 */ /* protocols */ REGISTER_MUXDEMUX (H264, h264); /* 省略部分程式碼 */ }
|
把註冊格式函式也貼出來吧: /** head of registered input format linked list */ AVInputFormat *first_iformat = NULL; /** head of registered output format linked list */ AVOutputFormat *first_oformat = NULL;
void av_register_input_format(AVInputFormat *format) { AVInputFormat **p; p = &first_iformat; while (*p != NULL) p = &(*p)->next; *p = format; format->next = NULL; }
void av_register_output_format(AVOutputFormat *format) { AVOutputFormat **p; p = &first_oformat; while (*p != NULL) p = &(*p)->next; *p = format; format->next = NULL; }
|
|
|