https://blog.csdn.net/zhuweigangzwg/article/details/72481966
ffmpeg转码多路输出(二)
本程序支持一路输入多路输出,可根据map配置自行添加,第1路为纯拷贝,其他2路经过编解码,格式转换缩放和重采样,纯拷贝方面不同格式适应方面还没做全,以后补充。本程序适合多分辨率切换等方面内容。注意重采样等方面的注释内容。
具体看代码:
#include "ffmpeg_transcode.h"
/*
int main()
{
AVOutputFormat *ofmt = NULL;
AVFormatContext *ifmt_ctx = NULL, *ofmt_ctx = NULL;
AVPacket pkt;
int ret, i;
av_register_all();
if ((ret = avformat_open_input(&ifmt_ctx, INPUTURL, 0, 0)) < 0) {
fprintf(stderr, "Could not open input file '%s'", INPUTURL);
}
if ((ret = avformat_find_stream_info(ifmt_ctx, 0)) < 0) {
fprintf(stderr, "Failed to retrieve input stream information");
}
av_dump_format(ifmt_ctx, 0, INPUTURL, 0);
avformat_alloc_output_context2(&ofmt_ctx, NULL, NULL, OUTPUTURL);
if (!ofmt_ctx) {
fprintf(stderr, "Could not create output context\n");
ret = AVERROR_UNKNOWN;
}
ofmt = ofmt_ctx->oformat;
for (i = 0; i < ifmt_ctx->nb_streams; i++) {
AVStream *in_stream = ifmt_ctx->streams[i];
AVStream *out_stream = avformat_new_stream(ofmt_ctx, in_stream->codec->codec);
if (!out_stream) {
fprintf(stderr, "Failed allocating output stream\n");
ret = AVERROR_UNKNOWN;
}
ret = avcodec_copy_context(out_stream->codec, in_stream->codec);
if (ret < 0) {
fprintf(stderr, "Failed to copy context from input to output stream codec context\n");
}
out_stream->codec->codec_tag = 0;
if (ofmt_ctx->oformat->flags & AVFMT_GLOBALHEADER)
out_stream->codec->flags |= CODEC_FLAG_GLOBAL_HEADER;
}
if (!(ofmt->flags & AVFMT_NOFILE)) {
ret = avio_open(&ofmt_ctx->pb, OUTPUTURL, AVIO_FLAG_WRITE);
if (ret < 0) {
fprintf(stderr, "Could not open output file '%s'", OUTPUTURL);
}
}
ret = avformat_write_header(ofmt_ctx, NULL);
if (ret < 0) {
fprintf(stderr, "Error occurred when opening output file\n");
}
av_dump_format(ofmt_ctx, 0, OUTPUTURL, 1);
AVBitStreamFilterContext * m_vbsf_aac_adtstoasc; //aac->adts to asc过滤器
m_vbsf_aac_adtstoasc = av_bitstream_filter_init("aac_adtstoasc");
while (1)
{
AVStream *in_stream, *out_stream;
ret = av_read_frame(ifmt_ctx, &pkt);
if (ret < 0)
break;
in_stream = ifmt_ctx->streams[pkt.stream_index];
out_stream = ofmt_ctx->streams[pkt.stream_index];
pkt.pts = av_rescale_q_rnd(pkt.pts, in_stream->time_base, out_stream->time_base, AVRounding(AV_ROUND_NEAR_INF|AV_ROUND_PASS_MINMAX));
pkt.dts = av_rescale_q_rnd(pkt.dts, in_stream->time_base, out_stream->time_base, AVRounding(AV_ROUND_NEAR_INF|AV_ROUND_PASS_MINMAX));
pkt.duration = av_rescale_q(pkt.duration, in_stream->time_base, out_stream->time_base);
pkt.pos = -1;
if (in_stream->codec->codec_type == AVMEDIA_TYPE_AUDIO)
{
if (m_vbsf_aac_adtstoasc != NULL)
{
AVPacket filteredPacket = pkt;
int a = av_bitstream_filter_filter(m_vbsf_aac_adtstoasc,
out_stream->codec, NULL,&filteredPacket.data, &filteredPacket.size,
pkt.data, pkt.size, pkt.flags & AV_PKT_FLAG_KEY);
if (a > 0)
{
av_free_packet(&pkt);
filteredPacket.destruct = av_destruct_packet;
pkt = filteredPacket;
}
else if (a == 0)
{
pkt = filteredPacket;
}
else if (a < 0)
{
fprintf(stderr, "%s failed for stream %d, codec %s",
m_vbsf_aac_adtstoasc->filter->name,pkt.stream_index,out_stream->codec->codec ? out_stream->codec->codec->name : "copy");
av_free_packet(&pkt);
}
}
}
ret = av_interleaved_write_frame(ofmt_ctx, &pkt);
if (ret < 0)
{
break;
}
av_packet_unref(&pkt);
}
av_write_trailer(ofmt_ctx);
avformat_close_input(&ifmt_ctx);
if (ofmt_ctx && !(ofmt->flags & AVFMT_NOFILE))
{
avio_closep(&ofmt_ctx->pb);
}
avformat_free_context(ofmt_ctx);
}
*/
int main(int argc ,char ** argv)
{
int ret = 0;
av_register_all();
avformat_network_init();
ffmpeg_init_demux(INPUTURL,&m_icodec);
//out_stream1 用原始的
Out_stream_info *out_stream_info1 = NULL;
out_stream_info1 = new Out_stream_info();
out_stream_info1->user_stream_id = 10;
sprintf(out_stream_info1->m_outurlname,"%s",OUTPUTURL10);
//out_stream2
Out_stream_info *out_stream_info2 = NULL;
out_stream_info2 = new Out_stream_info();
out_stream_info2->user_stream_id = 11;
sprintf(out_stream_info2->m_outurlname,"%s",OUTPUTURL11);
out_stream_info2->m_dwWidth = 640;
out_stream_info2->m_dwHeight = 480;
out_stream_info2->m_dbFrameRate = 25;
out_stream_info2->m_video_codecID = (int)AV_CODEC_ID_H264;
out_stream_info2->m_video_pixelfromat = (int)AV_PIX_FMT_YUV420P;
out_stream_info2->m_bit_rate = 800000;
out_stream_info2->m_gop_size = 125;
out_stream_info2->m_max_b_frame = 0;
out_stream_info2->m_thread_count = 8;
out_stream_info2->m_dwChannelCount = 2;
out_stream_info2->m_dwBitsPerSample = AV_SAMPLE_FMT_S16_t;
out_stream_info2->m_dwFrequency = 44100;
out_stream_info2->m_audio_codecID = (int)AV_CODEC_ID_AAC;
//out_stream3
Out_stream_info *out_stream_info3 = NULL;
out_stream_info3 = new Out_stream_info();
out_stream_info3->user_stream_id = 12;
sprintf(out_stream_info3->m_outurlname,"%s",OUTPUTURL12);
out_stream_info3->m_dwWidth = 352;
out_stream_info3->m_dwHeight = 288;
out_stream_info3->m_dbFrameRate = 25;
out_stream_info3->m_video_codecID = (int)AV_CODEC_ID_H264;
out_stream_info3->m_video_pixelfromat = (int)AV_PIX_FMT_YUV420P;
out_stream_info3->m_bit_rate = 400000;
out_stream_info3->m_gop_size = 125;
out_stream_info3->m_max_b_frame = 0;
out_stream_info3->m_thread_count = 8;
out_stream_info3->m_dwChannelCount = 2;
out_stream_info3->m_dwBitsPerSample = AV_SAMPLE_FMT_S16_t;
out_stream_info3->m_dwFrequency = 44100;
out_stream_info3->m_audio_codecID = (int)AV_CODEC_ID_AAC;
//申请map
m_list_out_stream_info[out_stream_info1->user_stream_id] = (out_stream_info1);
m_list_out_stream_info[out_stream_info2->user_stream_id] = (out_stream_info2);
m_list_out_stream_info[out_stream_info3->user_stream_id] = (out_stream_info3);
ffmpeg_init_mux(m_list_out_stream_info,out_stream_info1->user_stream_id);
printf("--------程序运行开始----------\n");
//
ffmpeg_transcode(out_stream_info1->user_stream_id);
//
ffmpeg_uinit_mux(m_list_out_stream_info,out_stream_info1->user_stream_id);
ffmpeg_uinit_demux(m_icodec);
//释放map
if (m_list_out_stream_info.size()> 0)
{
map<int,Out_stream_info*> ::iterator result_all;
Out_stream_info * out_stream_info_all = NULL;
for (result_all = m_list_out_stream_info.begin();result_all != m_list_out_stream_info.end();)
{
out_stream_info_all = result_all->second;
if(out_stream_info_all)
{
delete out_stream_info_all;
out_stream_info_all = NULL;
}
m_list_out_stream_info.erase(result_all ++);
}
m_list_out_stream_info.clear();
}
printf("--------程序运行结束----------\n");
printf("-------请按任意键退出---------\n");
return getchar();
}