C++ 使用FFmpeg通过UDP传输H.264,以及;“未设置尺寸”;错误

C++ 使用FFmpeg通过UDP传输H.264,以及;“未设置尺寸”;错误,c++,ffmpeg,streaming,video-streaming,rtsp,C++,Ffmpeg,Streaming,Video Streaming,Rtsp,我正在尝试通过UDP传输H.264,但到目前为止运气不佳。下面是一个可以重现问题的最小代码 编辑, g++ -o test -lavcodec -lavformat -lavutil test.cpp 额外信息,我开始ffplay如下。目前没有用 ffplay -i udp://127.0.0.1:8554/live.sdp 我的代码输出(请参见avio_open()call) 还有代码 extern "C" { #include <libavcodec/avcodec.h&g

我正在尝试通过UDP传输H.264,但到目前为止运气不佳。下面是一个可以重现问题的最小代码

编辑,

g++ -o test -lavcodec -lavformat -lavutil test.cpp
额外信息,我开始
ffplay
如下。目前没有用

ffplay -i udp://127.0.0.1:8554/live.sdp
我的代码输出(请参见
avio_open()
call)

还有代码

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;
}

我是否天真地期望流媒体协议会像这样改变?

显然,我正在创建并初始化一个
AVCodecContext
,然后没有使用它。。
AVStream
有自己的
AVCodecContext
(这很合理,因为不同的流通常需要不同的编码器),我需要用维度和像素格式初始化它。为此,我还需要交换对
avformat\u new\u stream()
avcodec\u 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;
——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 @@
使用名称空间std;
int main(){
-AVCodecContext*m_codecContext;
AVCodec*m_编解码器;
AVFormatContext*m_formatContext;
AVStream*m_流;
@@ -41,32 +40,25 @@
返回-1;
}
-m_codecContext=avcodec_alloc_context3(m_codec);
-if(!m_codecContext){
-cerr宽度=m_外径;
+m_-stream->codec->height=m_-outHeight;
-m_stream=avformat_new_stream(m_formatContext,m_编解码器);
-如果(!m_流){
-cerr编解码器,m_编解码器,空)<0){
+瑟尔
[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
--- 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;