Reputation: 1607
I'm trying to stream H.264 over UDP with no luck so far. Here is a minimal code that you can reproduce the problem.
To compile,
g++ -o test -lavcodec -lavformat -lavutil test.cpp
Extra information, I start ffplay
as follows. Currently it's of no use.
ffplay -i udp://127.0.0.1:8554/live.sdp
Output of my code (see avio_open()
call),
[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
And the code,
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;
}
For those who has even more time to spare on my problem, when I change m_output
to rtsp://127.0.0.1:8554/live.sdp
, and ffplay
command to ffplay -rtsp_flags listen -i rtsp://127.0.0.1:8554/live.sdp
I get the error,
[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
Am I naive to expect that streaming protocol will be changed like this?
Upvotes: 2
Views: 9993
Reputation: 1607
Apparently I was creating and initializing an AVCodecContext
and then not using it.. An AVStream
has its own AVCodecContext
(which is quite sensible, as different streams usually need different encoders) and it was the one that I needed to initialize with dimensions and pixel format. For that, I also needed to swap the calls to avformat_new_stream()
and avcodec_open2()
and call the former first. Here is the diff of the fix.
Note that m_codecContext
is removed altogether.
--- 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;
Upvotes: 3