本文说明了,在ffmpeg二次开发或调用库的过程,如何借助于ffmpeg源码进行调试。

:ffmpeg版本是4.0。

1. 编写代码

编写将pcm数据转换为mp2的代码

pcm_to_mp2.c

#include <libavformat/avformat.h>
#include <libavcodec/avcodec.h>
#include <libswresample/swresample.h>
#include <stdio.h>
#include <stdbool.h> SwrContext *g_swr_ctx = NULL; int flush_encoder(AVFormatContext *fmt_ctx, unsigned int stream_index)
{
int ret = 0;
int got_frame = 0;
AVPacket enc_pkt;
if(!(fmt_ctx->streams[stream_index]->codec->codec->capabilities &
CODEC_CAP_DELAY))
{
return 0;
} while(1)
{
enc_pkt.data = NULL;
enc_pkt.size = 0;
av_init_packet(&enc_pkt);
ret = avcodec_encode_audio2(fmt_ctx->streams[stream_index]->codec, &enc_pkt, NULL, &got_frame);
if(ret < 0)
{
break;
}
if(!got_frame)
{
ret = 0;
break;
} ret = av_write_frame(fmt_ctx, &enc_pkt);
if(ret < 0)
{
break;
}
} return ret;
} void usage(void)
{
printf("./aac input_file output_file.mp2\n");
} int main(int argc, char *argv[])
{ if(argc != 3)
{
usage();
return -1;
} char *input_file = argv[1];
char *output_file = argv[2]; AVFormatContext *pFormatCtx = NULL;
AVOutputFormat *ofmt = NULL;
AVStream *audio_stream = NULL;
AVCodecContext *pCodecCtx = NULL;
AVCodec *pCodec = NULL; uint8_t *frame_buf = NULL;
AVFrame *pFrame = NULL;
AVPacket pkt; int got_frame = 0;
int ret = 0;
int size = 0; int i = 0; FILE *fp = fopen(input_file, "rb"); av_register_all();
avformat_alloc_output_context2(&pFormatCtx, NULL, NULL, output_file);
ofmt = pFormatCtx->oformat; if(avio_open(&pFormatCtx->pb, output_file, AVIO_FLAG_READ_WRITE) < 0)
{
printf("Error: call avio_open failed!\n");
return -1;
} audio_stream = avformat_new_stream(pFormatCtx, 0);
if(!audio_stream)
{
return -1;
} //初始化编码器
pCodecCtx = audio_stream->codec;
pCodecCtx->codec_id = ofmt->audio_codec;
pCodecCtx->codec_type = AVMEDIA_TYPE_AUDIO;
pCodecCtx->sample_fmt = AV_SAMPLE_FMT_S16;
pCodecCtx->channel_layout = AV_CH_LAYOUT_STEREO;
pCodecCtx->channels = av_get_channel_layout_nb_channels(pCodecCtx->channel_layout);
pCodecCtx->sample_rate = 44100;
pCodecCtx->bit_rate = 192000;
pCodecCtx->frame_size = 1152; AVFrame *src_frame = NULL;
AVFrame *dst_frame = NULL; src_frame = av_frame_alloc();
src_frame->nb_samples = 1152;
src_frame->sample_rate = 44100;
src_frame->format= AV_SAMPLE_FMT_S16;
src_frame->channel_layout = AV_CH_LAYOUT_STEREO;
src_frame->channels = av_get_channel_layout_nb_channels(src_frame->channel_layout); pCodec = avcodec_find_encoder(pCodecCtx->codec_id);
if(!pCodec)
{
printf("Error: call avcodec_find_encoder failed!\n");
return -1;
} if(avcodec_open2(pCodecCtx, pCodec, NULL) < 0)
{
printf("Error: call avcodec_open2 failed!\n");
return -1;
} int sr_size = 0;
sr_size = av_samples_get_buffer_size(NULL, src_frame->channels, src_frame->nb_samples, src_frame->format, 1);
frame_buf = (uint8_t *)av_malloc(sr_size);
if(!frame_buf)
{
printf("Error: call av_malloc failed, sr_size = %d\n", sr_size);
return -1;
} if(av_sample_fmt_is_planar(src_frame->format))
{
avcodec_fill_audio_frame(src_frame, src_frame->channels, src_frame->format, (const uint8_t *)frame_buf, sr_size * src_frame->channels, 1 );
}
else
{
avcodec_fill_audio_frame(src_frame, src_frame->channels, src_frame->format, (const uint8_t *)frame_buf, sr_size, 0 );
} //Write Header
if(avformat_write_header(pFormatCtx,NULL) < 0)
{
printf("Error: call avformat_write_header..\n");
return -1;
} AVPacket *packet = (AVPacket *)av_malloc(sizeof(AVPacket));
av_init_packet(packet); av_dump_format(pFormatCtx, 0, output_file, 1); src_frame->pts = 0;
while(fread(frame_buf, 1, sr_size, fp) > 0)
{
got_frame = 0; ret = avcodec_encode_audio2(pCodecCtx, packet, src_frame, &got_frame);
if(ret < 0)
{
printf("Error: call avcodec_encode_audio2\n");
return -1;
}
i++; src_frame->pts = i * 100; if(1 == got_frame)
{
packet->stream_index = audio_stream->index;
ret = av_write_frame(pFormatCtx, packet);
if(ret < 0)
{
printf("Error: call av_write_frame..\n");
return -1;
}
av_free_packet(packet);
} } //flush encoder
ret = flush_encoder(pFormatCtx, 0);
if(ret < 0)
{
printf("Error: call flush_encoder failed!\n");
return -1;
} if(av_write_trailer(pFormatCtx) < 0)
{
printf("Error: call av_write_trailer..\n");
return -1;
} if(audio_stream)
{
avcodec_close(audio_stream->codec);
av_free(src_frame);
av_free(frame_buf);
} avio_close(pFormatCtx->pb);
avformat_free_context(pFormatCtx);
av_free(packet); fclose(fp); printf("Encode Audio End...\n"); return 0;
}

2. 编译ffmpeg源码

$ ./configure --enable-static --disable-shared --enable-debug --disable-optimizations --disable-asm --disable-stripping --enable-doc

$ make -j 4

3. 将代码放置在examples下

pcm_to_mp2.c拷贝到 doc/examples目录下,该目录下都是ffmpeg的例子程序。

4. 添加编译配置

修改doc/Makefile文件添加pcm_to_mp2的编译项目。

修改ffbuild/config.mak文件,

添加CONFIG_PCM_TO_MP2_EXAMPLE=yes宏。

5. 编译

ffmpeg源码根目录下,执行make examples

这样就在doc/examples目录下生成了pcm_to_mp2的可执行程序。

6. gdb调试

ffmpeg 使用 gdb 调试相关技巧的更多相关文章

  1. Linux下编译ffmpeg并用GDB调试

    1.在Ubuntu界面上调处命令行界面,最方便的方式是使用快捷键Ctrl+Alt+T. 2.安装SDL SDL是一个开源的多媒体开发库,可以设置图像和视频的绘制等操作.如果不安装SDL,FFMPEG将 ...

  2. gdb调试相关

    GDB调试及其调试脚本的使用返回脚本百事通一.GDB调试 1.1. GDB 概述 GDB是GNU开源组织发布的一个强大的UNIX下的程序调试工具.或许,各位比较喜欢那种图形界面方式的,像VC.BCB等 ...

  3. gdb调试小技巧

    1.进入gdb,需要源码,然后gdb+可执行文件,如果要看代码一起的就gdb+可执行文件+tui 2.设置参数 set args +参数 3.设置断点,可以b +行数或者b+函数名字 4.r就是一直跑 ...

  4. GDB调试-从入门到实践

    你好,我是雨乐! 在上篇文章中,我们分析了线上coredump产生的原因,其中用到了coredump分析工具gdb,这几天一直有读者在问,能不能写一篇关于gdb调试方面的文章,今天借助此文,分享一些工 ...

  5. roslaunch & gdb 调试指南(待补充)

    1. 安装xterm sudo apt-get install xterm 2. 在launch文件中添加如下内容: <node name="navigation" pkg= ...

  6. gdb调试器在windows下的相关内容

    1.gdb调试器在visual studio或dev c++中也有类似的调试图形化可视界面,但是gdb不同的是它是由命令行组成,他的界面对于习惯图形化可视界面的用户来说一时间会不知所措 2.通过gcc ...

  7. gdb调试运行时的程序小技巧

    使用gdb调试运行时的程序小技巧 标签: 未分类 gdb pstack | 发表时间:2012-10-15 04:32 | 作者:士豪 分享到: 出处:http://rdc.taobao.com/bl ...

  8. ffmpeg调试相关知识点

    1.若要调试FFMPEG,在编译时应当在configure时,加上 --enable-debug --disable-asm 注:在调试x264时就应该加上这两个配置选项,方能调试 2.make in ...

  9. GDB调试技巧:总结篇

    目录 一 写在开头 1.1 本文内容 二 学习资料 三 常用命令 四 调试技巧 注:原创不易,转载请务必注明原作者和出处,感谢支持! 一 写在开头 1.1 本文内容 总结GDB调试的一些常用命令和调试 ...

随机推荐

  1. ansible中roles的简单使用

    一.初识roles 上节中我们已经了解了playbook,详见  https://www.cnblogs.com/wangtaobiu/p/10691689.html 当我们在配置playbook时会 ...

  2. 题解[NOIP2017] 列队

    题解[NOIP2017] 列队 题面 解析 看到这题时感觉这个编号很难维护啊? 后来看了lzf大佬的题解才会.. 首先,考虑一个稍微暴力的做法, 维护每一行的前\(m-1\)个人和最后一列的\(n\) ...

  3. P3306 [SDOI2013]随机数生成器

    思路:\(BSGS\) 提交:\(1\)次 题解: 原式可以化为\[x_{i+1}+\frac{b}{a-1}=a(x_{i}+\frac{b}{a-1})\mod p\] 这不是等比数列吗? \[x ...

  4. js实现上传文件夹

    上传大文件的解决方案 需求:项目要支持大文件上传功能,经过讨论,初步将文件上传大小控制在500M内,因此自己需要在项目中进行文件上传部分的调整和配置,自己将大小都以501M来进行限制. 第一步: 前端 ...

  5. java+上传文件夹

    最近在学习百度的开源上传组件WebUploader,写了一些示例以记录.WebUploader的缺点是没有一个比较好的现成的界面,这个界面需要自己去实现.自由度高了一些. WebUploader是由B ...

  6. luogu 1903 [国家集训队]数颜色 / 维护队列 带修改莫队

    十分玄学的数据结构~ code: #include <bits/stdc++.h> #define N 1000006 #define setIO(s) freopen(s".i ...

  7. cmake 学习-cmakelists.txt

    #设置库的路径,电脑里有qt4以及qt5,使用qt5时 设置qt5的环境变量(路径). set(CMAKE_PREFIX_PATH $ENV{QTDIR}) #设定工程名称 Project(prona ...

  8. 【概率论】3-5:边缘分布(Marginal Distribution)

    title: [概率论]3-5:边缘分布(Marginal Distribution) categories: Mathematic Probability keywords: Marginal p. ...

  9. 2018CCPCFINAL B Balance of the Force 枚举最大值

    题意 n个人能选择黑暗面和光明面,选择两个面分别能获得\(L_i\)和\(R_i\)的力量,有m对人不能选择同一面,问n个人的力量中的最大值-最小值尽可能小为多少. \(1<=n<=2\t ...

  10. openssl 模块 安装 centso Ubuntu

    备忘: centos: yum install openssl-devel ubuntu: apt-get install libssl-dev 哎... 这玩意总是记不住. 每次都得搜索好麻烦.