为什么在单个AVFormatContext中处理多个媒体源时源顺序很重要?

huangapple go评论63阅读模式
英文:

Why the source order matters on working with multiple media sources in a single AVFormatContext?

问题

avformat_open_input()在源顺序更改时会删除AVFormatContext*并返回-6

我尝试以单个上下文(AVFormatContext)动态打开多个不同(混合)格式和编解码器的媒体源。

我的媒体源是首先作为第一源的BlackMagic DeckLink Duo SDI输入,然后是mp4文件rtsp流

当我首先打开源2(RTSP或MP4文件),然后打开BlackMagic DeckLink Duo,一切都如预期那样进行。

但当我更改顺序,首先打开DeckLink,然后尝试打开RTSP流或MP4文件时,根据调试器的检查,av_open_input()函数会删除AVFormatContext*并返回-6作为结果。

请查看以下的简单错误重现代码片段;

AVFormatContext* context{avformat_alloc_context()};
const char* url_source1{"DeckLink Duo (1)"};
const AVInputFormat* format_source1{av_find_input_format("decklink")};

const char* url_source2{"http://commondatastorage.googleapis.com/gtv-videos-bucket/sample/BigBuckBunny.mp4"};

// 打开第一个媒体输入
int result = avformat_open_input(&context, url_source1, format_source1, NULL);

if(result < 0) {
  exit(1);
}

// 打开第二个媒体输入
// 在当前顺序中,此函数会删除上下文并返回-6
result = avformat_open_input(&context, url_source2, NULL, NULL);
if(result < 0) {
  exit(1);
}

// 由于上一步中已删除上下文,因此会在此处发生分段错误!
result = avformat_find_stream_info(context, NULL);
if(result < 0) {
  exit(1);
}

std::cout << "流的总数: " << context->nb_streams << std::endl;

但是,当我更改顺序,首先为mp4文件调用avformat_open_input(),然后为DeckLink设备调用,如下所示,一切都如预期那样进行,没有错误。

AVFormatContext* context{avformat_alloc_context()};
const char* url_source1{"DeckLink Duo (1)"};
const AVInputFormat* format_source1{av_find_input_format("decklink")};

const char* url_source2{"http://commondatastorage.googleapis.com/gtv-videos-bucket/sample/BigBuckBunny.mp4"};

// 打开第二个媒体输入
int result = avformat_open_input(&context, url_source2, NULL, NULL);
if(result < 0) {
  exit(1);
}

// 打开第一个媒体输入
result = avformat_open_input(&context, url_source1, format_source1, NULL);

if(result < 0) {
  exit(1);
}

result = avformat_find_stream_info(context, NULL);
if(result < 0) {
  exit(1);
}

std::cout << "流的总数: " << context->nb_streams << std::endl;
英文:

avformat_open_input() deletes the AVFormatContext* and returns -6 when the source order changes.

I am trying to open multiple media sources dynamically with different(mixed) formats and codecs in a single context (AVFormatContext).

My media sources are a BlackMagic DeckLink Duo SDI input as first source and an mp4 file or rtsp stream as second.

When I order to open (avformat_open_input()) the source 2 (RTSP or MP4 file) at first and then open the BlackMagic DeckLink Duo, proceed as expected.

But when I change the order, and first open the DeckLink and then try to open RTSP stream or MP4 file, as I inspected in the step debugger; AVFormatContext* deleting in the av_open_input() function and it returns -6 as result.

Please find the simple error reproduction code snappet below;

AVFormatContext* context{avformat_alloc_context()};
const char* url_source1{&quot;DeckLink Duo (1)&quot;};
const AVInputFormat* format_source1{av_find_input_format(&quot;decklink&quot;)};

const char* url_source2{&quot;http://commondatastorage.googleapis.com/gtv-videos-bucket/sample/BigBuckBunny.mp4&quot;};

// Open the first media input
int result = avformat_open_input(&amp;context, url_source1, format_source1, NULL);

if(result &lt; 0) {
  exit(1);
}

// Open the second media input
// This function in current order deletes the context and returns -6
result = avformat_open_input(&amp;context, url_source2, NULL, NULL);
if(result &lt; 0) {
  exit(1);
}

// Since the context has been deleted in previous step, segmentation fault accours here!
result = avformat_find_stream_info(context, NULL);
if(result &lt; 0) {
  exit(1);
}

std::cout &lt;&lt; &quot;Total number of streams: &quot; &lt;&lt; context-&gt;nb_streams &lt;&lt; std::endl;

But When I change the order and call the avformat_open_input() first for the mp4 file and then the DeckLink device as following it proceed as expected, no error.

AVFormatContext* context{avformat_alloc_context()};
const char* url_source1{&quot;DeckLink Duo (1)&quot;};
const AVInputFormat* format_source1{av_find_input_format(&quot;decklink&quot;)};

const char* url_source2{&quot;http://commondatastorage.googleapis.com/gtv-videos-bucket/sample/BigBuckBunny.mp4&quot;};


// Open the second media input
int result = avformat_open_input(&amp;context, url_source2, NULL, NULL);
if(result &lt; 0) {
  exit(1);
}


// Open the first media input
result = avformat_open_input(&amp;context, url_source1, format_source1, NULL);

if(result &lt; 0) {
  exit(1);
}


result = avformat_find_stream_info(context, NULL);
if(result &lt; 0) {
  exit(1);
}

std::cout &lt;&lt; &quot;Total number of streams: &quot; &lt;&lt; context-&gt;nb_streams &lt;&lt; std::endl;

答案1

得分: 1

在FFmpeg API中明确提到,avformat_open_input()会在失败的情况下释放用户提供的上下文:

  • ps(第一个参数)是指向用户提供的AVFormatContext的指针(由avformat_alloc_context分配),可能是指向NULL的指针,这种情况下,该函数将分配一个AVFormatContext并将其写入ps。请注意,如果出现失败,用户提供的AVFormatContext将被释放。

在错误处理程序中实现av_strerror以获取人类可读的错误信息。这将有所帮助。

英文:

It is clearly mentioned on the FFmpeg API avformat_open_input() will free the user-supplied context in case of failure:

ps (the first parameter) is a pointer to the user-supplied AVFormatContext (allocated by
avformat_alloc_context) may be a pointer to NULL, in which case an AVFormatContext is
allocated by this function and written into ps. Note that a user-supplied AVFormatContext
will be freed on failure.

Implement on your error handler an av_strerror to get human-readable error information. It will help.

huangapple
  • 本文由 发表于 2023年2月24日 08:10:50
  • 转载请务必保留本文链接:https://go.coder-hub.com/75551538.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定