ffmpeg + sdl -02 利用ffmpeg来分析文件信息

本文介绍了如何利用ffmpeg库分析wma文件信息,包括通过ffprobe编写测试代码、使用gdb进行调试,以及分析ffmpeg的调用流程。通过avformat_open_input、av_probe_input_buffer等函数,展示了对ASF文件格式的读取和解析过程。
摘要由CSDN通过智能技术生成
利用ffmpeg来分析wma文件信息


STEP1: 参考ffprobe编写如下测试代码。
fileParse.c


#include <libavformat/avformat.h>
#include <libavcodec/avcodec.h>
#include <libavutil/avstring.h>
#include <libavutil/opt.h>
#include <libavutil/pixdesc.h>
#include <libavutil/dict.h>


#define print_error(a, b) printf(" Open %s with error (%d) \n", a, b)


int dec_init()
{
    av_register_all();
    avformat_network_init();
}


int dec_exit()
{
avformat_network_deinit();
}


int dec_parse(const char *filename)
{
    int err, i;
    AVFormatContext *fmt_ctx = NULL;
    AVDictionaryEntry *t;
    AVInputFormat *iformat = NULL;
    AVDictionary *format_opts = NULL;


    if ((err = avformat_open_input(&fmt_ctx, filename, iformat, &format_opts)) < 0) {
        print_error(filename, err);
        return err;
    }
    if ((t = av_dict_get(format_opts, "", NULL, AV_DICT_IGNORE_SUFFIX))) {
        av_log(NULL, AV_LOG_ERROR, "Option %s not found.\n", t->key);
        return AVERROR_OPTION_NOT_FOUND;
    }




    /* fill the streams in the format context */
    if ((err = avformat_find_stream_info(fmt_ctx, NULL)) < 0) {
        print_error(filename, err);
        return err;
    }


    av_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 with id %d for input stream %d\n",
                    stream->codec->codec_id, stream->index);
        } else if (avcodec_open2(stream->codec, codec, NULL) < 0) {
            fprintf(stderr, "Error while opening codec for input stream %d\n",
                    stream->index);
        }
    }
    
    avformat_close_input(&fmt_ctx);
    return 0;
}


int main(int argc, char **argv)
{
dec_init();

dec_parse(argv[1]);
dec_exit();
}


Makefile文件
.PHONY: fileParse
INCLUDE= -I../ffmpeg-0.9.2/libavcodec -I../ffmpeg-0.9.2/libavformat -I../ffmpeg-0.9.2/libavfilter -I../ffmpeg-0.9.2/libavformat -I../ffmpeg-0.9.2/libswscale


fileParse:
-rm fileParse
gcc -g ${INCLUDE} -o fileParse fileParse.c -lavformat -lavcodec -lavutil -lswscale -lbz2 -lz -lm `sdl-config  --cflags  --libs`
chmod +x fileParse


STEP2: 使用gdb来Debug FFMPEG
1〉修改ffmpeg配置。
make clean
./configure --enable-debug --disable-optimizations --disable-yasm --disable-asm
make
make install


2> 使用gdb 来调试fileParse
为了了解ffmpeg流程,用wma来测试。
注意到wma采用asf封装,猜测格式检测函数是asf_probe
文件:libavformat/Asfdec.c    
.read_probe     = asf_probe  


gdb
file fileParse
b asf_probe
r /projects/media/wma/123.wma  (测试文件路径)
bt


#0  asf_probe (pd=0xbffff12c) at libavformat/asfdec.c:139
#1  0x0812a2a3 in av_probe_input_format3 (pd=0xbffff1c0, is_opened=1, 
    score_ret=0xbffff178) at libavformat/utils.c:351
#2  0x0812a384 in av_probe_input_format2 (pd=0xbffff1c0, is_opened=1, 
    score_max=0xbffff1bc) at libavformat/utils.c:373
#3  0x0812aae5 in av_probe_input_buffer (pb=0x8c375d0, fmt=0x8c2f024, 
    filename=0xbffff548 "/projects/media/wma/123.wma", logctx=0x8c2f020, 
    offset=0, max_probe_size=1048576) at libavformat/utils.c:586
#4  0x0812add6 in init_input (s=0x8c2f020, 
    filename=0xbffff548 "/projects/media/wma/123.wma", options=0xbffff24c)
    at libavformat/utils.c:653
#5  0x0812ae90 in avformat_open_input (ps=0xbffff2a4, 
    filename=0xbffff548 "/projects/media/wma/123.wma", fmt=0x0, 
    options=0xbffff2a0) at libavformat/utils.c:674
#6  0x0804a48f in dec_parse (filename=0xbffff548 "/projects/media/wma/123.wma")
    at fileParse.c:29
#7  0x0804a66d in main (argc=2, argv=0xbffff394) at fileParse.c:69


可见ffmpeg的调用关系如下:
avformat_open_input
   ↓
init_input
  ↓
av_probe_input_buffer
  ↓
av_probe_input_format2
  ↓
av_probe_input_format3
  ↓


while ((fmt1 = av_iformat_next(fmt1))) {
        if (!is_opened == !(fmt1->flags & AVFMT_NOFILE))
            continue;
        score = 0;
        if (fmt1->read_probe) {
            score = fmt1->read_probe(&lpd);
            if(fmt1->extensions && av_match_ext(lpd.filename, fmt1->extensions))
                score = FFMAX(score, nodat ? AVPROBE_SCORE_MAX/4-1 : 1);
        } else if (fmt1->extensions) {
            if (av_match_ext(lpd.filename, fmt1->extensions)) {
                score = 50;
            }
        }
        if (score > score_max) {
            score_max = score;
            fmt = fmt1;
        }else if (score == score_max)
            fmt = NULL;
    }


评分算法:
   1〉文件头检查OK, 直接打100分
   2〉文件后缀匹配,直接打50分


av_iformat_next遍历的链表信息主要在av_register_all中调用REGISTER_MUXER宏来
注册。


同样
b asf_read_header
bt


可以得到如下调试信息
#0  asf_read_header (s=0x8c2f020, ap=0xbffff250) at libavformat/asfdec.c:581
#1  0x0812aff8 in avformat_open_input (ps=0xbffff2a4, 
    filename=0xbffff548 "/projects/media/wma/123.wma", fmt=0x0, 
    options=0xbffff2a0) at libavformat/utils.c:707
#2  0x0804a48f in dec_parse (filename=0xbffff548 "/projects/media/wma/123.wma")
    at fileParse.c:29
#3  0x0804a66d in main (argc=2, argv=0xbffff394) at fileParse.c:69


通过以上分析可以知道,对于ASF文件格式解析来说,
我们只需要研究如下函数。


  .read_probe     = asf_probe,
  .read_header    = asf_read_header,
  .read_packet    = asf_read_packet,
  .read_close     = asf_read_close,
  .read_seek      = asf_read_seek,
  .read_timestamp = asf_read_pts,


STEP3:
   参考上面的函数,在工作平台实现相关函数。(略)

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值