FFmpeg: Drain recording buffers

This commit is contained in:
Vicki Pfau 2019-09-16 23:34:09 -07:00
parent 29fc787fc9
commit e15185f521
2 changed files with 41 additions and 11 deletions

View File

@ -60,6 +60,7 @@ Other fixes:
- Qt: Only show emulator restart warning once per settings saving
- Qt: Improve cheat view UX
- GB: Fix SGB controller incrementing (fixes mgba.io/i/1104)
- FFmpeg: Drain recording buffers
Misc:
- GBA Savedata: EEPROM performance fixes
- GBA Savedata: Automatically map 1Mbit Flash files as 1Mbit Flash

View File

@ -30,6 +30,9 @@ static void _ffmpegPostVideoFrame(struct mAVStream*, const color_t* pixels, size
static void _ffmpegPostAudioFrame(struct mAVStream*, int16_t left, int16_t right);
static void _ffmpegSetVideoDimensions(struct mAVStream*, unsigned width, unsigned height);
static bool _ffmpegWriteAudioFrame(struct FFmpegEncoder* encoder, struct AVFrame* audioFrame);
static bool _ffmpegWriteVideoFrame(struct FFmpegEncoder* encoder, struct AVFrame* videoFrame);
enum {
PREFERRED_SAMPLE_RATE = 0x8000
};
@ -390,6 +393,21 @@ bool FFmpegEncoderOpen(struct FFmpegEncoder* encoder, const char* outfile) {
}
void FFmpegEncoderClose(struct FFmpegEncoder* encoder) {
if (encoder->audio) {
while (true) {
if (!_ffmpegWriteAudioFrame(encoder, NULL)) {
break;
}
}
}
if (encoder->video) {
while (true) {
if (!_ffmpegWriteVideoFrame(encoder, NULL)) {
break;
}
}
}
if (encoder->context && encoder->context->pb) {
av_write_trailer(encoder->context);
avio_close(encoder->context->pb);
@ -510,6 +528,10 @@ void _ffmpegPostAudioFrame(struct mAVStream* stream, int16_t left, int16_t right
encoder->audioFrame->pts = encoder->currentAudioFrame;
encoder->currentAudioFrame += samples;
_ffmpegWriteAudioFrame(encoder, encoder->audioFrame);
}
bool _ffmpegWriteAudioFrame(struct FFmpegEncoder* encoder, struct AVFrame* audioFrame) {
AVPacket packet;
av_init_packet(&packet);
packet.data = 0;
@ -517,13 +539,13 @@ void _ffmpegPostAudioFrame(struct mAVStream* stream, int16_t left, int16_t right
int gotData;
#ifdef FFMPEG_USE_PACKETS
avcodec_send_frame(encoder->audio, encoder->audioFrame);
avcodec_send_frame(encoder->audio, audioFrame);
gotData = avcodec_receive_packet(encoder->audio, &packet);
gotData = (gotData == 0) && packet.size;
#else
avcodec_encode_audio2(encoder->audio, &packet, encoder->audioFrame, &gotData);
avcodec_encode_audio2(encoder->audio, &packet, audioFrame, &gotData);
#endif
packet.pts = av_rescale_q(encoder->audioFrame->pts, encoder->audio->time_base, encoder->audioStream->time_base);
packet.pts = av_rescale_q(packet.pts, encoder->audio->time_base, encoder->audioStream->time_base);
packet.dts = packet.pts;
if (gotData) {
@ -566,6 +588,7 @@ void _ffmpegPostAudioFrame(struct mAVStream* stream, int16_t left, int16_t right
#else
av_free_packet(&packet);
#endif
return gotData;
}
void _ffmpegPostVideoFrame(struct mAVStream* stream, const color_t* pixels, size_t stride) {
@ -575,11 +598,6 @@ void _ffmpegPostVideoFrame(struct mAVStream* stream, const color_t* pixels, size
}
stride *= BYTES_PER_PIXEL;
AVPacket packet;
av_init_packet(&packet);
packet.data = 0;
packet.size = 0;
#if LIBAVCODEC_VERSION_MAJOR >= 55
av_frame_make_writable(encoder->videoFrame);
#endif
@ -588,14 +606,23 @@ void _ffmpegPostVideoFrame(struct mAVStream* stream, const color_t* pixels, size
sws_scale(encoder->scaleContext, (const uint8_t* const*) &pixels, (const int*) &stride, 0, encoder->iheight, encoder->videoFrame->data, encoder->videoFrame->linesize);
_ffmpegWriteVideoFrame(encoder, encoder->videoFrame);
}
bool _ffmpegWriteVideoFrame(struct FFmpegEncoder* encoder, struct AVFrame* videoFrame) {
AVPacket packet;
av_init_packet(&packet);
packet.data = 0;
packet.size = 0;
int gotData;
#ifdef FFMPEG_USE_PACKETS
avcodec_send_frame(encoder->video, encoder->videoFrame);
avcodec_send_frame(encoder->video, videoFrame);
gotData = avcodec_receive_packet(encoder->video, &packet) == 0;
#else
avcodec_encode_video2(encoder->video, &packet, encoder->videoFrame, &gotData);
avcodec_encode_video2(encoder->video, &packet, videoFrame, &gotData);
#endif
packet.pts = encoder->videoFrame->pts;
if (gotData) {
#ifndef FFMPEG_USE_PACKET_UNREF
if (encoder->video->coded_frame->key_frame) {
@ -610,6 +637,8 @@ void _ffmpegPostVideoFrame(struct mAVStream* stream, const color_t* pixels, size
#else
av_free_packet(&packet);
#endif
return gotData;
}
static void _ffmpegSetVideoDimensions(struct mAVStream* stream, unsigned width, unsigned height) {