ffmpeg关于io的输入输出操作

来源:互联网 发布:安卓数据恢复软件 编辑:程序博客网 时间:2024/06/02 16:42

                                     ffmpeg关于io的输入输出操作

ffmpeg 无论转码是本地文件输入输出,例如将mp4文件 转成 flv文件,或者从rtmp流接入到rtsp流,这时候我们在输入输出端拿不到数据流,只能拿到输入输出的地址,这时候ffmpeg的 io就出场了,道理是把输入输出流写入到缓存中,在做处理。应用场景例如:从http 拿到的数据流,从摄像头拿到的数据流,这些都能作为io输入,将mux后的数据write到io用于存成文件,或者librtmp打包出去,这些都用于io输出。具体操作如下:

1:ffmpeg的IO输入

Io_Buf_Info buf_info;//这里必须用av_malloc申请,用calloc申请会崩溃buf_info.BufLen = DEMUX_MAX_IO_BUF_SIZE;buf_info.Buf = (char * )av_malloc(buf_info.BufLen);m_list_format_io_buf[rtmpaddress_id] = (buf_info);AVIOContext * pb = NULL;AVInputFormat *piFmt = NULL;AVFormatContext * m_pFmt = NULL;//step1:申请一个AVIOContext,传入回调函数//填写当前要读的rtmpaddress_id 回调里面才能知道去读哪一个地址的流param->use_rtmpaddress_id = rtmpaddress_id;pb = avio_alloc_context((unsigned char *)buf_info.Buf, buf_info.BufLen,0, param,param->read_packet_cb, NULL,param->seek_cb);if (!pb) {printf("ERROR : avio alloc failed!\n");return -1;}//step2:探测流格式if (av_probe_input_buffer2(pb, &piFmt, "", NULL,0,0) < 0) {printf("ERROR : probe failed!\n");return -1;} else {printf("SUCCESS :probe success!\n");printf("format: %s[%s]\n", piFmt->name, piFmt->long_name);}m_pFmt = avformat_alloc_context();m_pFmt->pb = pb; //step3:这一步很关键//step4:打开流if (avformat_open_input(&m_pFmt, "", piFmt, NULL) < 0){printf("ERROR : avformat open failed.\n");return -1;} else {printf("SUCCESS : open stream success!\n");}av_dump_format(m_pFmt, 0, "", 0);
这样就和本地文件一样用av_read_frame读取数据read_packet_cb中放入数据。

2:ffmpeg的IO输出

<pre name="code" class="cpp">Module_StreamInfo * module_streaminfo = in_video->second;AVFormatContext * formatcontext = avformat_alloc_context();AVIOContext * pb = NULL;AVStream * ovideo_st = NULL;   Io_Buf_Info  io_buf_info_video;io_cb_write_pram * cb_pram_video = NULL;cb_pram_video = (io_cb_write_pram *)malloc(sizeof(io_cb_write_pram )* 1);cb_pram_video->thisclass  = this;cb_pram_video->pram = module_streaminfo;m_list_cb_write_pram[module_streaminfo->stream_id] = (cb_pram_video);//step1 申请一个AVFormatContext if (m_mux_info.mux_format == MuxFormat_Flv){avformat_alloc_output_context2(&formatcontext, NULL,"flv",NULL); }else if (m_mux_info.mux_format == MuxFormat_Mpegts){avformat_alloc_output_context2(&formatcontext, NULL,"mpegts",NULL); }else if (m_mux_info.mux_format == MuxFormat_Mp4){avformat_alloc_output_context2(&formatcontext, NULL,"mp4",NULL); }else{avformat_alloc_output_context2(&formatcontext, NULL,"flv",NULL); }if (!formatcontext)   {  return -1;}    //step2申请一个AVIOContext//这里分配大小一定要是4096的整数倍,足够一帧大小否则中断io_buf_info_video.BufLen = (module_streaminfo->VideoInfo.Width * module_streaminfo->VideoInfo.Height * 3 /20 + 100) /4096 * 4096;io_buf_info_video.Buf =(char *)calloc(module_streaminfo->BufLen,sizeof(char));m_list_format_io_buf[in_video->first] = (io_buf_info_video);pb = avio_alloc_context((unsigned char *)m_list_format_io_buf[in_video->first].Buf,m_list_format_io_buf[in_video->first].BufLen,1,cb_pram_video, NULL, cb_write_data, NULL);if (!pb) {printf("error : avio alloc failed!\n");return -1;}//step3:这一步很关键,将输出的buf和AVFormatContext关联formatcontext->pb = pb; //The caller has supplied a custom AVIOContext, don't avio_close() it.//AVFMT_FLAG_FLUSH_PACKETS这个值相当重要,他决定每次写av_interleaved_write_frame,是否立刻返回formatcontext->flags = AVFMT_FLAG_CUSTOM_IO | AVFMT_FLAG_FLUSH_PACKETS;  //step4 添加流信息ovideo_st = add_out_stream2(formatcontext,AVMEDIA_TYPE_VIDEO,module_streaminfo);if (ovideo_st == NULL){return -1;}//这里要填写1否则中断av_dump_format(formatcontext, 0, "", 1);ret = avformat_write_header(formatcontext, NULL);  if (ret != 0)  {  printf("Call avformat_write_header function failed.\n");  return -1;  }avio_flush(pb);

这样在cb_write_data回调中就有要的数据了。


如有错误请指正:

交流请加QQ群:62054820
QQ:379969650.


0 0
原创粉丝点击