AVFormatContext的初始化

网上关于这个结构的介绍有很多,我在之前最初学习时查看过相关源码记录了一些笔记,由于更换固态硬盘笔记一直在原来128g的固态中,想将其改成U盘成本实在是太高,很多笔记都扔在里面了,真的好蛋疼,我直接写一些我的使用,其他的在一点一点完善

AVFormatContext* get_input_avformatcontex_f(char *input_url){
    int ret = 0;
    char errbuf[1024] = {0,};
    AVFormatContext *fmt_ctx = NULL;
    AVInputFormat *ifmt = NULL;
    AVDictionary *options = NULL;
    ifmt = av_find_input_format("avfoundation");
    //查看设备支持什么作为输入
    av_dict_set(&options,"list_devices","true",0);
    char *input_stream_url = input_url; //设置输入源通常为本地文件或一些链接
    //如果是使用ffmpeg进行采集则需要设置一些音频或视频的采集参数 
    /*
     av_dict_set(&options, "video_size", w_h_c_str, 0);
     av_dict_set(&options, "framerate", "30", 0);
     av_dict_set(&options, "pixel_format", "nv12", 0);
        {"pixel_format", "set pixel format", OFFSET(pix_fmt), AV_OPT_TYPE_PIXEL_FMT, {.i64=AV_PIX_FMT_NONE}, -1, INT_MAX, 0 },
        {"video_size", "set video size", OFFSET(width), AV_OPT_TYPE_IMAGE_SIZE, {.str=NULL}, 0, INT_MAX, 0 }, {NULL}, };
    */
    av_log_set_level(AV_LOG_DEBUG);
    if ((ret = avformat_open_input(&fmt_ctx, input_stream_url, ifmt, &options)) < 0){
        av_strerror(ret, errbuf, 1024);
        fprintf(stderr, "Failed to open audio device, [%d]%s\n", ret, errbuf);
        return NULL;
    }

    return fmt_ctx;
}

然后创建一个AVPacket用来接收封装数据

AVPacket* get_avpacket_f_input(){
    AVPacket *av_packet = NULL;
    av_packet = av_packet_alloc();
    if (!av_packet) {
        fprintf(stderr,"av_packet_alloc failed");
        goto __ERROR;
    }
    return av_packet;
__ERROR:
    if (!av_packet) {
        av_packet_free(&av_packet);
    }
    return NULL;
}

在打开输入上下文之后可以对获取数据进行解码

-(void)decode_audio:(AVCodecContext *)input_ctx and_packet:(AVPacket *)input_avpacket{
    int ret = -1;
    ret = avcodec_send_packet(input_ctx, input_avpacket);
    while (ret >=0 ) {
        ret = avcodec_receive_frame(input_ctx,input_a_frame);
        if (ret == AVERROR(EAGAIN) || ret == AVERROR_EOF)
            return;
        else if (ret < 0) {
            fprintf(stderr, "Error during decoding\n");
            exit(1);
        }
        if (ret >= 0) {          
            self.callback(Collect_Data_Audio, input_a_frame);
        }
        av_packet_unref(input_packet);//一定要记得释放 如果不释放内存会暴涨
    }
}

可以在获取数据之前查看输入流的相关信息代码如下

- (void)get_input_stream_oc:(char *)input_url and_avFormatContext:(AVFormatContext *)input_fmt{
    avformat_find_stream_info(input_fmt, NULL);
    av_dump_format(input_fmt, 0, input_url , 0);
    for (int i = 0; i < input_fmt->nb_streams; i++) {
         AVStream  *stream = input_fmt->streams[i];
        if (stream->codecpar->codec_type == AVMEDIA_TYPE_AUDIO) {//打印流信息
            audio_stream_index = i;
        }else if(stream->codecpar->codec_type == AVMEDIA_TYPE_VIDEO){
            video_stream_index = i;
        }
    }
    //音频
    AVCodec *acodec = avcodec_find_decoder(input_fmt->streams[audio_stream_index]->codecpar->codec_id);
    AVCodecContext *ac = avcodec_alloc_context3(acodec);
    ac->sample_rate = input_fmt->streams[audio_stream_index]->codecpar->sample_rate;
    ac->sample_fmt = input_fmt->streams[audio_stream_index]->codecpar->format;
    ac->channels = input_fmt->streams[audio_stream_index]->codecpar->channels;
    avcodec_open2(ac, acodec, NULL);
    
    AVFrame *frame = av_frame_alloc();
    frame->nb_samples = ac->frame_size;
    frame->channel_layout = ac->channel_layout;
    frame->format = ac->sample_fmt;
    
    av_frame_get_buffer(frame, 0);
    input_de_codec_a = acodec;
    input_de_ctx_a = ac;
    input_a_frame = frame;
    //视频
    AVCodecContext* vc = input_fmt->streams[video_stream_index]->codec;
    AVCodec* vcodec = avcodec_find_decoder(vc->codec_id);
    avcodec_open2(vc, vcodec, NULL);
    AVFrame *vframe = av_frame_alloc();
    av_frame_get_buffer(vframe, 0);
    input_de_codec_v = vcodec;
    input_de_ctx_v = vc;
    input_v_frame = vframe; //c函数内无法这样给成员变量赋值 应该是语法的问题
    [self config_av_inputfmt:fmt_ctx and_videoindex:video_stream_index and_audioindex:audio_stream_index];
}

我将采集到的裸数据以call的形式返回到调用出在外部,在外部可以进行放入队列或者是重采样编码等操作

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值