ffprobe.c 基本就是open file 然後 show stream , format, packet.
所以所有 stream type identify 的動作都是在 ffprobe.c 中的 open_input_file( ) 完成的。
static int open_input_file(AVFormatContext **fmt_ctx_ptr, const char *filename)
{
int err, i;
AVFormatContext *fmt_ctx;
fmt_ctx = avformat_alloc_context();
if ((err = av_open_input_file(&fmt_ctx, filename, iformat, 0, NULL)) < 0) {
print_error(filename, err);
return err;
}
/* fill the streams in the format context */
if ((err = av_find_stream_info(fmt_ctx)) < 0) {
print_error(filename, err);
return err;
}
dump_format(fmt_ctx, 0, filename, 0);
/* bind a decoder to each input stream */
for (i = 0; i < fmt_ctx->nb_streams; i++) {
AVStream *stream = fmt_ctx->streams[i];
AVCodec *codec;
if (!(codec = avcodec_find_decoder(stream->codec->codec_id))) {
fprintf(stderr, "Unsupported codec (id=%d) for input stream %d\n",
stream->codec->codec_id, stream->index);
} else if (avcodec_open(stream->codec, codec) < 0) {
fprintf(stderr, "Error while opening codec for input stream %d\n",
stream->index);
}
}
*fmt_ctx_ptr = fmt_ctx;
return 0;
}
mpeg transport stream 的 probe 方式是: mpegts.c (analyze())
static int analyze(const uint8_t *buf, int size, int packet_size, int *index){
int stat[TS_MAX_PACKET_SIZE];
int i;
int x=0;
int best_score=0;
memset(stat, 0, packet_size*sizeof(int));
for(x=i=0; i<size-3; i++){
if(buf[i] == 0x47 && !(buf[i+1] & 0x80) && (buf[i+3] & 0x30)){
stat[x]++;
if(stat[x] > best_score){
best_score= stat[x];
if(index) *index= x;
}
}
x++;
if(x == packet_size) x= 0;
}
return best_score;
}
逐一檢查 :- byte0 == 0x47
- byte1 & 0x80 == 0x00
- byte3 & 0x30 != 0x00
傳入 10 個 packet_size 來檢查。
這樣,如果傳入的 stream data 剛好是對齊 byte0 的話。最後 state[0]=10.
如果是對齊 byte[1]。state[1]=9
mpegts.c 在 mpegts_probe( ) 里分別 probe 三種type 的 stream:
score = analyze(p->buf, TS_PACKET_SIZE *check_count, TS_PACKET_SIZE , NULL)*CHECK_COUNT/check_count;
dvhs_score= analyze(p->buf, TS_DVHS_PACKET_SIZE*check_count, TS_DVHS_PACKET_SIZE, NULL)*CHECK_COUNT/check_count;
fec_score = analyze(p->buf, TS_FEC_PACKET_SIZE *check_count, TS_FEC_PACKET_SIZE , NULL)*CHECK_COUNT/check_count;
因為是 sample stream file 是 mpeg2 transport stream,而且第一個 byte 就對齊了 sync byte 0x47,所以第一個 analyz( ) 會 return 10.而mpegts_probe( ) 最後 return:
AVPROBE_SCORE_MAX + score - CHECK_COUNT
其中 CHECK_COUNT 就是送進去sample 的 packet number (10)。所以計算結果是 AVPROBE_SCORE_MAX。
probe 的結果是得到 fmt -- AVInputFormat 的 fmt
這個 probe 到的 format 再被用來 open stream:
err = av_open_input_stream(ic_ptr, pb, filename, fmt, ap);
av_open_input_stream 實際上是依據 pb, filename create 一個 AVFormatContext 的 structure。把 fmt 填進 structure 中,並且由 fmt 的
read_header( ) 從 stream 中 parsing header information,填入 ap --- AVFormatParameters
沒有留言:
張貼留言