ffmpeg处理rtmp/文件/rtsp的推流和拉流
ffmpeg处理rtmp/文件/rtsp的推流和拉流
- //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 param
- extern 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 param
- extern 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 1
- extern int nRet; //状态标志
- extern AVFormatContext* icodec;
- extern AVInputFormat* ifmt;
- extern char szError[256]; //错误字符串
- extern AVFormatContext* oc ; //输出流context
- extern 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 param
- int 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 param
- int 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);
- //添加音频信息到输出context
- for (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();
- }
- }
- //添加音频信息到输出context
- if(audio_stream_idx != -1)
- {
- ofmt->audio_codec = audio_codecID;
- audio_st = Add_output_stream_2(oc, AVMEDIA_TYPE_AUDIO,audio_codecID,&audio_codec);
- }
- //添加视频信息到输出context
- ofmt->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();
- }
ffmpeg处理rtmp/文件/rtsp的推流和拉流的更多相关文章
- iOS开发之利用IJKPlayer+nginx+rtmp搭建直播的推流和拉流
最近项目中想实现直播的功能,所以研究了一段时间的直播功能,当然也是在别人的基础上不断的学习实现的,所以记录一下,希望对大家有所帮助. 直播拉流功能: 这里使用了开源的IJKPlayer第三框架,ijk ...
- Mac上搭建直播服务器Nginx+rtmp,实现手机推流、拉流
转载自http://www.cnblogs.com/jys509/p/5649066.html 简介 nginx是非常优秀的开源服务器,用它来做hls或者rtmp流媒体服务器是非常不错的选择,本人在网 ...
- 流媒体压力测试rtmp&hls(含推流和拉流)
http://blog.csdn.net/sinat_34194127/article/details/50816045 [root@localhost ~]# yum install git unz ...
- java封装FFmpeg命令,支持原生ffmpeg全部命令,实现FFmpeg多进程处理与多线程输出控制(开启、关闭、查询),rtsp/rtmp推流、拉流
前言: 之前已经对FFmpeg命令进行了封装http://blog.csdn.net/eguid_1/article/details/51787646,但是当时没有考虑到扩展性,所以总体设计不是太好, ...
- nginx+ffmpeg搭建rtmp转播rtsp流的flash服务器
本文概要: nginx是非常优秀的开源服务器,用它来做hls或者rtmp流媒体服务器是非常不错的选择.本文介绍了一种简易方法快速搭建rtmp流媒体服务器,也叫rtsp转播,数据源不是读取文件,而是采用 ...
- 用FFmpeg+nginx+rtmp搭建环境实现推流
Windows: 1.下载文件: 链接:https://pan.baidu.com/s/1c2LmIHHw-dwLOlRN6iTIMg 提取码:g7sj 2.解压文件: 解压到nginx-1.7.11 ...
- 三、Windows下用FFmpeg+nginx+rtmp搭建直播环境 实现推流、拉流
一.环境 1.开发环境:windows 2.开发工具:FFmpeg.nginx.nginx-rmtp-module (链接:https://pan.baidu.com/s/119d2GeMzddas_ ...
- 推流和拉流的概念以及RTMP和HLS协议
推流为将直播内容推送至服务器的过程:拉流为服务器已有直播内容,用指定地址进行拉取的过程. rtmp rtmp是Real Time Messaging Protocol(实时消息传输协议)的首字母缩写. ...
- 开源流媒体服务器SRS学习笔记(1) - 安装、推流、拉流
SRS(Simple RTMP Server) 是国人写的一款非常优秀的开源流媒体服务器软件,可用于直播/录播/视频客服等多种场景,其定位是运营级的互联网直播服务器集群. 一.安装 官网提供了3种安 ...
随机推荐
- stm32DMA通道 ADC通道
DMA: 1.使用DAC的时候.将转化后得到的模拟信号通过IO口输出的时候.为什么还将IO口配置能输入模式 PS:stm32手冊上定义PA4和PA5分别和DAC1通道和DAC2通道相连 : DMA1 ...
- EasyDSS直播服务器如何帮助用户解决OBS不能同时同步输出多路直播流到直播平台、CDN平台的限制
最近有用户突然寻求帮助,大概的意思就是说: 他需要同步将桌面的直播同时RTMP发布到:斗鱼.熊猫TV等等多个平台,但是OBS又只能同时采集并发布推流直播到单一个平台,而且有时候在4G或者网络比较差的情 ...
- 使用memcache进行账号验证服务
适用环境是需要频繁进行账号和请求合法性验证的地方 大致思路: 1.登陆时,服务器端接收一个账号和密码,还可以再加上用户的ip等信息通过md5等加密算法计算出一个定长的字符串作为用来验证的token 2 ...
- Django之CURD插件
什么是CURD? CURD顾名思义就是create,update,rearch,delete(所谓的增删改查). 当我们接到一个项目的时候,夸夸夸的就写完表结构,然后就一直写增删改查,增删改查,写了一 ...
- Centos设置开机启动Apache和Mysql
先用chkconfig --list查询apache和mysql服务是否存在,不存在则需要手动添加 [root@centos64 vsftpd]# chkconfig --list 测试存在,只需要开 ...
- 淘宝开放平台php-sdk测试 获取淘宝商品信息(转)
今天想使用淘宝开放平台的API获取商品详情,可是以前一直没使用过,看起来有点高深莫测,后然看开发入门,一步一步,还真有点感觉了,然后看示例,还真行了,记下来以后参考.其中遇到问题,后然解决了.因为我已 ...
- android ui篇 自己写界面
对于一些较为简单的界面则自己进行写. 在这里就需要了解xml文件中一些基本的属性以及android手机的知识. 一.目前手机屏幕像素密度基本有5种情况.(以下像素密度简称密度) 密度 ldpi mdp ...
- spring 3.2 后 annotation-driven 注册新的类
DefaultAnnotationHandlerMapping 和 AnnotationMethodHandlerAdapter 的使用已经过时! DefaultAnnotationHandlerMa ...
- JavaScript测试代码
<!-- 在谷歌浏览器上的console运行 --> //变量 var netPrice = 8.99; alert(netPrice); //字符串方法 var string1 = &q ...
- LeetCode:二叉树相关应用
LeetCode:二叉树相关应用 基础知识 617.归并两个二叉树 题目 Given two binary trees and imagine that when you put one of the ...