[英]Streaming H.264 over UDP using FFmpeg, and "dimensions not set" error
到目前為止,我正在嘗試通過 UDP 流式傳輸 H.264,但沒有運氣。 這是您可以重現問題的最小代碼。
編譯,
g++ -o test -lavcodec -lavformat -lavutil test.cpp
額外的信息,我開始ffplay
如下。 目前它沒有用。
ffplay -i udp://127.0.0.1:8554/live.sdp
我的代碼的輸出(參見avio_open()
調用),
[libx264 @ 0x6a26c0] using mv_range_thread = 24
[libx264 @ 0x6a26c0] using cpu capabilities: MMX2 SSE2Fast SSSE3 SSE4.1 Cache64
[libx264 @ 0x6a26c0] profile High, level 3.1
Output #0, h264, to 'udp://127.0.0.1:8554/live.sdp':
Stream #0:0, 0, 0/0: Video: h264 (libx264), -1 reference frame, none, q=-1--1
[h264 @ 0x6a2020] dimensions not set
Cannot write header to stream: Success
還有代碼,
extern "C" {
#include <libavcodec/avcodec.h>
#include <libavformat/avformat.h>
#include <libavutil/avutil.h>
}
#include <iostream>
using namespace std;
int main() {
AVCodecContext* m_codecContext;
AVCodec* m_codec;
AVFormatContext* m_formatContext;
AVStream* m_stream;
unsigned m_outWidth = 768;
unsigned m_outHeight = 608;
av_register_all();
avcodec_register_all();
avformat_network_init();
int errorStatus = 0;
char errorLog[128] = { 0 };
av_log_set_level(AV_LOG_TRACE);
string m_output("udp://127.0.0.1:8554/live.sdp");
if (avformat_alloc_output_context2(&m_formatContext, NULL, "h264", m_output.c_str()) < 0) {
cerr << "Cannot allocate output context: "
<< av_make_error_string(errorLog, 128, errorStatus) << endl;
return -1;
}
AVOutputFormat *m_outputFormat = m_formatContext->oformat;
m_codec = avcodec_find_encoder(AV_CODEC_ID_H264);
if (!m_codec) {
cerr << "Cannot find an encoder: "
<< av_make_error_string(errorLog, 128, errorStatus) << endl;
return -1;
}
m_codecContext = avcodec_alloc_context3(m_codec);
if (!m_codecContext) {
cerr << "Cannot allocate a codec context: "
<< av_make_error_string(errorLog, 128, errorStatus) << endl;
return -1;
}
m_codecContext->pix_fmt = AV_PIX_FMT_YUV420P;
m_codecContext->width = m_outWidth;
m_codecContext->height = m_outHeight;
if (avcodec_open2(m_codecContext, m_codec, NULL) < 0) {
cerr << "Cannot open codec: "
<< av_make_error_string(errorLog, 128, errorStatus) << endl;
return -1;
}
m_stream = avformat_new_stream(m_formatContext, m_codec);
if (!m_stream) {
cerr << "Cannot create a new stream: "
<< av_make_error_string(errorLog, 128, errorStatus) << endl;
return -1;
}
av_dump_format(m_formatContext, 0, m_output.c_str(), 1);
if ((errorStatus = avio_open(&m_formatContext->pb, m_output.c_str(), AVIO_FLAG_WRITE)) < 0) {
cerr << "Cannot open output: "
<< av_make_error_string(errorLog, 128, errorStatus) << endl;
return -1;
}
if (avformat_write_header(m_formatContext, NULL) < 0) {
cerr << "Cannot write header to stream: "
<< av_make_error_string(errorLog, 128, errorStatus) << endl;
return -1;
}
cout << "All done." << endl;
return 0;
}
對於那些誰擁有更多的空閑時間我的問題,當我改變m_output
到rtsp://127.0.0.1:8554/live.sdp
,並ffplay
命令ffplay -rtsp_flags listen -i rtsp://127.0.0.1:8554/live.sdp
我收到錯誤消息,
[libx264 @ 0x1e056c0] using mv_range_thread = 24
[libx264 @ 0x1e056c0] using cpu capabilities: MMX2 SSE2Fast SSSE3 SSE4.1 Cache64
[libx264 @ 0x1e056c0] profile High, level 3.1
Output #0, h264, to 'rtsp://127.0.0.1:8554/live.sdp':
Stream #0:0, 0, 0/0: Video: h264 (libx264), -1 reference frame, none, q=-1--1
Cannot open output: Protocol not found
我是否天真地期望流媒體協議會像這樣改變?
顯然我正在創建和初始化一個AVCodecContext
然后不使用它..一個AVStream
有它自己的AVCodecContext
(這是非常明智的,因為不同的流通常需要不同的編碼器)並且它是我需要用尺寸和像素格式初始化的. 為此,我還需要交換對avformat_new_stream()
和avcodec_open2()
調用,並首先調用前者。 這是修復的差異。
請注意, m_codecContext
已完全刪除。
--- rtsp-so.cpp.orig 2015-09-03 17:34:08.190375415 +0200
+++ rtsp-so.cpp 2015-09-03 17:43:42.166542704 +0200
@@ -8,7 +8,6 @@
using namespace std;
int main() {
- AVCodecContext* m_codecContext;
AVCodec* m_codec;
AVFormatContext* m_formatContext;
AVStream* m_stream;
@@ -41,32 +40,25 @@
return -1;
}
- m_codecContext = avcodec_alloc_context3(m_codec);
- if (!m_codecContext) {
- cerr << "Cannot allocate a codec context: "
+ m_stream = avformat_new_stream(m_formatContext, m_codec);
+ if (!m_stream) {
+ cerr << "Cannot create a new stream: "
<< av_make_error_string(errorLog, 128, errorStatus) << endl;
return -1;
}
- m_codecContext->pix_fmt = AV_PIX_FMT_YUV420P;
- m_codecContext->width = m_outWidth;
- m_codecContext->height = m_outHeight;
+ av_dump_format(m_formatContext, 0, m_output.c_str(), 1);
- if (avcodec_open2(m_codecContext, m_codec, NULL) < 0) {
- cerr << "Cannot open codec: "
- << av_make_error_string(errorLog, 128, errorStatus) << endl;
- return -1;
- }
+ m_stream->codec->pix_fmt = AV_PIX_FMT_YUV420P;
+ m_stream->codec->width = m_outWidth;
+ m_stream->codec->height = m_outHeight;
- m_stream = avformat_new_stream(m_formatContext, m_codec);
- if (!m_stream) {
- cerr << "Cannot create a new stream: "
+ if (avcodec_open2(m_stream->codec, m_codec, NULL) < 0) {
+ cerr << "Cannot open codec: "
<< av_make_error_string(errorLog, 128, errorStatus) << endl;
return -1;
}
- av_dump_format(m_formatContext, 0, m_output.c_str(), 1);
-
if ((errorStatus = avio_open(&m_formatContext->pb, m_output.c_str(), AVIO_FLAG_WRITE)) < 0) {
cerr << "Cannot open output: "
<< av_make_error_string(errorLog, 128, errorStatus) << endl;
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.