生活随笔
收集整理的這篇文章主要介紹了
                                
最简单的基于FFMPEG的推流器附件:收流器
小編覺得挺不錯的,現在分享給大家,幫大家做個參考.                        
 
                                
                            
                            
                            =====================================================
最簡單的基于FFmpeg的推流器系列文章列表:
《最簡單的基于FFmpeg的推流器(以推送RTMP為例)》
《最簡單的基于FFMPEG的推流器附件:收流器》
=====================================================
出于對《最簡單的基于FFmpeg的推流器》的補充,本文記錄一個最簡單的基于FFmpeg的收流器。收流器和推流器的作用正好相反:推流器用于將本地文件以流媒體的形式發送出去,而收流器用于將流媒體內容保存為本地文件。
本文記錄的推流器可以將RTMP流媒體保存成為一個本地的FLV文件。由于FFmpeg本身支持很多的流媒體協議和封裝格式,所以也支持其它的封裝格式和流媒體協議。
源代碼
 #include <stdio.h> #define __STDC_CONSTANT_MACROS #ifdef _WIN32extern "C"{#include "libavformat/avformat.h"#include "libavutil/mathematics.h"#include "libavutil/time.h"};#else#ifdef __cplusplusextern "C"{#endif#include <libavformat/avformat.h>#include <libavutil/mathematics.h>#include <libavutil/time.h>#ifdef __cplusplus};#endif#endif #define USE_H264BSF 0 int main(int argc, char* argv[]){AVOutputFormat *ofmt = NULL; AVFormatContext *ifmt_ctx = NULL, *ofmt_ctx = NULL;AVPacket pkt; const char *in_filename, *out_filename; int ret, i; int videoindex=-1; int frame_index=0;in_filename = "rtmp://live.hkstv.hk.lxdns.com/live/hks";   out_filename = "receive.flv"; av_register_all(); avformat_network_init();  if ((ret = avformat_open_input(&ifmt_ctx, in_filename, 0, 0)) < 0) { printf( "Could not open input file."); goto end;} if ((ret = avformat_find_stream_info(ifmt_ctx, 0)) < 0) { printf( "Failed to retrieve input stream information"); goto end;}  for(i=0; i<ifmt_ctx->nb_streams; i++)  if(ifmt_ctx->streams[i]->codec->codec_type==AVMEDIA_TYPE_VIDEO){videoindex=i; break;} av_dump_format(ifmt_ctx, 0, in_filename, 0);  avformat_alloc_output_context2(&ofmt_ctx, NULL, NULL, out_filename);   if (!ofmt_ctx) { printf( "Could not create output context\n");ret = AVERROR_UNKNOWN; goto end;}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) { printf( "Failed allocating output stream\n");ret = AVERROR_UNKNOWN; goto end;} ret = avcodec_copy_context(out_stream->codec, in_stream->codec); if (ret < 0) { printf( "Failed to copy context from input to output stream codec context\n"); goto end;}out_stream->codec->codec_tag = 0; if (ofmt_ctx->oformat->flags & AVFMT_GLOBALHEADER)out_stream->codec->flags |= CODEC_FLAG_GLOBAL_HEADER;} av_dump_format(ofmt_ctx, 0, out_filename, 1);  if (!(ofmt->flags & AVFMT_NOFILE)) {ret = avio_open(&ofmt_ctx->pb, out_filename, AVIO_FLAG_WRITE); if (ret < 0) { printf( "Could not open output URL '%s'", out_filename); goto end;}} ret = avformat_write_header(ofmt_ctx, NULL); if (ret < 0) { printf( "Error occurred when opening output URL\n"); goto end;} #if USE_H264BSFAVBitStreamFilterContext* h264bsfc = av_bitstream_filter_init("h264_mp4toannexb"); #endif  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(pkt.stream_index==videoindex){ printf("Receive %8d video frames from input URL\n",frame_index);frame_index++; #if USE_H264BSFav_bitstream_filter_filter(h264bsfc, in_stream->codec, NULL, &pkt.data, &pkt.size, pkt.data, pkt.size, 0);#endif} ret = av_interleaved_write_frame(ofmt_ctx, &pkt);  if (ret < 0) { printf( "Error muxing packet\n"); break;} av_free_packet(&pkt); } #if USE_H264BSFav_bitstream_filter_close(h264bsfc); #endif  av_write_trailer(ofmt_ctx);end:avformat_close_input(&ifmt_ctx);  if (ofmt_ctx && !(ofmt->flags & AVFMT_NOFILE))avio_close(ofmt_ctx->pb);avformat_free_context(ofmt_ctx); if (ret < 0 && ret != AVERROR_EOF) { printf( "Error occurred.\n"); return -1;} return 0;}
運行結果
程序運行之后,即可獲取流媒體數據并且在本地保存成一個視頻文件。
下載
simplest ffmpeg streamer
項目主頁
SourceForge:https://sourceforge.net/projects/simplestffmpegstreamer/
Github:https://github.com/leixiaohua1020/simplest_ffmpeg_streamer
開源中國:http://git.oschina.net/leixiaohua1020/simplest_ffmpeg_streamer
CSDN下載地址:http://download.csdn.net/detail/leixiaohua1020/8924345
解決方案包含2個項目:
simplest_ffmpeg_streamer: 將本地視頻文件推送至流媒體服務器。
simplest_ffmpeg_receiver: 將流媒體數據保存成本地文件。
                            總結
                            
                                以上是生活随笔為你收集整理的最简单的基于FFMPEG的推流器附件:收流器的全部內容,希望文章能夠幫你解決所遇到的問題。
                            
                            
                                如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。