最簡單的基于 FFmpeg 的收流器(以接收 RTMP 為例)

最簡單的基于 FFmpeg 的收流器(以接收 RTMP 為例)

最簡單的基于 FFmpeg 的收流器(以接收 RTMP 為例)

參考雷霄驊博士的文章,鏈接:最簡單的基于FFMPEG的推流器附件:收流器

正文

出于對 最簡單的基于 FFmpeg 的推流器(以推送 RTMP 為例)的補充,本文記錄一個最簡單的基于 FFmpeg 的收流器。

收流器和推流器的作用正好相反:推流器用于將本地文件以流媒體的形式發送出去,而收流器用于將流媒體內容保存為本地文件。

本文記錄的推流器可以將 RTMP 流媒體保存成為一個本地的 FLV 文件。由于 FFmpeg 本身支持很多的流媒體協議和封裝格式,所以也支持其它的封裝格式和流媒體協議。

源程序:

// Simplest FFmpeg Receiver.cpp : 定義控制臺應用程序的入口點。
///**
* 最簡單的基于 FFmpeg 的收流器(接收 RTMP)
* Simplest FFmpeg Receiver (Receive RTMP)
*
* 源程序:
* 雷霄驊 Lei Xiaohua
* leixiaohua1020@126.com
* 中國傳媒大學/數字電視技術
* Communication University of China / Digital TV Technology
* http://blog.csdn.net/leixiaohua1020
*
* 修改:
* 劉文晨 Liu Wenchen
* 812288728@qq.com
* 電子科技大學/電子信息
* University of Electronic Science and Technology of China / Electronic and Information Science
* https://blog.csdn.net/ProgramNovice
*
* 本例子將流媒體數據(以 RTMP 為例)保存成本地文件。
* 是使用 FFmpeg 進行流媒體接收最簡單的教程。
*
* This example saves streaming media data (Use RTMP as example)
* as a local file.
* It's the simplest FFmpeg stream receiver.
*/#include "stdafx.h"#include <stdio.h>
#include <stdlib.h>// 解決報錯:'fopen': This function or variable may be unsafe.Consider using fopen_s instead.
#pragma warning(disable:4996)// 解決報錯:無法解析的外部符號 __imp__fprintf,該符號在函數 _ShowError 中被引用
#pragma comment(lib, "legacy_stdio_definitions.lib")
extern "C"
{// 解決報錯:無法解析的外部符號 __imp____iob_func,該符號在函數 _ShowError 中被引用FILE __iob_func[3] = { *stdin, *stdout, *stderr };
}#define __STDC_CONSTANT_MACROS#ifdef _WIN32
// Windows
extern "C"
{
#include "libavformat/avformat.h"
#include "libavutil/mathematics.h"
#include "libavutil/time.h"
};
#else
// Linux...
#ifdef __cplusplus
extern "C"
{
#endif
#include <libavformat/avformat.h>
#include <libavutil/mathematics.h>
#include <libavutil/time.h>
#ifdef __cplusplus
};
#endif
#endif// 1: Use H.264 Bitstream Filter 
#define USE_H264BSF 0int main(int argc, char* argv[])
{AVOutputFormat *ofmt = NULL;// Input AVFormatContext and Output AVFormatContextAVFormatContext *ifmt_ctx = NULL, *ofmt_ctx = NULL;AVPacket pkt;const char *in_filename, *out_filename;int ret, i;int videoindex = -1;int frame_index = 0;// RTMPin_filename = "rtmp://liteavapp.qcloud.com/live/liteavdemoplayerstreamid";// UDP// in_filename  = "rtp://233.233.233.233:6666";out_filename = "receive.flv";// out_filename = "receive.ts";// out_filename = "receive.mkv";av_register_all();// Init networkavformat_network_init();// Inputif ((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;}// Print some input informationav_dump_format(ifmt_ctx, 0, in_filename, 0);// Outputavformat_alloc_output_context2(&ofmt_ctx, NULL, NULL, out_filename); // RTMPif (ofmt_ctx == NULL){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++){// Create output AVStream according to input AVStreamAVStream *in_stream = ifmt_ctx->streams[i];AVStream *out_stream = avformat_new_stream(ofmt_ctx, in_stream->codec->codec);if (out_stream == NULL){printf("Failed allocating output stream.\n");ret = AVERROR_UNKNOWN;goto end;}// Copy the settings of AVCodecContextret = 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;}}// Print some output informationav_dump_format(ofmt_ctx, 0, out_filename, 1);// Open output URLif (!(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'.\n", out_filename);goto end;}}// Write file headerret = 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");
#endifwhile (1){AVStream *in_stream, *out_stream;// Get an AVPacketret = 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];// copy packet// Convert PTS/DTSpkt.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_write_frame(ofmt_ctx, &pkt);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// Write file trailerav_write_trailer(ofmt_ctx);
end:avformat_close_input(&ifmt_ctx);// Close outputif (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;}system("pause");return 0;
}

結果

運行程序,輸出如下:

在這里插入圖片描述

程序運行之后,即可獲取流媒體數據并且在本地保存成一個視頻文件 “receive.flv”。

在這里插入圖片描述

工程文件下載

GitHub:UestcXiye / Simplest-FFmpeg-Receiver

CSDN:Simplest FFmpeg Receiver.zip

參考鏈接

  1. 最簡單的基于 FFmpeg 的推流器(以推送 RTMP 為例)

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/717929.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/717929.shtml
英文地址,請注明出處:http://en.pswp.cn/news/717929.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

藍凌OA frpt_listreport_definefield.aspx接口存在SQL注入漏洞

免責聲明&#xff1a;文章來源互聯網收集整理&#xff0c;請勿利用文章內的相關技術從事非法測試&#xff0c;由于傳播、利用此文所提供的信息或者工具而造成的任何直接或者間接的后果及損失&#xff0c;均由使用者本人負責&#xff0c;所產生的一切不良后果與文章作者無關。該…

DevStack 部署 OpenStack

Devstack 簡介 DevStack 是一系列可擴展的腳本&#xff0c;用于基于 git master 的最新版本快速調出完整的 OpenStack 環境。devstack 以交互方式用作開發環境和 OpenStack 項目大部分功能測試的基礎。 devstack 透過執行 stack.sh 腳本&#xff0c;搭建 openstack 環境&…

lv20 QT主窗口4

熟悉創建主窗口項目 1 QAction 2 主窗口 菜單欄&#xff1a;fileMenu menuBar()->addMenu(tr("&File")); 工具欄&#xff1a;fileToolBar addToolBar(tr("File")); 浮動窗&#xff1a;QDockWidget *dockWidget new QDockWidget(tr("Dock W…

Threejs之精靈模型Sprite

參考資料 精靈模型Sprite…Sprite模擬下雨、下雪 知識點 注&#xff1a;基于Three.jsv0.155.0 精靈模型Sprite精靈模型標注場景(貼圖)Sprite模擬下雨、下雪 精靈模型Sprite Three.js的精靈模型Sprite和Threejs的網格模型Mesh一樣都是模型對象&#xff0c;父類都是Object3…

【設計者模式】單例模式

文章目錄 1、模式定義2、代碼實現&#xff08;1&#xff09;雙重判空加鎖方式兩次判空的作用&#xff1f;volatile 關鍵字的作用&#xff1f;構造函數私有&#xff1f; &#xff08;2&#xff09;靜態內部類【推薦】&#xff08;3&#xff09;Kotlin中的單例模式lateinit 和 by…

Matlab 最小二乘插值(曲線擬合)

文章目錄 一、簡介二、實現代碼三、實現效果參考資料一、簡介 在多項式插值時,當數據點個數較多時,插值會導致多項式曲線階數過高,帶來不穩定因素。因此我們可以通過固定冪基函數的最高次數 m(m < n),來對我們要擬合的曲線進行降階。之前的函數形式就可以變為: 二、實現…

spring Boot 報錯RedisConnectionFailureException

錯誤描述&#xff1a; 錯誤重點&#xff1a;&#xff08;圖片中藍色區域&#xff09; Unable to connect to Redis; 無法連接到Redis Unable to connect to 127.0.0.1 無法連接到本地服務器 所以&#xff0c;錯誤是本地服務器沒有連接上Redis所引起的 錯誤解析…

vue3中的父傳子,子傳父

在Vue 3中&#xff0c;父組件向子組件傳遞數據和子組件向父組件通信的方式與Vue 2非常相似&#xff0c;但Vue 3提供了Composition API和更多的響應式API&#xff0c;為組件間的通信提供了更多的可能性。下面是父傳子和子傳父的基本方法&#xff1a; ### 父組件傳遞數據給子組件…

【InternLM 實戰營筆記】使用SDK接口上傳模型到OpenXLab

概述 浦源內容平臺-模型中心的Python SDK旨在為開發人員提供編程方式來管理和操作模型中心平臺的功能&#xff0c;以便他們可以輕松地與模型中心進行交互和模型管理。通過Python SDK提供的推理接口&#xff0c;開發人員能夠高效地調用不同的模型&#xff0c;實現模型應用的開發…

遞歸實現排列型枚舉(c++題解)

題目描述 把 1~n 這 n(n<10) 個整數排成一行后隨機打亂順序&#xff0c;輸出所有可能的次序。 輸入格式 一個整數n。 輸出格式 按照從小到大的順序輸出所有方案&#xff0c;每行1個。 首先&#xff0c;同一行相鄰兩個數用一個空格隔開。其次&#xff0c;對于兩個不同的…

Linux——進程控制(二)進程等待

目錄 前言 一、進程等待 二、如何進行進程等待 1.wait 2.waitpid 2.1第二個參數 2.2第三個參數 3. 等待多個進程 三、為什么不用全局變量獲取子進程的退出信息 前言 前面我們花了大量的時間去學習進程的退出&#xff0c;退出并不難&#xff0c;但更深入的學習能為本…

048 異常

什么是異常 異常體系結構 異常的繼承關系 Error Exception 異常處理機制 try&#xff1a;用{}將可能產生異常的代碼包裹catch&#xff1a;與try搭配使用&#xff0c;捕獲try包裹代碼中拋出的異常并進行后續動作finally&#xff1a;跟在try后&#xff0c;在try和catch之后執行…

web3時事粥報

比特幣正成為更具有吸引力的通脹對沖工具 在通脹的宏觀經濟浪潮中&#xff0c;比特幣正逐漸嶄露頭角&#xff0c;成為那些渴望多元化投資組合的投資者眼中的璀璨明星。Kooner 預測&#xff0c;2024年&#xff0c;各種宏觀經濟挑戰可能進一步提升比特幣、黃金和白銀等資產的避險…

3月3日做題總結(C/C++真題)

第一題 參加位運算的數據其類型不能是&#xff08;&#xff09;。 A---int B---char C---float D---long int 正確答案&#xff1a;C 解析&#xff1a;無論是float&#xff0c;還是double&#xff0c;在內存中的存儲分為三部分&#xff1a;符號位、指數位、尾數位&#…

Google Dremel和parquet的復雜嵌套數據結構表征方法解析

轉載請注明出處。作者&#xff1a;archimekai 核心參考文獻&#xff1a; Dremel: Interactive Analysis of Web-Scale Datasets 文章目錄 引言復雜嵌套數據結構的無損表征問題Dremel論文中提出的表征方法parquet備注 引言 Dremel是Google的交互式分析系統。Google大量采用prot…

全量知識系統問題及SmartChat給出的答復 之17 知識系統中的兩個特權類(超類和欠類) :腳本和場景

Q.45 知識系統中的兩個特權類 &#xff1a;腳本和場景 知識系統中的兩個特權類&#xff08;也是集合論中兩個特權集合&#xff09;&#xff1a;腳本script和場景scene 。 一個$Demonstrate類型的腳本script&#xff1a; 表示“值val”&#xff08; 形式上是應用程序的實用工…

如何學習openfoam

學習OpenFOAM的詳細步驟、流程、學習網站、練習案例以及B站學習資源推薦如下&#xff1a; 一、詳細步驟和流程 安裝OpenFOAM&#xff1a;首先&#xff0c;你需要在你的計算機上安裝OpenFOAM。你可以從OpenFOAM的官方網站下載適合你的操作系統的安裝包&#xff0c;然后按照官方提…

搭建服務器及跨域處理

使用內置的模塊搭建服務器 自己電腦: 域名:localhost ip:127.0.0.1 http模塊搭建服務器 const http = require(http)// 創建一個http對應的服務器,每次改完服務器的代碼后都需要重新啟動下服務器 /*方式一: const server = http.createServer((request,response)=>{…

對簡單工廠模式、工廠方法模式的思考

目錄 1 背景1.1 題目描述1.2 輸入描述1.3 輸出描述1.4 輸入示例1.5 輸出示例 2 簡單工廠模式3 工廠方法模式4 思考4.1 改進工廠方法模式 1 背景 題目源自&#xff1a;【設計模式專題之工廠方法模式】2.積木工廠 1.1 題目描述 小明家有兩個工廠&#xff0c;一個用于生產圓形積木…

鐵路關基保護新規發布!鐵路軟件供應鏈安全洞察與治理思路

近日&#xff0c;國家鐵路局發布《鐵路關鍵信息基礎設施安全保護管理辦法》&#xff0c;《辦法》第十四條提到&#xff1a;“運營者應當加強鐵路關鍵信息基礎設施供應鏈安全保護&#xff0c;優先采購安全可信的網絡產品和服務。運營者采購網絡產品和服務&#xff0c;應當預判該…