zoukankan      html  css  js  c++  java
  • ffmpeg 使用 gdb 调试相关技巧

    本文说明了,在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
    ");
    }
    
    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!
    ");
            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!
    ");
            return -1;
        }
    
        if(avcodec_open2(pCodecCtx, pCodec, NULL) < 0)
        {
            printf("Error: call avcodec_open2 failed!
    ");
            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
    ", 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..
    ");
            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
    ");
                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..
    ");
                    return -1;
                }
                av_free_packet(packet);
            }
    
        }
    
        //flush encoder
        ret = flush_encoder(pFormatCtx, 0);
        if(ret < 0)
        {
            printf("Error: call flush_encoder failed!
    ");
            return -1;
        }
    
        if(av_write_trailer(pFormatCtx) < 0)
        {
            printf("Error: call av_write_trailer..
    ");
            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...
    ");
    
        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调试

  • 相关阅读:
    如何上架一个iOS APP(2020年最新版教程)
    可以在Windows申请iOS证书上架iOS APP---Appuploader
    上传了ipa但iTunes Connect没有构建版本问题
    iOS证书类型介绍及申请教程
    APP专用密码app-specific password怎么设置
    Windows电脑申请iOS证书教程及工具分享
    【2020】申请iOS个人开发者账号流程
    【分享】使用免费的苹果开发者账号申请iOS证书打包测试教程
    iOS证书及描述文件制作流程详解
    linux /bin/bash^M: bad interpreter的解决办法
  • 原文地址:https://www.cnblogs.com/standardzero/p/10840009.html
Copyright © 2011-2022 走看看