Skip to content

Commit

Permalink
encode zmbv video at proper (fractional) frame rate, prepare some stu…
Browse files Browse the repository at this point in the history
…ff to skip frames if needed. "warpmode" and "no audio" still needs to be fixed

git-svn-id: https://svn.code.sf.net/p/vice-emu/code/trunk@45346 379a1393-f5fb-40a0-bcee-ef074d9b53f7
  • Loading branch information
mrdudz committed Sep 26, 2024
1 parent bb37ca2 commit 58b5dcf
Show file tree
Hide file tree
Showing 4 changed files with 61 additions and 22 deletions.
5 changes: 3 additions & 2 deletions vice/src/gfxoutputdrv/gfxoutput.c
Original file line number Diff line number Diff line change
Expand Up @@ -112,12 +112,13 @@ int gfxoutput_early_init(int help)
gfxoutput_init_iff(help);
gfxoutput_init_pcx(help);
gfxoutput_init_ppm(help);

/* video related */
gfxoutput_init_zmbv(help);
gfxoutput_init_ffmpegexe(help);
#ifdef HAVE_FFMPEG
gfxoutput_init_ffmpeg(help);
#endif
gfxoutput_init_ffmpegexe(help);
gfxoutput_init_zmbv(help);

/* C64 formats */
gfxoutput_init_godot(help);
Expand Down
67 changes: 52 additions & 15 deletions vice/src/gfxoutputdrv/zmbvdrv.c
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,8 @@
#include "lib.h"
#include "log.h"
#include "machine.h"
#include "maincpu.h"
#include "math.h"
#include "palette.h"
#include "resources.h"
#include "screenshot.h"
Expand Down Expand Up @@ -124,7 +126,14 @@ static char *zmbv_format = NULL;
static int audio_freq = 48000; /* initialized by zmbv_soundmovie_init */
static int audio_channels = 1; /* initialized by zmbv_soundmovie_init */

static unsigned int video_framerate = 50; /* initialized by zmbvdrv_init_video */
static double video_framerate = 50.125f; /* initialized by zmbvdrv_init_video */

CLOCK clk_startframe;
CLOCK clk_frame_cycles;
CLOCK clk_last_audio_frame;
CLOCK clk_this_audio_frame;
CLOCK clk_last_video_frame;
CLOCK clk_this_video_frame;

static int zmbvdrv_init_file(void);

Expand Down Expand Up @@ -268,12 +277,12 @@ static int zmbvdrv_open_audio(int speed, int channels)
log_error(LOG_DEFAULT, "zmbvdrv: Error allocating audio buffer (%u bytes)", (unsigned)MAX_AUDIO_BUFFER_SIZE);
return -1;
}
zmbvdrv_audio_in.size = (audio_freq / video_framerate);
LOG(("zmbvdrv_open_audio freq:%d fps:%u bufsize:%d\n", audio_freq, video_framerate, zmbvdrv_audio_in.size));
zmbvdrv_audio_in.size = round((double)audio_freq / video_framerate);
LOG(("zmbvdrv_open_audio freq:%d fps:%f bufsize:%d", audio_freq, video_framerate, zmbvdrv_audio_in.size));
#if 0
memset(cur_audio, 0, zmbvdrv_audio_in.size * 2);
if (zmbv_avi_write_chunk_audio(zavi, &cur_audio[0], zmbvdrv_audio_in.size) < 0) {
LOG(("FATAL: can't write audio frame for screen #%d\n", 0));
LOG(("FATAL: can't write audio frame for screen #%d", 0));
}
#endif
return 0;
Expand Down Expand Up @@ -322,8 +331,11 @@ static int zmbv_soundmovie_encode(soundmovie_buffer_t *audio_in)
{
int ret = 0;

LOGFRAMES(("zmbv_soundmovie_encode(size:%d used:%d channels:%d)",
audio_in->size, audio_in->used, audio_channels));
clk_last_audio_frame = clk_this_audio_frame;
clk_this_audio_frame = maincpu_clk;

LOGFRAMES(("zmbv_soundmovie_encode(size:%d used:%d channels:%d) clk:%ld frame:%d",
audio_in->size, audio_in->used, audio_channels, clk_this_audio_frame, frameno));

/* FIXME: we might have an endianess problem here, we might have to swap lo/hi on BE machines */
if (audio_channels == 1) {
Expand Down Expand Up @@ -403,14 +415,14 @@ static int zmbvdrv_fill_rgb_image(screenshot_t *screenshot)
cur_pal[(x * (PALETTE_COLORS_BPP / 8)) + 2] = screenshot->palette->entries[x].blue;
}

LOGFRAMES(("zmbvdrv_fill_rgb_image video_width/height: %dx%d\n", video_width, video_height));
LOGFRAMES(("zmbvdrv_fill_rgb_image video_width/height: %dx%d", video_width, video_height));
for (y = 0; y < video_height; y++) {
for (x = 0; x < video_width; x++) {
cur_screen[(y * video_width) + x] = screenshot->draw_buffer[bufferoffset + x];
}
bufferoffset += screenshot->draw_buffer_line_size;
}
LOGFRAMES(("zmbvdrv_fill_rgb_image done\n"));
LOGFRAMES(("zmbvdrv_fill_rgb_image done"));

return 0;
}
Expand Down Expand Up @@ -455,9 +467,9 @@ static void zmbvdrv_init_video(screenshot_t *screenshot)
video_init_done = 1;
{
double time_base, fps;
clk_frame_cycles = machine_get_cycles_per_frame();
time_base = ((double)machine_get_cycles_per_frame()) / ((double) machine_get_cycles_per_second());
fps = 1.0f / time_base;
fps += 0.5f;
LOG(("zmbvdrv_init_video fps: %f timebase: %f", fps, time_base));
video_framerate = fps;
}
Expand Down Expand Up @@ -508,7 +520,13 @@ static int zmbvdrv_save(screenshot_t *screenshot, const char *filename)
/* complevel = 9; */
/* no_zlib = 0; */

if (no_zlib) iflg |= ZMBV_INIT_FLAG_NOZLIB;
clk_startframe = maincpu_clk;
clk_this_video_frame = clk_this_audio_frame = clk_startframe;
LOG(("zmbvdrv_save start clock: %ld", clk_startframe));

if (no_zlib) {
iflg |= ZMBV_INIT_FLAG_NOZLIB;
}
LOG(("zmbvdrv_save using compression level %d", complevel));

zmbvdrv_init_video(screenshot);
Expand Down Expand Up @@ -579,38 +597,57 @@ static int zmbvdrv_record(screenshot_t *screenshot)
int ret = -1;
int32_t written;
int flags;
CLOCK clk_diff;

if (audio_init_done && video_init_done && !file_init_done) {
zmbvdrv_init_file();
}

clk_last_video_frame = clk_this_video_frame;
clk_this_video_frame = maincpu_clk;

if (clk_this_video_frame > clk_this_audio_frame) {
/* video ahead of audio */
clk_diff = clk_this_video_frame - clk_this_audio_frame;
if (clk_diff > clk_frame_cycles) {
LOG(("zmbvdrv_record video>audio %ld %ld frame:%ld diff:%ld", clk_this_video_frame, clk_this_audio_frame, clk_frame_cycles, clk_diff));
/*return 0;*/ /* skip this frame? */
}
} else if (clk_this_audio_frame > clk_this_video_frame) {
/* audio is ahead of video */
clk_diff = clk_this_audio_frame - clk_this_video_frame;
if (clk_diff > clk_frame_cycles) {
LOG(("zmbvdrv_record video<audio %ld %ld frame:%ld diff:%ld", clk_this_video_frame, clk_this_audio_frame, clk_frame_cycles, clk_diff));
}
}

zmbvdrv_fill_rgb_image(screenshot);

flags = ((frameno % KEYFRAME_INTERVAL == 0) ? ZMBV_PREP_FLAG_KEYFRAME : ZMBV_PREP_FLAG_NONE);

frameno++;

LOGFRAMES(("zmbvdrv_record: frame %d\n", frameno));
LOGFRAMES(("zmbvdrv_record: frame %d (clk:%ld)", frameno, clk_this_video_frame));

/* encode video frame */
if (zmbv_encode_prepare_frame(zcodec, flags, fmt, cur_pal, video_work_buffer, work_buffer_size) < 0) {
LOG(("FATAL: can't prepare frame for screen #%d\n", frameno));
LOG(("FATAL: can't prepare frame for screen #%d", frameno));
goto quit;
}
for (int y = 0; y < video_height; ++y) {
if (zmbv_encode_line(zcodec, cur_screen+(y*video_width)) < 0) {
LOG(("FATAL: can't encode line #%d for screen #%d\n", y, frameno));
LOG(("FATAL: can't encode line #%d for screen #%d", y, frameno));
goto quit;
}
}
written = zmvb_encode_finish_frame(zcodec);
if (written < 0) {
LOG(("FATAL: can't finish frame for screen #%d\n", frameno));
LOG(("FATAL: can't finish frame for screen #%d", frameno));
goto quit;
}
/* write avi chunk */
if (zmbv_avi_write_chunk_video(zavi, video_work_buffer, written) < 0) {
LOG(("FATAL: can't write compressed frame for screen #%d\n", frameno));
LOG(("FATAL: can't write compressed frame for screen #%d", frameno));
goto quit;
}
ret = 0;
Expand Down
9 changes: 5 additions & 4 deletions vice/src/lib/libzmbv/zmbv_avi.c
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <math.h>

#include <sys/stat.h>
#include <sys/types.h>
Expand Down Expand Up @@ -69,7 +70,7 @@ struct zmbv_avi_s {
uint8_t *index;
uint32_t indexsize, indexused;
uint32_t width, height;
uint32_t fps;
double fps;
uint32_t frames;
uint32_t written;
//uint32_t audioused; // always 0 for now
Expand All @@ -79,7 +80,7 @@ struct zmbv_avi_s {
};


zmbv_avi_t zmbv_avi_start (const char *fname, int width, int height, int fps, int audiorate) {
zmbv_avi_t zmbv_avi_start (const char *fname, int width, int height, double fps, int audiorate) {
if (fname != NULL && fname[0] && width > 0 && height > 0 && width <= 16384 && height <= 16384 && fps > 0 && fps <= 100) {
zmbv_avi_t zavi = malloc(sizeof(*zavi));
if (zavi == NULL) return NULL;
Expand Down Expand Up @@ -139,7 +140,7 @@ int zmbv_avi_stop (zmbv_avi_t zavi) {

AVIOUT4("avih");
AVIOUTd(56); // # of bytes to follow
AVIOUTd((uint32_t)(1000000/zavi->fps)); // microseconds per frame
AVIOUTd((uint32_t)round(1000000.0f/zavi->fps)); // microseconds per frame
AVIOUTd(0);
AVIOUTd(0); // PaddingGranularity (whatever that might be)
AVIOUTd(0x110); // Flags, 0x10 has index, 0x100 interleaved
Expand Down Expand Up @@ -167,7 +168,7 @@ int zmbv_avi_stop (zmbv_avi_t zavi) {
AVIOUTd(0); // Reserved, MS says: wPriority, wLanguage
AVIOUTd(0); // InitialFrames
AVIOUTd(1000000); // Scale
AVIOUTd((uint32_t)(1000000*zavi->fps)); // Rate: Rate/Scale == samples/second
AVIOUTd((uint32_t)round(1000000.0f*zavi->fps)); // Rate: Rate/Scale == samples/second
AVIOUTd(0); // Start
AVIOUTd(zavi->frames); // Length
AVIOUTd(0); // SuggestedBufferSize
Expand Down
2 changes: 1 addition & 1 deletion vice/src/lib/libzmbv/zmbv_avi.h
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ extern "C" {

typedef struct zmbv_avi_s *zmbv_avi_t;

extern zmbv_avi_t zmbv_avi_start (const char *fname, int width, int height, int fps, int audiorate);
extern zmbv_avi_t zmbv_avi_start (const char *fname, int width, int height, double fps, int audiorate);
extern int zmbv_avi_stop (zmbv_avi_t zavi);

extern int zmbv_avi_write_chunk (zmbv_avi_t zavi, const char tag[4], uint32_t size, const void *data, uint32_t flags);
Expand Down

0 comments on commit 58b5dcf

Please sign in to comment.