ffmpeg转码多路输出(二)

ffmpeg转码多路输出(二)

本程序支持一路输入多路输出,可根据map配置自行添加,第1路为纯拷贝,其他2路经过编解码,格式转换缩放和重采样,纯拷贝方面不同格式适应方面还没做全,以后补充。本程序适合多分辨率切换等方面内容。注意重采样等方面的注释内容。

具体看代码:

//main.cpp

#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();
}

//.h

#ifndef __FFMPEG_TRANSCODE_H__  
#define __FFMPEG_TRANSCODE_H__  

#include <string.h> 
#include <stdio.h>
#include <vector>
#include <map>
#include <list>

using namespace std;

extern "C"  
{  
#include "libavformat/avformat.h"  
#include "libavformat/avio.h"  
#include "libavcodec/avcodec.h"  
#include "libswscale/swscale.h"  
#include "libavutil/avutil.h"  
#include "libavutil/mathematics.h"  
#include "libswresample/swresample.h"  
#include "libavutil/opt.h"  
#include "libavutil/channel_layout.h"  
#include "libavutil/samplefmt.h"  
#include "libavdevice/avdevice.h"  //摄像头所用  
#include "libavfilter/avfilter.h"  
#include "libavutil/error.h"  
#include "libavutil/mathematics.h"    
#include "libavutil/time.h"    
#include "libavutil/fifo.h"  
#include "libavutil/audio_fifo.h"   //这里是做分片时候重采样编码音频用的  
#include "inttypes.h"  
#include "stdint.h"  
};  

#pragma comment(lib,"avformat.lib")  
#pragma comment(lib,"avcodec.lib")  
#pragma comment(lib,"avdevice.lib")  
#pragma comment(lib,"avfilter.lib")  
#pragma comment(lib,"avutil.lib")  
#pragma comment(lib,"postproc.lib")  
#pragma comment(lib,"swresample.lib")  
#pragma comment(lib,"swscale.lib")  

//#define INPUTURL   "../in_stream/22.flv"   
//#define INPUTURL "../in_stream/闪电侠.The.Flash.S01E01.中英字幕.HDTVrip.624X352.mp4"  
//#define INPUTURL   "../in_stream/33.ts"   
//#define INPUTURL   "../in_stream/22mp4.mp4"   
//#define INPUTURL   "../in_stream/EYED0081.MOV"   
//#define INPUTURL   "../in_stream/李荣浩 - 李白.mp3"   
//#define INPUTURL   "../in_stream/avier1.mp4"   
//#define INPUTURL   "../in_stream/分歧者2预告片.mp4"   
//#define INPUTURL   "../in_stream/Class8简介.m4v"   
#define INPUTURL   "../in_stream/9160_2.ts"   
//#define INPUTURL   "../in_stream/44.mp3"  
//#define INPUTURL   "../in_stream/ceshi.mp4"  
//#define INPUTURL   "../in_stream/33.mp4"  
//#define INPUTURL   "../in_stream/father.avi"  
//#define INPUTURL   "../in_stream/22.flv"  
//#define INPUTURL   "../in_stream/西海情歌.wav"   
//#define INPUTURL   "../in_stream/Furious_7_2015_International_Trailer_2_5.1-1080p-HDTN.mp4"   
//#define INPUTURL   "../in_stream/Wildlife.wmv"   
//#define INPUTURL   "../in_stream/单身男女2.HD1280超清国语版.mp4"   
//#define INPUTURL     "rtmp://221.228.193.50:1935/live/teststream1"   
#define OUTPUTURL  "../out_stream/output.flv" 
//http://10.69.112.96:8080/live/10flv/index.m3u8
#define OUTPUTURL10  "../out_stream/10.flv"
//#define OUTPUTURL10   "rtmp://10.69.112.96:1936/live/10flv"
#define OUTPUTURL11  "../out_stream/11.flv"  
//#define OUTPUTURL11   "rtmp://10.69.112.96:1936/live/11flv"
#define OUTPUTURL12  "../out_stream/12.flv"  
//#define OUTPUTURL12   "rtmp://10.69.112.96:1936/live/12flv"
//#define OUTPUTURL    "rtmp://221.228.193.50:1935/live/zwg"  
//#define OUTPUTURL    "rtmp://221.228.193.50:1935/live/zwg"  


//样本枚举
enum AVSampleFormat_t   
{  
	AV_SAMPLE_FMT_NONE_t = -1,  
	AV_SAMPLE_FMT_U8_t,          ///< unsigned 8 bits  
	AV_SAMPLE_FMT_S16_t,         ///< signed 16 bits  
	AV_SAMPLE_FMT_S32_t,         ///< signed 32 bits  
	AV_SAMPLE_FMT_FLT_t,         ///< float  
	AV_SAMPLE_FMT_DBL_t,         ///< double  

	AV_SAMPLE_FMT_U8P_t,         ///< unsigned 8 bits, planar  
	AV_SAMPLE_FMT_S16P_t,        ///< signed 16 bits, planar  
	AV_SAMPLE_FMT_S32P_t,        ///< signed 32 bits, planar  
	AV_SAMPLE_FMT_FLTP_t,        ///< float, planar  
	AV_SAMPLE_FMT_DBLP_t,        ///< double, planar  

	AV_SAMPLE_FMT_NB_t           ///< Number of sample formats. DO NOT USE if linking dynamically  
};  


#define OUT_AUDIO_ID            0                                                 //packet 中的ID ,如果先加入音频 pocket 则音频是 0  视频是1,否则相反(影响add_out_stream顺序)  
#define OUT_VIDEO_ID            1  

//多路输出每一路的信息结构体
typedef struct Out_stream_info_t
{
	//user info
	int user_stream_id;                 //多路输出每一路的ID
	//video param  
	int m_dwWidth;  
	int m_dwHeight;  
	double m_dbFrameRate;               //帧率                                                    
	int m_video_codecID;  
	int m_video_pixelfromat; 
	int m_bit_rate;                     //码率
	int m_gop_size;  
	int m_max_b_frame;  
	int m_thread_count;                 //用cpu内核数目  
	//audio param  
	int m_dwChannelCount;               //声道  
	AVSampleFormat_
  • 4
    点赞
  • 15
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值