javaee论坛

普通会员

225648

帖子

344

回复

358

积分

楼主
发表于 2017-06-08 11:03:20 | 查看: 700 | 回复: 1

                                     ffmpeg关于io的输入输出操作

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

1:ffmpeg的IO输入

< code_snippet_id="1907016" snippet_file_name="blog_20160929_1_5170823" code_snippet_id="1907016" snippet_file_name="blog_20160929_1_5170823" name="code" class="cpp"> 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输出

< code_snippet_id="1907016" snippet_file_name="blog_20160929_2_3677107" code_snippet_id="1907016" snippet_file_name="blog_20160929_2_3677107" name="code" class="cpp">< 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

帖子

308

回复

316

积分
沙发
发表于 2023-11-13 14:54:18

谢谢

您需要登录后才可以回帖 登录 | 立即注册

触屏版| 电脑版

技术支持 历史网 V2.0 © 2016-2017