diff --git a/src/emu/video.c b/src/emu/video.c index aebf8cf5bff..9cc30c0506f 100644 --- a/src/emu/video.c +++ b/src/emu/video.c @@ -101,10 +101,13 @@ video_manager::video_manager(running_machine &machine) m_snap_native(true), m_snap_width(0), m_snap_height(0), - m_avifile(NULL), - m_movie_frame_period(attotime::zero), - m_movie_next_frame_time(attotime::zero), - m_movie_frame(0) + m_mng_frame_period(attotime::zero), + m_mng_next_frame_time(attotime::zero), + m_mng_frame(0), + m_avi_file(NULL), + m_avi_frame_period(attotime::zero), + m_avi_next_frame_time(attotime::zero), + m_avi_frame(0) { // request a callback upon exiting machine.add_notifier(MACHINE_NOTIFY_EXIT, machine_notify_delegate(FUNC(video_manager::exit), this)); @@ -359,19 +362,19 @@ void video_manager::save_active_screen_snapshots() void video_manager::begin_recording(const char *name, movie_format format) { - // stop any existign recording - end_recording(); - // create a snapshot bitmap so we know what the target size is create_snapshot_bitmap(NULL); - // reset the state - m_movie_frame = 0; - m_movie_next_frame_time = machine().time(); - // start up an AVI recording if (format == MF_AVI) { + // stop any existing recording + end_recording(format); + + // reset the state + m_avi_frame = 0; + m_avi_next_frame_time = machine().time(); + // build up information about this new movie avi_movie_info info; info.video_format = 0; @@ -400,9 +403,6 @@ void video_manager::begin_recording(const char *name, movie_format format) else filerr = open_next(tempfile, "avi"); - // compute the frame time - m_movie_frame_period = attotime::from_seconds(1000) / info.video_timescale; - // if we succeeded, make a copy of the name and create the real file over top if (filerr == FILERR_NONE) fullpath = tempfile.fullpath(); @@ -410,39 +410,55 @@ void video_manager::begin_recording(const char *name, movie_format format) if (filerr == FILERR_NONE) { + // compute the frame time + m_avi_frame_period = attotime::from_seconds(1000) / info.video_timescale; + // create the file and free the string - avi_error avierr = avi_create(fullpath, &info, &m_avifile); + avi_error avierr = avi_create(fullpath, &info, &m_avi_file); if (avierr != AVIERR_NONE) + { mame_printf_error("Error creating AVI: %s\n", avi_error_string(avierr)); + return end_recording(format); + } } } // start up a MNG recording else if (format == MF_MNG) { + // stop any existing recording + end_recording(format); + + // reset the state + m_mng_frame = 0; + m_mng_next_frame_time = machine().time(); + // create a new movie file and start recording - m_mngfile.reset(global_alloc(emu_file(machine().options().snapshot_directory(), OPEN_FLAG_WRITE | OPEN_FLAG_CREATE | OPEN_FLAG_CREATE_PATHS))); + m_mng_file.reset(global_alloc(emu_file(machine().options().snapshot_directory(), OPEN_FLAG_WRITE | OPEN_FLAG_CREATE | OPEN_FLAG_CREATE_PATHS))); file_error filerr; if (name != NULL) - filerr = m_mngfile->open(name); + filerr = m_mng_file->open(name); else - filerr = open_next(*m_mngfile, "mng"); + filerr = open_next(*m_mng_file, "mng"); if (filerr == FILERR_NONE) { // start the capture int rate = (machine().first_screen() != NULL) ? ATTOSECONDS_TO_HZ(machine().first_screen()->frame_period().attoseconds) : screen_device::DEFAULT_FRAME_RATE; - png_error pngerr = mng_capture_start(*m_mngfile, m_snap_bitmap, rate); + png_error pngerr = mng_capture_start(*m_mng_file, m_snap_bitmap, rate); if (pngerr != PNGERR_NONE) - return end_recording(); + { + mame_printf_error("Error capturing MNG, png_error=%d\n", pngerr); + return end_recording(format); + } // compute the frame time - m_movie_frame_period = attotime::from_hz(rate); + m_mng_frame_period = attotime::from_hz(rate); } else { - mame_printf_error("Error creating MNG\n"); - m_mngfile.reset(); + mame_printf_error("Error creating MNG, file_error=%d\n", filerr); + m_mng_file.reset(); } } } @@ -452,24 +468,32 @@ void video_manager::begin_recording(const char *name, movie_format format) // end_recording - stop recording of a movie //------------------------------------------------- -void video_manager::end_recording() +void video_manager::end_recording(movie_format format) { - // close the file if it exists - if (m_avifile != NULL) + if (format == MF_AVI) { - avi_close(m_avifile); - m_avifile = NULL; + // close the file if it exists + if (m_avi_file != NULL) + { + avi_close(m_avi_file); + m_avi_file = NULL; + + // reset the state + m_avi_frame = 0; + } } - - // close the file if it exists - if (m_mngfile != NULL) + else if (format == MF_MNG) { - mng_capture_stop(*m_mngfile); - m_mngfile.reset(); - } + // close the file if it exists + if (m_mng_file != NULL) + { + mng_capture_stop(*m_mng_file); + m_mng_file.reset(); - // reset the state - m_movie_frame = 0; + // reset the state + m_mng_frame = 0; + } + } } @@ -481,16 +505,16 @@ void video_manager::end_recording() void video_manager::add_sound_to_recording(const INT16 *sound, int numsamples) { // only record if we have a file - if (m_avifile != NULL) + if (m_avi_file != NULL) { g_profiler.start(PROFILER_MOVIE_REC); // write the next frame - avi_error avierr = avi_append_sound_samples(m_avifile, 0, sound + 0, numsamples, 1); + avi_error avierr = avi_append_sound_samples(m_avi_file, 0, sound + 0, numsamples, 1); if (avierr == AVIERR_NONE) - avierr = avi_append_sound_samples(m_avifile, 1, sound + 1, numsamples, 1); + avierr = avi_append_sound_samples(m_avi_file, 1, sound + 1, numsamples, 1); if (avierr != AVIERR_NONE) - end_recording(); + end_recording(MF_AVI); g_profiler.stop(); } @@ -505,7 +529,8 @@ void video_manager::add_sound_to_recording(const INT16 *sound, int numsamples) void video_manager::exit() { // stop recording any movie - end_recording(); + end_recording(MF_AVI); + end_recording(MF_MNG); // free the snapshot target machine().render().target_free(m_snap_target); @@ -541,7 +566,8 @@ void video_manager::screenless_update_callback(void *ptr, int param) void video_manager::postload() { - m_movie_next_frame_time = machine().time(); + m_avi_next_frame_time = machine().time(); + m_mng_next_frame_time = machine().time(); } @@ -1189,7 +1215,7 @@ file_error video_manager::open_next(emu_file &file, const char *extension) void video_manager::record_frame() { // ignore if nothing to do - if (m_mngfile == NULL && m_avifile == NULL) + if (m_mng_file == NULL && m_avi_file == NULL) return; // start the profiler and get the current time @@ -1199,27 +1225,36 @@ void video_manager::record_frame() // create the bitmap create_snapshot_bitmap(NULL); - // loop until we hit the right time - while (m_movie_next_frame_time <= curtime) + // handle an AVI recording + if (m_avi_file != NULL) { - // handle an AVI recording - if (m_avifile != NULL) + // loop until we hit the right time + while (m_avi_next_frame_time <= curtime) { // write the next frame - avi_error avierr = avi_append_video_frame(m_avifile, m_snap_bitmap); + avi_error avierr = avi_append_video_frame(m_avi_file, m_snap_bitmap); if (avierr != AVIERR_NONE) { g_profiler.stop(); - return end_recording(); + end_recording(MF_AVI); + break; } + + // advance time + m_avi_next_frame_time += m_avi_frame_period; + m_avi_frame++; } - - // handle a MNG recording - if (m_mngfile != NULL) + } + + // handle a MNG recording + if (m_mng_file != NULL) + { + // loop until we hit the right time + while (m_mng_next_frame_time <= curtime) { // set up the text fields in the movie info png_info pnginfo = { 0 }; - if (m_movie_frame == 0) + if (m_mng_frame == 0) { astring text1(emulator_info::get_appname(), " ", build_version); astring text2(machine().system().manufacturer, " ", machine().system().description); @@ -1230,19 +1265,21 @@ void video_manager::record_frame() // write the next frame const rgb_t *palette = (machine().first_screen() !=NULL && machine().first_screen()->palette() != NULL) ? machine().first_screen()->palette()->palette()->entry_list_adjusted() : NULL; int entries = (machine().first_screen() !=NULL && machine().first_screen()->palette() != NULL) ? machine().first_screen()->palette()->entries() : 0; - png_error error = mng_capture_frame(*m_mngfile, &pnginfo, m_snap_bitmap, entries, palette); + png_error error = mng_capture_frame(*m_mng_file, &pnginfo, m_snap_bitmap, entries, palette); png_free(&pnginfo); if (error != PNGERR_NONE) { g_profiler.stop(); - return end_recording(); + end_recording(MF_MNG); + break; } + + // advance time + m_mng_next_frame_time += m_mng_frame_period; + m_mng_frame++; } - - // advance time - m_movie_next_frame_time += m_movie_frame_period; - m_movie_frame++; } + g_profiler.stop(); } @@ -1264,12 +1301,12 @@ void video_manager::toggle_record_movie() { if (!is_recording()) { - begin_recording(NULL, video_manager::MF_MNG); + begin_recording(NULL, MF_MNG); popmessage("REC START"); } else { - end_recording(); + end_recording(MF_MNG); popmessage("REC STOP"); } } diff --git a/src/emu/video.h b/src/emu/video.h index c525f066b61..4e17c0db714 100644 --- a/src/emu/video.h +++ b/src/emu/video.h @@ -64,7 +64,7 @@ public: bool throttled() const { return m_throttled; } float throttle_rate() const { return m_throttle_rate; } bool fastforward() const { return m_fastforward; } - bool is_recording() const { return (m_mngfile != NULL || m_avifile != NULL); } + bool is_recording() const { return (m_mng_file != NULL || m_avi_file != NULL); } // setters void set_frameskip(int frameskip); @@ -89,8 +89,8 @@ public: void save_active_screen_snapshots(); // movies - void begin_recording(const char *name, movie_format format = MF_AVI); - void end_recording(); + void begin_recording(const char *name, movie_format format); + void end_recording(movie_format format); void add_sound_to_recording(const INT16 *sound, int numsamples); private: @@ -165,12 +165,17 @@ private: INT32 m_snap_width; // width of snapshots (0 == auto) INT32 m_snap_height; // height of snapshots (0 == auto) - // movie recording - auto_pointer m_mngfile; // handle to the open movie file - avi_file * m_avifile; // handle to the open movie file - attotime m_movie_frame_period; // period of a single movie frame - attotime m_movie_next_frame_time; // time of next frame - UINT32 m_movie_frame; // current movie frame number + // movie recording - MNG + auto_pointer m_mng_file; // handle to the open movie file + attotime m_mng_frame_period; // period of a single movie frame + attotime m_mng_next_frame_time; // time of next frame + UINT32 m_mng_frame; // current movie frame number + + // movie recording - AVI + avi_file * m_avi_file; // handle to the open movie file + attotime m_avi_frame_period; // period of a single movie frame + attotime m_avi_next_frame_time; // time of next frame + UINT32 m_avi_frame; // current movie frame number static const UINT8 s_skiptable[FRAMESKIP_LEVELS][FRAMESKIP_LEVELS];