ffmpeg处理rtmp/文件/rtsp的推流和拉流

来源:互联网 发布:淘宝购物联名信用卡 编辑:程序博客网 时间:2024/05/21 21:38

ffmpeg处理rtmp/文件/rtsp的推流和拉流


本demo演示了利用ffmpeg从服务器拉流或本地文件读取流,更改流url或文件类型名称发送回服务器或存到本地的作用。
由于本程序只写了3个小时,还要忙别的,所以会有一些bug和优化的地方。不过demo的意义已经达到了。

//info.h#ifndef __INFO_H__#define __INFO_H__#include <string.h> #include <stdio.h>#endif

//ffmpeg.h#ifndef __FFMPEG_H__#define __FFMPEG_H__#include "info.h"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 "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   "test.flv" #define INPUTURL     "rtmp://test1.com:1935/myapp/teststream1" //#define OUTPUTURL  "testnew.flv"; #define OUTPUTURL    "rtmp://test1.com:1935/myapp/teststream1new"//video paramextern int m_dwWidth;extern int m_dwHeight;extern double m_dbFrameRate;  //帧率                                                  extern AVCodecID video_codecID;extern AVPixelFormat video_pixelfromat;extern char spspps[100];extern int spspps_size;//audio paramextern int m_dwChannelCount; //声道extern int m_dwBitsPerSample; //样本extern int m_dwFrequency;     //采样率extern AVCodecID audio_codecID;extern int audio_frame_size;#define AUDIO_ID            0                                                 //packet 中的ID ,如果先加入音频 pocket 则音频是 0  视频是1,否则相反#define VEDIO_ID            1extern int nRet;                                                              //状态标志extern AVFormatContext* icodec; extern AVInputFormat* ifmt;extern char szError[256];                                                     //错误字符串extern AVFormatContext* oc ;                                                  //输出流contextextern AVOutputFormat* ofmt;extern AVStream* video_st;extern AVStream* audio_st;extern AVCodec *audio_codec;extern AVCodec *video_codec;extern int video_stream_idx;extern int audio_stream_idx;extern AVPacket pkt;   extern AVBitStreamFilterContext * vbsf_aac_adtstoasc;                         //aac->adts to asc过滤器static int  m_nVideoTimeStamp = 0;static int  m_nAudioTimeStamp = 0;int InitInput(char * Filename,AVFormatContext ** iframe_c,AVInputFormat** iinputframe);int InitOutput();AVStream * Add_output_stream_2(AVFormatContext* output_format_context,AVMediaType codec_type_t, AVCodecID codecID,AVCodec **codec); int OpenCodec(AVStream * istream, AVCodec * icodec); //打开编解码器void read_frame(AVFormatContext *oc);    //从文件读取一帧数据根据ID读取不同的帧void write_frame_3(AVFormatContext *oc,int ID,AVPacket pkt_t); //这个是根据传过来的buf 和size 写入文件int Es2Mux_2(); //通过时间戳控制写入音视频帧顺序int UintInput();int UintOutput();#endif

//ffmpeg.cpp#include "ffmpeg.h"int nRet = 0;AVFormatContext* icodec = NULL; AVInputFormat* ifmt = NULL;char szError[256]; AVFormatContext* oc = NULL;AVOutputFormat* ofmt = NULL;AVStream * video_st = NULL;AVStream * audio_st = NULL;AVCodec *audio_codec;AVCodec *video_codec;double audio_pts = 0.0;double video_pts = 0.0;int video_stream_idx = -1;int audio_stream_idx = -1;AVPacket pkt;AVBitStreamFilterContext * vbsf_aac_adtstoasc = NULL;//video paramint m_dwWidth = 0;int m_dwHeight = 0;double m_dbFrameRate = 25.0;  //帧率                                                  AVCodecID video_codecID = AV_CODEC_ID_H264;AVPixelFormat video_pixelfromat = AV_PIX_FMT_YUV420P;char spspps[100];int spspps_size = 0;//audio paramint m_dwChannelCount = 2;      //声道int m_dwBitsPerSample = 16;    //样本int m_dwFrequency = 44100;     //采样率AVCodecID audio_codecID = AV_CODEC_ID_AAC;int audio_frame_size  = 1024;int InitInput(char * Filename,AVFormatContext ** iframe_c,AVInputFormat** iinputframe){int i = 0;nRet = avformat_open_input(iframe_c, Filename,(*iinputframe), NULL);if (nRet != 0){av_strerror(nRet, szError, 256);printf(szError);printf("\n");printf("Call avformat_open_input function failed!\n");return 0;}if (av_find_stream_info(*iframe_c) < 0){printf("Call av_find_stream_info function failed!\n");return 0;}//输出视频信息av_dump_format(*iframe_c, -1, Filename, 0);//添加音频信息到输出contextfor (i = 0; i < (*iframe_c)->nb_streams; i++){if ((*iframe_c)->streams[i]->codec->codec_type == AVMEDIA_TYPE_VIDEO){video_stream_idx = i;m_dwWidth = (*iframe_c)->streams[i]->codec->width;m_dwHeight = (*iframe_c)->streams[i]->codec->height;m_dbFrameRate = av_q2d((*iframe_c)->streams[i]->r_frame_rate);video_codecID = (*iframe_c)->streams[i]->codec->codec_id;video_pixelfromat = (*iframe_c)->streams[i]->codec->pix_fmt;spspps_size = (*iframe_c)->streams[i]->codec->extradata_size;memcpy(spspps,(*iframe_c)->streams[i]->codec->extradata,spspps_size);}else if ((*iframe_c)->streams[i]->codec->codec_type == AVMEDIA_TYPE_AUDIO){audio_stream_idx = i;m_dwChannelCount = (*iframe_c)->streams[i]->codec->channels;switch ((*iframe_c)->streams[i]->codec->sample_fmt){case AV_SAMPLE_FMT_U8:m_dwBitsPerSample  = 8;break;case AV_SAMPLE_FMT_S16:m_dwBitsPerSample  = 16;break;case AV_SAMPLE_FMT_S32:m_dwBitsPerSample  = 32;break;default:break;}m_dwFrequency = (*iframe_c)->streams[i]->codec->sample_rate;audio_codecID = (*iframe_c)->streams[i]->codec->codec_id;audio_frame_size = (*iframe_c)->streams[i]->codec->frame_size;}}return 1;}int InitOutput(){int i = 0;/* allocate the output media context */avformat_alloc_output_context2(&oc, NULL, "flv", OUTPUTURL);if (!oc) {return getchar();}ofmt = oc->oformat;/* open the output file, if needed */if (!(ofmt->flags & AVFMT_NOFILE)){if (avio_open(&oc->pb, OUTPUTURL, AVIO_FLAG_WRITE) < 0){printf("Could not open '%s'\n", OUTPUTURL);return getchar();}}//添加音频信息到输出contextif(audio_stream_idx != -1){ofmt->audio_codec = audio_codecID;audio_st = Add_output_stream_2(oc, AVMEDIA_TYPE_AUDIO,audio_codecID,&audio_codec);}//添加视频信息到输出contextofmt->video_codec = video_codecID;video_st = Add_output_stream_2(oc, AVMEDIA_TYPE_VIDEO,video_codecID,&video_codec);if (OpenCodec(video_st,video_codec) < 0)   //打开视频编码器{printf("can not open video codec\n");return getchar();}if(audio_stream_idx != -1){if (OpenCodec(audio_st,audio_codec) < 0)   //打开音频编码器{printf("can not open audio codec\n");return getchar();}}av_dump_format(oc, 0, OUTPUTURL, 1);if (avformat_write_header(oc, NULL)){printf("Call avformat_write_header function failed.\n");return 0;}if(audio_stream_idx != -1){if ((strstr(oc->oformat->name, "flv") != NULL) || (strstr(oc->oformat->name, "mp4") != NULL) || (strstr(oc->oformat->name, "mov") != NULL) ||(strstr(oc->oformat->name, "3gp") != NULL))    {if (audio_st->codec->codec_id == AV_CODEC_ID_AAC) //AV_CODEC_ID_AAC{vbsf_aac_adtstoasc =  av_bitstream_filter_init("aac_adtstoasc");  }} }if(vbsf_aac_adtstoasc == NULL)  {  return -1;  } return 1;}AVStream * Add_output_stream_2(AVFormatContext* output_format_context,AVMediaType codec_type_t, AVCodecID codecID,AVCodec **codec){AVCodecContext* output_codec_context = NULL;AVStream * output_stream = NULL;/* find the encoder */*codec = avcodec_find_encoder(codecID);if (!(*codec)) {return NULL;}output_stream = avformat_new_stream(output_format_context, *codec);if (!output_stream){return NULL;}output_stream->id = output_format_context->nb_streams - 1;output_codec_context = output_stream->codec;output_codec_context->codec_id = codecID;output_codec_context->codec_type = codec_type_t;switch (codec_type_t){case AVMEDIA_TYPE_AUDIO:AVRational CodecContext_time_base;CodecContext_time_base.num = 1;CodecContext_time_base.den = m_dwFrequency;output_stream->time_base = CodecContext_time_base;output_codec_context->time_base = CodecContext_time_base;output_stream->start_time = 0;output_codec_context->sample_rate = m_dwFrequency;output_codec_context->channels = m_dwChannelCount;output_codec_context->frame_size = audio_frame_size;switch (m_dwBitsPerSample){case 8:output_codec_context->sample_fmt  = AV_SAMPLE_FMT_U8;break;case 16:output_codec_context->sample_fmt  = AV_SAMPLE_FMT_S16;break;case 32:output_codec_context->sample_fmt  = AV_SAMPLE_FMT_S32;break;default:break;}output_codec_context->block_align = 0;if(! strcmp( output_format_context-> oformat-> name,  "mp4" ) ||!strcmp (output_format_context ->oformat ->name , "mov" ) ||!strcmp (output_format_context ->oformat ->name , "3gp" ) ||!strcmp (output_format_context ->oformat ->name , "flv" )){output_codec_context->flags |= CODEC_FLAG_GLOBAL_HEADER;}break;case AVMEDIA_TYPE_VIDEO:AVRational r_frame_rate_t;r_frame_rate_t.num = 1000;r_frame_rate_t.den = (int)(m_dbFrameRate * 1000);output_stream->time_base = r_frame_rate_t;output_codec_context->time_base = r_frame_rate_t;AVRational r_frame_rate_s;r_frame_rate_s.num = (int)(m_dbFrameRate * 1000);r_frame_rate_s.den = 1000;output_stream->r_frame_rate = r_frame_rate_s;output_stream->start_time = 0;output_codec_context->pix_fmt = video_pixelfromat;output_codec_context->width = m_dwWidth;output_codec_context->height = m_dwHeight;output_codec_context->extradata = (uint8_t *)spspps;output_codec_context->extradata_size = spspps_size;//这里注意不要加头,demux的时候 h264filter过滤器会改变文件本身信息//这里用output_codec_context->extradata 来显示缩略图//if(! strcmp( output_format_context-> oformat-> name,  "mp4" ) ||//!strcmp (output_format_context ->oformat ->name , "mov" ) ||//!strcmp (output_format_context ->oformat ->name , "3gp" ) ||//!strcmp (output_format_context ->oformat ->name , "flv" ))//{//output_codec_context->flags |= CODEC_FLAG_GLOBAL_HEADER;//}break;default:break;}return output_stream;}int OpenCodec(AVStream * istream, AVCodec * icodec){AVCodecContext *c = istream->codec;nRet = avcodec_open2(c, icodec, NULL); return nRet;}int UintInput(){/* free the stream */av_free(icodec);return 1;}int UintOutput(){int i = 0;nRet = av_write_trailer(oc);if (nRet < 0){av_strerror(nRet, szError, 256);printf(szError);printf("\n");printf("Call av_write_trailer function failed\n");}if (vbsf_aac_adtstoasc !=NULL){av_bitstream_filter_close(vbsf_aac_adtstoasc); vbsf_aac_adtstoasc = NULL;}av_dump_format(oc, -1, OUTPUTURL, 1); /* Free the streams. */for (i = 0; i < oc->nb_streams; i++) {av_freep(&oc->streams[i]->codec);av_freep(&oc->streams[i]);}if (!(ofmt->flags & AVFMT_NOFILE)){/* Close the output file. */avio_close(oc->pb);}av_free(oc);return 1;}void read_frame(AVFormatContext *oc){int ret = 0;ret = av_read_frame(icodec, &pkt);if (pkt.stream_index == video_stream_idx){write_frame_3(oc,VEDIO_ID,pkt);}else if (pkt.stream_index == audio_stream_idx){write_frame_3(oc,AUDIO_ID,pkt);}}void write_frame_3(AVFormatContext *oc,int ID,AVPacket pkt_t){int64_t pts = 0, dts = 0;int nRet = -1;AVRational time_base_t;time_base_t.num = 1;time_base_t.den = 1000;if(ID == VEDIO_ID){AVPacket videopacket_t;av_init_packet(&videopacket_t);if (av_dup_packet(&videopacket_t) < 0){av_free_packet(&videopacket_t);}videopacket_t.pts = pkt_t.pts;videopacket_t.dts = pkt_t.dts;videopacket_t.pos = 0;videopacket_t.priv = 0;videopacket_t.flags = 1;videopacket_t.convergence_duration = 0;videopacket_t.side_data_elems = 0;videopacket_t.stream_index = VEDIO_ID;videopacket_t.duration = 0;videopacket_t.data = pkt_t.data;videopacket_t.size = pkt_t.size;nRet = av_interleaved_write_frame(oc, &videopacket_t);if (nRet != 0){printf("error av_interleaved_write_frame _ video\n");}av_free_packet(&videopacket_t);}else if(ID == AUDIO_ID){AVPacket audiopacket_t;av_init_packet(&audiopacket_t);if (av_dup_packet(&audiopacket_t) < 0){av_free_packet(&audiopacket_t);}audiopacket_t.pts = pkt_t.pts;audiopacket_t.dts = pkt_t.dts;audiopacket_t.pos = 0;audiopacket_t.priv = 0;audiopacket_t.flags = 1;audiopacket_t.duration = 0;audiopacket_t.convergence_duration = 0;audiopacket_t.side_data_elems = 0;audiopacket_t.stream_index = AUDIO_ID;audiopacket_t.duration = 0;audiopacket_t.data = pkt_t.data;audiopacket_t.size = pkt_t.size;//添加过滤器if(! strcmp( oc-> oformat-> name,  "mp4" ) ||!strcmp (oc ->oformat ->name , "mov" ) ||!strcmp (oc ->oformat ->name , "3gp" ) ||!strcmp (oc ->oformat ->name , "flv" )){if (audio_st->codec->codec_id == AV_CODEC_ID_AAC){if (vbsf_aac_adtstoasc != NULL){AVPacket filteredPacket = audiopacket_t; int a = av_bitstream_filter_filter(vbsf_aac_adtstoasc,                                           audio_st->codec, NULL,&filteredPacket.data, &filteredPacket.size,audiopacket_t.data, audiopacket_t.size, audiopacket_t.flags & AV_PKT_FLAG_KEY); if (a >  0)             {                av_free_packet(&audiopacket_t); filteredPacket.destruct = av_destruct_packet;  audiopacket_t = filteredPacket;             }   else if (a == 0){audiopacket_t = filteredPacket;   }else if (a < 0)            {                fprintf(stderr, "%s failed for stream %d, codec %s",vbsf_aac_adtstoasc->filter->name,audiopacket_t.stream_index,audio_st->codec->codec ?  audio_st->codec->codec->name : "copy");av_free_packet(&audiopacket_t);   }}}}nRet = av_interleaved_write_frame(oc, &audiopacket_t);if (nRet != 0){printf("error av_interleaved_write_frame _ audio\n");}av_free_packet(&audiopacket_t);}}int Es2Mux_2(){for (;;){read_frame(oc);}return 1;}
//main.cpp#include "ffmpeg.h"int main(int argc ,char ** argv){av_register_all();avformat_network_init();InitInput(INPUTURL,&icodec,&ifmt);InitOutput();printf("--------程序运行开始----------\n");//////////////////////////////////////////////////////////////////////////Es2Mux_2();//////////////////////////////////////////////////////////////////////////UintOutput();UintInput();printf("--------程序运行结束----------\n");printf("-------请按任意键退出---------\n");return getchar();}


交流请加QQ群:62054820
QQ:379969650

1 0
原创粉丝点击