ubuntu 在 R40e 上 還有 Debian 在 Sempron 2600 上

2010年9月28日 星期二

ffmpeg -ffprobe

要看ffmpeg 怎麼找到transport stream 中的 stream 和 format,看 ffprobe 就可以。
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
以 state[] 作為一個 packet size(188) 的檢測結果。
傳入 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

沒有留言:

標籤

網誌存檔