all repos — mgba @ b0fdbab77ec897331ae79b01a4d805764d654d9a

mGBA Game Boy Advance Emulator

Video: Support scaling the output frame
Jeffrey Pfau jeffrey@endrift.com
Wed, 12 Nov 2014 01:25:50 -0800
commit

b0fdbab77ec897331ae79b01a4d805764d654d9a

parent

046a1b71edf961567790a14751549020bec55100

M src/platform/ffmpeg/ffmpeg-encoder.csrc/platform/ffmpeg/ffmpeg-encoder.c

@@ -29,6 +29,7 @@ encoder->containerFormat = 0;

FFmpegEncoderSetAudio(encoder, "flac", 0); FFmpegEncoderSetVideo(encoder, "png", 0); FFmpegEncoderSetContainer(encoder, "matroska"); + FFmpegEncoderSetDimensions(encoder, VIDEO_HORIZONTAL_PIXELS, VIDEO_VERTICAL_PIXELS); encoder->resampleContext = 0; encoder->absf = 0; encoder->context = 0;

@@ -143,6 +144,11 @@ encoder->containerFormat = container;

return true; } +void FFmpegEncoderSetDimensions(struct FFmpegEncoder* encoder, int width, int height) { + encoder->width = width > 0 ? width : VIDEO_HORIZONTAL_PIXELS; + encoder->height = height > 0 ? height : VIDEO_VERTICAL_PIXELS; +} + bool FFmpegEncoderVerifyContainer(struct FFmpegEncoder* encoder) { AVOutputFormat* oformat = av_guess_format(encoder->containerFormat, 0, 0); AVCodec* acodec = avcodec_find_encoder_by_name(encoder->audioCodec);

@@ -218,8 +224,8 @@

encoder->videoStream = avformat_new_stream(encoder->context, vcodec); encoder->video = encoder->videoStream->codec; encoder->video->bit_rate = encoder->videoBitrate; - encoder->video->width = VIDEO_HORIZONTAL_PIXELS; - encoder->video->height = VIDEO_VERTICAL_PIXELS; + encoder->video->width = encoder->width; + encoder->video->height = encoder->height; encoder->video->time_base = (AVRational) { VIDEO_TOTAL_LENGTH, GBA_ARM7TDMI_FREQUENCY }; encoder->video->pix_fmt = encoder->pixFormat; encoder->video->gop_size = 15;

@@ -234,8 +240,8 @@ encoder->videoFrame->width = encoder->video->width;

encoder->videoFrame->height = encoder->video->height; encoder->videoFrame->pts = 0; encoder->scaleContext = sws_getContext(VIDEO_HORIZONTAL_PIXELS, VIDEO_VERTICAL_PIXELS, AV_PIX_FMT_0BGR32, - VIDEO_HORIZONTAL_PIXELS, VIDEO_VERTICAL_PIXELS, encoder->video->pix_fmt, - 0, 0, 0, 0); + encoder->videoFrame->width, encoder->videoFrame->height, encoder->video->pix_fmt, + SWS_POINT, 0, 0, 0); av_image_alloc(encoder->videoFrame->data, encoder->videoFrame->linesize, encoder->video->width, encoder->video->height, encoder->video->pix_fmt, 32); avio_open(&encoder->context->pb, outfile, AVIO_FLAG_WRITE);
M src/platform/ffmpeg/ffmpeg-encoder.hsrc/platform/ffmpeg/ffmpeg-encoder.h

@@ -35,6 +35,8 @@

struct AVCodecContext* video; enum AVPixelFormat pixFormat; struct AVFrame* videoFrame; + int width; + int height; int64_t currentVideoFrame; struct SwsContext* scaleContext; struct AVStream* videoStream;

@@ -44,6 +46,7 @@ void FFmpegEncoderInit(struct FFmpegEncoder*);

bool FFmpegEncoderSetAudio(struct FFmpegEncoder*, const char* acodec, unsigned abr); bool FFmpegEncoderSetVideo(struct FFmpegEncoder*, const char* vcodec, unsigned vbr); bool FFmpegEncoderSetContainer(struct FFmpegEncoder*, const char* container); +void FFmpegEncoderSetDimensions(struct FFmpegEncoder*, int width, int height); bool FFmpegEncoderVerifyContainer(struct FFmpegEncoder*); bool FFmpegEncoderOpen(struct FFmpegEncoder*, const char* outfile); void FFmpegEncoderClose(struct FFmpegEncoder*);
M src/platform/qt/VideoView.cppsrc/platform/qt/VideoView.cpp

@@ -79,6 +79,9 @@

connect(m_ui.abr, SIGNAL(valueChanged(int)), this, SLOT(setAudioBitrate(int))); connect(m_ui.vbr, SIGNAL(valueChanged(int)), this, SLOT(setVideoBitrate(int))); + connect(m_ui.width, SIGNAL(valueChanged(int)), this, SLOT(setWidth(int))); + connect(m_ui.height, SIGNAL(valueChanged(int)), this, SLOT(setHeight(int))); + connect(m_ui.showAdvanced, SIGNAL(clicked(bool)), this, SLOT(showAdvanced(bool))); FFmpegEncoderInit(&m_encoder);

@@ -107,7 +110,7 @@ addPreset(m_ui.presetHQ, (Preset) {

.container = "MP4", .vcodec = "h.264", .acodec = "AAC", - .vbr = 6000, + .vbr = 5000, .abr = 384, .width = 1620, .height = 1080

@@ -144,6 +147,8 @@ setVideoCodec(m_ui.video->currentText());

setAudioBitrate(m_ui.abr->value()); setVideoBitrate(m_ui.vbr->value()); setContainer(m_ui.container->currentText()); + setWidth(m_ui.width->value()); + setHeight(m_ui.height->value()); showAdvanced(false); }

@@ -246,6 +251,24 @@ uncheckIncompatible();

} } +void VideoView::setWidth(int width, bool manual) { + m_width = width; + FFmpegEncoderSetDimensions(&m_encoder, m_width, m_height); + validateSettings(); + if (manual) { + uncheckIncompatible(); + } +} + +void VideoView::setHeight(int height, bool manual) { + m_height = height; + FFmpegEncoderSetDimensions(&m_encoder, m_width, m_height); + validateSettings(); + if (manual) { + uncheckIncompatible(); + } +} + void VideoView::showAdvanced(bool show) { m_ui.advancedBox->setVisible(show); }

@@ -290,7 +313,9 @@ .container = m_container,

.acodec = m_audioCodec, .vcodec = m_videoCodec, .abr = m_abr / 1000, - .vbr = m_vbr / 1000 + .vbr = m_vbr / 1000, + .width = m_width, + .height = m_height }; for (auto iterator = m_presets.constBegin(); iterator != m_presets.constEnd(); ++iterator) {

@@ -370,6 +395,14 @@ }

if (preset.vbr) { setVideoBitrate(preset.vbr, false); safelySet(m_ui.vbr, preset.vbr); + } + if (preset.width) { + setWidth(preset.width, false); + safelySet(m_ui.width, preset.width); + } + if (preset.height) { + setHeight(preset.height, false); + safelySet(m_ui.height, preset.height); } uncheckIncompatible();
M src/platform/qt/VideoView.hsrc/platform/qt/VideoView.h

@@ -52,6 +52,9 @@

void setAudioBitrate(int, bool manual = true); void setVideoBitrate(int, bool manual = true); + void setWidth(int, bool manual = true); + void setHeight(int, bool manual = true); + void showAdvanced(bool); void uncheckIncompatible();

@@ -80,6 +83,9 @@ char* m_containerCstr;

int m_abr; int m_vbr; + + int m_width; + int m_height; QMap<QAbstractButton*, Preset> m_presets;
M src/platform/qt/VideoView.uisrc/platform/qt/VideoView.ui

@@ -152,9 +152,6 @@ <item>

<layout class="QVBoxLayout" name="verticalLayout_3"> <item> <widget class="QRadioButton" name="preset1080"> - <property name="enabled"> - <bool>false</bool> - </property> <property name="text"> <string>1080p</string> </property>

@@ -165,9 +162,6 @@ </widget>

</item> <item> <widget class="QRadioButton" name="preset720"> - <property name="enabled"> - <bool>false</bool> - </property> <property name="text"> <string>720p</string> </property>

@@ -178,9 +172,6 @@ </widget>

</item> <item> <widget class="QRadioButton" name="preset480"> - <property name="enabled"> - <bool>false</bool> - </property> <property name="text"> <string>480p</string> </property>

@@ -191,9 +182,6 @@ </widget>

</item> <item> <widget class="QRadioButton" name="preset160"> - <property name="enabled"> - <bool>false</bool> - </property> <property name="text"> <string>GBA (240x160)</string> </property>

@@ -423,9 +411,6 @@ </widget>

</item> <item row="0" column="3"> <widget class="QSpinBox" name="height"> - <property name="enabled"> - <bool>false</bool> - </property> <property name="minimum"> <number>160</number> </property>

@@ -436,9 +421,6 @@ </widget>

</item> <item row="0" column="1"> <widget class="QSpinBox" name="width"> - <property name="enabled"> - <bool>false</bool> - </property> <property name="minimum"> <number>240</number> </property>