mirror of
https://github.com/panda3d/panda3d.git
synced 2025-10-04 19:08:55 -04:00
ffmpeg: Add async audio decoding loop
This leverages libavcodec >= 57.37.100's new asynchronous API, which both allows decoding in hardware and in a separate thread, and in any case would free up more CPU time for Panda's app loop. This also avoids use of the now-deprecated `avcodec_decode_audio4`
This commit is contained in:
parent
62f9de101a
commit
e430428703
@ -299,6 +299,62 @@ fetch_packet() {
|
|||||||
*/
|
*/
|
||||||
bool FfmpegAudioCursor::
|
bool FfmpegAudioCursor::
|
||||||
reload_buffer() {
|
reload_buffer() {
|
||||||
|
#if LIBAVCODEC_VERSION_INT >= AV_VERSION_INT(57, 37, 100)
|
||||||
|
// lavc >= 57.37.100 deprecates the old (avcodec_decode_audio*) API in favor
|
||||||
|
// of a newer, asynchronous API. This is great for our purposes - it gives
|
||||||
|
// the codec the opportunity to decode in the background (e.g. in another
|
||||||
|
// thread or on a dedicated hardware coprocessor).
|
||||||
|
|
||||||
|
// First, let's fill the codec's input buffer with as many packets as it'll
|
||||||
|
// take:
|
||||||
|
int ret;
|
||||||
|
while (_packet->data != nullptr) {
|
||||||
|
ret = avcodec_send_packet(_audio_ctx, _packet);
|
||||||
|
|
||||||
|
if (ret != 0) {
|
||||||
|
// Nonzero return code is an error.
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
// If we got here, the codec took the packet! Fetch another one.
|
||||||
|
fetch_packet();
|
||||||
|
if (_packet->data == nullptr) {
|
||||||
|
// fetch_packet() says we're out of packets. Let the codec know.
|
||||||
|
ret = avcodec_send_packet(_audio_ctx, NULL);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Expected ret codes are 0 (we ran out of packets) and EAGAIN (codec full)
|
||||||
|
if ((ret != 0) && (ret != AVERROR(EAGAIN))) {
|
||||||
|
// Some odd error happened. We can't proceed.
|
||||||
|
ffmpeg_cat.error()
|
||||||
|
<< "avcodec_send_packet returned " << ret << "\n";
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Now we retrieve our frame!
|
||||||
|
ret = avcodec_receive_frame(_audio_ctx, _frame);
|
||||||
|
|
||||||
|
if (ret == AVERROR_EOF) {
|
||||||
|
// The only way for this to happen is if we're out of packets.
|
||||||
|
nassertr(_packet->data == nullptr, false);
|
||||||
|
|
||||||
|
// Synthesize silence:
|
||||||
|
_buffer_head = 0;
|
||||||
|
_buffer_tail = _buffer_size;
|
||||||
|
memset(_buffer, 0, _buffer_size * 2);
|
||||||
|
return true;
|
||||||
|
|
||||||
|
} else if (ret != 0) {
|
||||||
|
// Some odd error happened. We can't proceed.
|
||||||
|
ffmpeg_cat.error()
|
||||||
|
<< "avcodec_receive_frame returned " << ret << "\n";
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// We now have _frame. It will be handled below.
|
||||||
|
|
||||||
|
#else
|
||||||
int got_frame = 0;
|
int got_frame = 0;
|
||||||
while (!got_frame) {
|
while (!got_frame) {
|
||||||
// If we're out of packets, generate silence.
|
// If we're out of packets, generate silence.
|
||||||
@ -339,6 +395,7 @@ reload_buffer() {
|
|||||||
_packet_data += len;
|
_packet_data += len;
|
||||||
_packet_size -= len;
|
_packet_size -= len;
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
int bufsize;
|
int bufsize;
|
||||||
#ifdef HAVE_SWRESAMPLE
|
#ifdef HAVE_SWRESAMPLE
|
||||||
|
Loading…
x
Reference in New Issue
Block a user