"invalid argument" av_buffersrc_write_frame/av_buffersrc_add_frame
"invalid argument" for av_buffersrc_write_frame / av_buffersrc_add_frame
我正在尝试使用FFmpeg C api创建一个过滤器来合并两个音频流。尝试遵循这里的代码:在Android NDK 中使用Libavfilter库实现多输入过滤器图
一切似乎都很好。
然而,一旦我调用av_buffersrc_write_frame(或av_bufffersrc_add_frame或av_bbuffersrc_add-frame_flags,这无关紧要),FFmpeg只报告"无效参数",而不报告其他任何信息-这是一条完全无用的错误消息,因为它可能意味着一切
哪个参数无效?它怎么了?没人知道。
我正在初始化图形并"抓取"缓冲区源的上下文,以便稍后使用,如下所示:
// Alloc filter graph
*filter_graph = avfilter_graph_alloc();
if ((*filter_graph) == NULL) {
os::log("Error: Cannot allocate filter graph.");
return AVERROR(ENOMEM);
}
// Building the filter string, ommitted
int result = avfilter_graph_parse2(*filter_graph, filterString.c_str(), &gis, &gos, NULL);
if (result < 0)
{
char errorBuf[1024];
av_make_error_string(errorBuf, 1024, result);
log("Error: Parsing filter string: %s", errorBuf);
return AVERROR_EXIT;
}
// Configure the graph
result = avfilter_graph_config(*filter_graph, NULL);
if (result < 0)
{
char errorBuf[1024];
av_make_error_string(errorBuf, 1024, result);
log("Error: Configuring filter graph: %s", errorBuf);
return AVERROR_EXIT;
}
// Get the buffer source and buffer sink contexts
for (unsigned int i = 0; i < (*filter_graph)->nb_filters; ++i) {
AVFilterContext* filterContext = (*filter_graph)->filters[i];
// The first two filters should be the abuffers
std::string name = filterContext->name;
if (name.find("abuffer") != name.npos && i < 2) {
inputs[i].buffer_source_context = filterContext;
}
// abuffersink is the one we need to get the converted frames from
if (name.find("abuffersink") != name.npos) {
*buffer_sink_context = filterContext;
}
}
初始化过程中绝对没有错误。至少FFmpeg对此只有这一点,我认为这看起来不错:
FFMPEG: [Parsed_abuffer_0 @ 0ddfe840] Setting 'time_base' to value '1/48000'
FFMPEG: [Parsed_abuffer_0 @ 0ddfe840] Setting 'sample_rate' to value '48000'
FFMPEG: [Parsed_abuffer_0 @ 0ddfe840] Setting 'sample_fmt' to value '1'
FFMPEG: [Parsed_abuffer_0 @ 0ddfe840] Setting 'channel_layout' to value '3'
FFMPEG: [Parsed_abuffer_0 @ 0ddfe840] Setting 'channels' to value '2'
FFMPEG: [Parsed_abuffer_0 @ 0ddfe840] tb:1/48000 samplefmt:s16 samplerate:48000 chlayout:3
FFMPEG: [Parsed_abuffer_1 @ 0ddfe500] Setting 'time_base' to value '1/44100'
FFMPEG: [Parsed_abuffer_1 @ 0ddfe500] Setting 'sample_rate' to value '44100'
FFMPEG: [Parsed_abuffer_1 @ 0ddfe500] Setting 'sample_fmt' to value '1'
FFMPEG: [Parsed_abuffer_1 @ 0ddfe500] Setting 'channel_layout' to value '3'
FFMPEG: [Parsed_abuffer_1 @ 0ddfe500] Setting 'channels' to value '2'
FFMPEG: [Parsed_abuffer_1 @ 0ddfe500] tb:1/44100 samplefmt:s16 samplerate:44100 chlayout:3
FFMPEG: [Parsed_volume_3 @ 0ddfe580] Setting 'volume' to value '2'
FFMPEG: [Parsed_aresample_4 @ 0ddfe660] Setting 'sample_rate' to value '48000'
FFMPEG: [Parsed_aformat_5 @ 0ddfe940] Setting 'sample_fmts' to value 'fltp'
FFMPEG: [Parsed_aformat_5 @ 0ddfe940] Setting 'channel_layouts' to value '3'
然后,我试图添加一个帧(事先已经解码),如下所示:
// "buffer_source_context" is one of the "inputs[i].buffer_source_context" from the code above
int result = av_buffersrc_write_frame( buffer_source_context,
input_frame);
if (result < 0) {
char errorBuf[1024];
av_make_error_string(errorBuf, 1024, result);
log("Error: While adding to buffer source: %s", errorBuf);
return AVERROR_EXIT;
}
结果就是上面提到的"无效论点"。
buffer_source_context是上面代码中提到的一个,input_frame也非常好。在添加筛选代码之前,相同的帧被传递给编码器,而没有问题。
我对这里可能出现的错误感到不知所措。我以尽可能低的级别记录FFmpeg错误,但没有显示任何错误。我使用的是FFmpeg 3.1.1。
事实证明,问题是输入(解码器)的AVCodecContext的初始化
正如您在我的问题中看到的,abuffer滤波器的channel_layouts设置为3(表示立体声)。该值直接取自输入的AVCodecContext。
因此,自然地,人们会假设从输入读取和解码的帧将在该信道布局中
由于某种原因,他们没有。相反,在打开AVCodecContext之前,我必须将其上的channel_layout
和requested_channel_layout
都设置为立体声(AV_CH_LAYOUT_stereo)。
最终让我得出这个结论的是,我吞下了查看FFmpeg源代码的苦果(在这种特定情况下,不可能进行实时调试),并找到了可能为该函数抛出无效参数错误的地方
我发现许多类似的地方:
int ch = src->channels;
if (!ch) {
ret = AVERROR(EINVAL);
goto fail;
}
所以我检查了所有的候选人,最终发现频道布局不匹配。
如果FFmpeg的作者们能花一些时间在这种情况下输出真正有用的错误消息,我就不会浪费近两天的时间在大海捞针了。
代码仍然不起作用,因为似乎同时有多个输入会使av_read_frame几乎停止,但这与这个问题无关。但问题中的代码部分总是正确的(至少我认为是这样),错误在其他地方。
- 堆叠协程 + gdb = "previous frame inner to this frame (corrupt stack)?"
- OpenCV VideoCapture Partial Frame Corruption
- openh264 Repeating frame
- g++:如果在 -O2 或 -O3 之前指定,-fno-omit-frame-pointer 是否有效
- C# 到非托管 C++ DLL 访问冲突/"frame not in module"
- 源代码中的这一行(cap>> frame;)是什么意思?
- cvCaptureFromCAM(CV_CAP_DSHOW) capture blank frame
- ID3 Frame Header
- Xcode的GDB在设备上安装时显示"Warning: the current language does not match this frame"
- DockPaneLeftOf in CMDIChildWndEx Frame
- 调试失败,gdb: "Could not find the frame base" ,但使用 lldb
- cvResize on a video frame
- visual MFT Frame Extraction in c++
- 为什么函数'x'.write(frame)对我不起作用?