Core: Allow changing video dimensions
Jeffrey Pfau jeffrey@endrift.com
Mon, 15 Feb 2016 22:19:15 -0800
7 files changed,
60 insertions(+),
21 deletions(-)
M
src/core/interface.h
→
src/core/interface.h
@@ -21,6 +21,7 @@
struct blip_t; struct mAVStream { + void (*videoDimensionsChanged)(struct mAVStream*, unsigned width, unsigned height); void (*postVideoFrame)(struct mAVStream*, const color_t* buffer, size_t stride); void (*postAudioFrame)(struct mAVStream*, int16_t left, int16_t right); void (*postAudioBuffer)(struct mAVStream*, struct blip_t* left, struct blip_t* right);
M
src/gb/core.c
→
src/gb/core.c
@@ -117,6 +117,9 @@
static void _GBCoreSetAVStream(struct mCore* core, struct mAVStream* stream) { struct GB* gb = core->board; gb->stream = stream; + if (stream && stream->videoDimensionsChanged) { + stream->videoDimensionsChanged(stream, GB_VIDEO_HORIZONTAL_PIXELS, GB_VIDEO_VERTICAL_PIXELS); + } } static bool _GBCoreLoadROM(struct mCore* core, struct VFile* vf) {
M
src/gba/core.c
→
src/gba/core.c
@@ -148,6 +148,9 @@
static void _GBACoreSetAVStream(struct mCore* core, struct mAVStream* stream) { struct GBA* gba = core->board; gba->stream = stream; + if (stream && stream->videoDimensionsChanged) { + stream->videoDimensionsChanged(stream, VIDEO_HORIZONTAL_PIXELS, VIDEO_VERTICAL_PIXELS); + } } static bool _GBACoreLoadROM(struct mCore* core, struct VFile* vf) {
M
src/platform/ffmpeg/ffmpeg-encoder.c
→
src/platform/ffmpeg/ffmpeg-encoder.c
@@ -24,6 +24,7 @@ #include <libswscale/swscale.h>
static void _ffmpegPostVideoFrame(struct mAVStream*, const color_t* pixels, size_t stride); static void _ffmpegPostAudioFrame(struct mAVStream*, int16_t left, int16_t right); +static void _ffmpegSetVideoDimensions(struct mAVStream*, unsigned width, unsigned height); enum { PREFERRED_SAMPLE_RATE = 0x8000@@ -32,6 +33,7 @@
void FFmpegEncoderInit(struct FFmpegEncoder* encoder) { av_register_all(); + encoder->d.videoDimensionsChanged = _ffmpegSetVideoDimensions; encoder->d.postVideoFrame = _ffmpegPostVideoFrame; encoder->d.postAudioFrame = _ffmpegPostAudioFrame; encoder->d.postAudioBuffer = 0;@@ -43,9 +45,12 @@ FFmpegEncoderSetAudio(encoder, "flac", 0);
FFmpegEncoderSetVideo(encoder, "png", 0); FFmpegEncoderSetContainer(encoder, "matroska"); FFmpegEncoderSetDimensions(encoder, VIDEO_HORIZONTAL_PIXELS, VIDEO_VERTICAL_PIXELS); + encoder->iwidth = VIDEO_HORIZONTAL_PIXELS; + encoder->iheight = VIDEO_VERTICAL_PIXELS; encoder->resampleContext = 0; encoder->absf = 0; encoder->context = 0; + encoder->scaleContext = NULL; } bool FFmpegEncoderSetAudio(struct FFmpegEncoder* encoder, const char* acodec, unsigned abr) {@@ -290,22 +295,7 @@ encoder->videoFrame->format = encoder->video->pix_fmt;
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, -#ifdef COLOR_16_BIT -#ifdef COLOR_5_6_5 - AV_PIX_FMT_RGB565, -#else - AV_PIX_FMT_BGR555, -#endif -#else -#ifndef USE_LIBAV - AV_PIX_FMT_0BGR32, -#else - AV_PIX_FMT_BGR32, -#endif -#endif - encoder->videoFrame->width, encoder->videoFrame->height, encoder->video->pix_fmt, - SWS_POINT, 0, 0, 0); + _ffmpegSetVideoDimensions(&encoder->d, encoder->iwidth, encoder->iheight); 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);@@ -351,6 +341,7 @@ #endif
avcodec_close(encoder->video); sws_freeContext(encoder->scaleContext); + encoder->scaleContext = NULL; avformat_free_context(encoder->context); encoder->context = 0;@@ -437,7 +428,7 @@ #endif
encoder->videoFrame->pts = av_rescale_q(encoder->currentVideoFrame, encoder->video->time_base, encoder->videoStream->time_base); ++encoder->currentVideoFrame; - sws_scale(encoder->scaleContext, (const uint8_t* const*) &pixels, (const int*) &stride, 0, VIDEO_VERTICAL_PIXELS, encoder->videoFrame->data, encoder->videoFrame->linesize); + sws_scale(encoder->scaleContext, (const uint8_t* const*) &pixels, (const int*) &stride, 0, encoder->iheight, encoder->videoFrame->data, encoder->videoFrame->linesize); int gotData; avcodec_encode_video2(encoder->video, &packet, encoder->videoFrame, &gotData);@@ -450,3 +441,28 @@ av_interleaved_write_frame(encoder->context, &packet);
} av_free_packet(&packet); } + +static void _ffmpegSetVideoDimensions(struct mAVStream* stream, unsigned width, unsigned height) { + struct FFmpegEncoder* encoder = (struct FFmpegEncoder*) stream; + encoder->iwidth = width; + encoder->iheight = height; + if (encoder->scaleContext) { + sws_freeContext(encoder->scaleContext); + } + encoder->scaleContext = sws_getContext(encoder->iwidth, encoder->iheight, +#ifdef COLOR_16_BIT +#ifdef COLOR_5_6_5 + AV_PIX_FMT_RGB565, +#else + AV_PIX_FMT_BGR555, +#endif +#else +#ifndef USE_LIBAV + AV_PIX_FMT_0BGR32, +#else + AV_PIX_FMT_BGR32, +#endif +#endif + encoder->videoFrame->width, encoder->videoFrame->height, encoder->video->pix_fmt, + SWS_POINT, 0, 0, 0); +}
M
src/platform/ffmpeg/ffmpeg-encoder.h
→
src/platform/ffmpeg/ffmpeg-encoder.h
@@ -42,6 +42,8 @@ enum AVPixelFormat pixFormat;
struct AVFrame* videoFrame; int width; int height; + int iwidth; + int iheight; int64_t currentVideoFrame; struct SwsContext* scaleContext; struct AVStream* videoStream;
M
src/platform/imagemagick/imagemagick-gif-encoder.c
→
src/platform/imagemagick/imagemagick-gif-encoder.c
@@ -9,16 +9,21 @@ #include "gba/video.h"
#include "util/string.h" static void _magickPostVideoFrame(struct mAVStream*, const color_t* pixels, size_t stride); +static void _magickVideoDimensionsChanged(struct mAVStream*, unsigned width, unsigned height); void ImageMagickGIFEncoderInit(struct ImageMagickGIFEncoder* encoder) { encoder->wand = 0; + encoder->d.videoDimensionsChanged = _magickVideoDimensionsChanged; encoder->d.postVideoFrame = _magickPostVideoFrame; encoder->d.postAudioFrame = 0; encoder->d.postAudioBuffer = 0; encoder->frameskip = 2; encoder->delayMs = -1; + + encoder->iwidth = VIDEO_HORIZONTAL_PIXELS; + encoder->iheight = VIDEO_VERTICAL_PIXELS; } void ImageMagickGIFEncoderSetParams(struct ImageMagickGIFEncoder* encoder, int frameskip, int delayMs) {@@ -35,7 +40,7 @@ encoder->wand = NewMagickWand();
MagickSetImageFormat(encoder->wand, "GIF"); MagickSetImageDispose(encoder->wand, PreviousDispose); encoder->outfile = strdup(outfile); - encoder->frame = malloc(VIDEO_HORIZONTAL_PIXELS * VIDEO_VERTICAL_PIXELS * 4); + encoder->frame = malloc(encoder->iwidth * encoder->iheight * 4); encoder->currentFrame = 0; return true; }@@ -68,11 +73,11 @@ }
const uint8_t* p8 = (const uint8_t*) pixels; size_t row; - for (row = 0; row < VIDEO_VERTICAL_PIXELS; ++row) { - memcpy(&encoder->frame[row * VIDEO_HORIZONTAL_PIXELS], &p8[row * 4 * stride], VIDEO_HORIZONTAL_PIXELS * 4); + for (row = 0; row < encoder->iheight; ++row) { + memcpy(&encoder->frame[row * encoder->iwidth], &p8[row * 4 * stride], encoder->iwidth * 4); } - MagickConstituteImage(encoder->wand, VIDEO_HORIZONTAL_PIXELS, VIDEO_VERTICAL_PIXELS, "RGBP", CharPixel, encoder->frame); + MagickConstituteImage(encoder->wand, encoder->iwidth, encoder->iheight, "RGBP", CharPixel, encoder->frame); uint64_t ts = encoder->currentFrame; uint64_t nts = encoder->currentFrame + encoder->frameskip + 1; if (encoder->delayMs >= 0) {@@ -89,3 +94,9 @@ }
MagickSetImageDelay(encoder->wand, nts - ts); ++encoder->currentFrame; } + +static void _magickVideoDimensionsChanged(struct mAVStream* stream, unsigned width, unsigned height) { + struct ImageMagickGIFEncoder* encoder = (struct ImageMagickGIFEncoder*) stream; + encoder->iwidth = width; + encoder->iheight = height; +}
M
src/platform/imagemagick/imagemagick-gif-encoder.h
→
src/platform/imagemagick/imagemagick-gif-encoder.h
@@ -22,6 +22,9 @@
unsigned currentFrame; int frameskip; int delayMs; + + unsigned iwidth; + unsigned iheight; }; void ImageMagickGIFEncoderInit(struct ImageMagickGIFEncoder*);