利用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:
参考上面的函数,在工作平台实现相关函数。(略)
分享到:
相关推荐
Qt+FFMPEG+SDL实现的视频播放器 包含源代码和可执行程序
qt使用FFmPeg+SDL2.0+QOpenGLWidget实现的视频播放器,FFmPeg+SDL2.0解码音视频,视频图像解码为YUV420的格式,然后使用QOpenGLWidget进行显示。亲测在windows和Linux下都可使用,附带FFmPeg+SDL2.0第三方库
基于FFMPEG+SDL2写的播放mp3文件程序,采用链表队列的方式来传递数据,详细解释见博文《基于FFMPEG+SDL2播放音频》,链接:https://blog.csdn.net/u011003120/article/details/81950045
最简单ffmpeg+sdl播放器,初学者学习ffmpeg的好资料。
FFMPEG+SDL最新库文件和源文件 FFMPEG+SDL最新库文件和源文件 FFMPEG+SDL最新库文件和源文件
ffmpeg+sdl播放器解码视音频,使用ffmpeg-2.5.2+SDL-1.2.15,参考ffmpeg官方例子,欢迎交流 内含10个工程 1.保存为bmp图片 2.解码视频 3.解码视频, 音频 4.分离代码,加入线程(伪同步) 5.视频同步到音频 6.音频同步到...
最简单的基于FFMPEG+SDL的视频播放器_FFMPEG解决方法.rar
QT工程,ffmpeg+SDL显示h264文件
FFMPEG+SDL实现视频播放,有声音,有图像(用MINGW编译的软件) 软件解码H.264 ,播放 mp4 可以用快进,全屏
1.ffmpeg+sdl+gcc环境搭建 2.用于后续ffmpeg开发 3.资源有ffmpeg+sdl2相关库文件+gcc编译器 4.后面的资源只提供代码
QT + ffmpeg + sdl音频播放器, 利用ffmpeg解码,sdl播放声音。
ffmpeg +SDL 视频播放实例(目前只能显示视频,没有声音)
ffmpeg+SDL2实现的音频播放器 博客:http://blog.csdn.net/i_scream_/article/details/52736200 中的代码。
FFMPEG工程浩大,可以参考的书籍又不是很多,...但是几乎包含了使用FFMPEG播放一个视频所有必备的API,并且使用SDL显示解码出来的视频。十分适合新手学习FFmpeg。 使用了2014.5.6编译的类库,支持最新的HEVC以及VP9.
ffmpeg+sdl教程----编写一个简单的播放器5(同步视频到音频) ffmpeg+sdl教程----------编写一个简单的播放器1
基于FFmpeg+SDL的视频播放器_其它文档,包含视频编码格式标准文档与VS开发的基础文档。
FFmpeg解码视频,并通过SDL来播放视频,学习FFmpeg编辑、学习SDL的同学都可以下载学习。
本例程采用ffmpeg+SDL展示ffmpeg的解码、播放显示过程。
FFmpeg+SDL的视频播放器资料: (0) 大纲 (1) 视音频基础知识 (2) FFmpeg命令行工具的使用 (3) FFmpeg视频解码器 (4) SDL视频显示 (5) FFmpeg+SDL视频播放器 (6) FFmpeg+SDL视频播放器-图形界面版
集成RTSP+FFmpeg+SDL的库