[Libav-user] Flushing Audio Frame Crash
Brad O'Hearne
brado at bighillsoftware.com
Fri May 10 19:15:12 CEST 2013
On May 10, 2013, at 3:44 AM, mohM <phuze9 at gmail.com> wrote:
> I saw another thread on here similar to this, but it didn't really solve my
> problem. Basically, I'm still working on getting my audio encoding to work,
> and I'm now having trouble getting a basic audio encode to work...What I'm
> trying to do is get a single frame of audio to encode. The first call to
> avcodec_encode_audio2() is successfull, and if I leave out the flush loop,
> the console output tells me:
>
> As far as I can understand from the documentation and my experience with
> video encoding, this is pretty normal. When I try to flush the frame by
> passing NULL into avcodec_encode_audio2(), however, the program crashes and
> says "Integer division by zero" in mlock.c. Am I doing something wrong here?
> Any ideas?
Hey there...I assume the "another thread" you are referring to is mine that was posted a few days ago on the same topic. I can identify where you are coming from. This issue, its proper handling, and surrounding implications are not outright documented as a whole in a single place, and where it is referred to in documentation (several places), there seems to be details that have to be inferred. Disclaimer -- I am no expert on this, and don't know if what I put here will help solve your problem, but it's the best of what I understand about it, for better or worse. Hopefully it will help.
Here's where you can find some references to discussion of this:
- avcodec.h, line 4014, frame parameter. Here it mentions using NULL to flush. It doesn't mention exactly whether flushing is a bulk or repeated operation, nor the implications for pts or dts for flushed frames here. But it does reference CODEC_CAP_DELAY, and if you follow to to that parameter's doc, there's much more helpful info.
- avcodec.h, line 737, CODEC_CAP_DELAY define. Explains that encoding needs to end with flushing, and says in so many words that you need to repeat the process of passing a NULL parameter until the encoder has no more frames. Make sure to read the NOTE, as it gives some important information about pts and dts.
- decoding_encoding.h, line 447, flush loop -- it says "get the delayed frames" -- that's essentially flushing the encoder. It doesn't do anything with pts and dts (nor did it for anywhere in this example, but see the CODEC_CAP_DELAY doc for that detail).
As I understand it, the general idea is this: when you execute avcodec_encode_audio2, you are giving the encoder an audio buffer of samples to encode. The encoder may optionally populate and output a packet for you to do further processing (presumably stream or write to drive). That part you probably know and have working. In the case where the encoder does not populate and output a packet in that call, it may have decided for some encoding reason to hold the data. What that means is that after you send the last of your sample data to the encoder in your last normal avcodec_encode_audio2 call, the encoder may still be holding on to data that you previously sent it.
You need to flush this data out of the encoder so that you can process it like the rest of the encoded data by repeating calls to avcodec_encode_audio2 with NULL as the frame parameter to tell the codec to release a single buffered frame. That's important -- this isn't a single call, it may be several. Repeat the process until got_packet_ptr returns a 0 value, indicating that no packet has been returned. Note that the decoding_encoding.c example references a use case where all of the data is known at the time of encoding -- in a streaming scenario, it will usually be the input's attempt to close the stream which should trigger the flushing of the codec.
Note there are a number of unknowns still for me:
- I do not know what codecs support CODEC_CAP_DELAY, or if there's something significant which determines if a codec supports it, or if it is entirely arbitrary.
- I do not know whether you can or what determines if you can change the CODEC_CAP_DELAY value for an encoder from what it is set at after you create the encoder.
- I do not know if a codec without CODEC_CAP_DELAY set can still buffer frames, and if so, how it would be flushed.
That's the best I've pieced together. I hope it helps. If not, I wish you the best of success solving the problem. If I encounter anything which might seem relevant, I'll post it.
Cheers,
Brad
More information about the Libav-user
mailing list