From e511bcd1b28597c52940a07bcc3fd59f069f2292 Mon Sep 17 00:00:00 2001 From: "K.Ohta" Date: Wed, 10 Aug 2016 22:44:23 +0900 Subject: [PATCH] [MOVIE_LOADER] Primary decoding. --- source/src/qt/avio/movie_loader.cpp | 214 ++++++++++++++++++++++-------------- source/src/qt/avio/movie_loader.h | 4 +- source/src/qt/common/emu_thread.cpp | 12 +- source/src/qt/common/emu_thread.h | 4 +- source/src/qt/common/qt_utils.cpp | 2 +- source/src/qt/osd_video.cpp | 2 + source/src/qt/osd_wrapper.cpp | 11 +- 7 files changed, 151 insertions(+), 98 deletions(-) diff --git a/source/src/qt/avio/movie_loader.cpp b/source/src/qt/avio/movie_loader.cpp index eb0dceb8f..594b0ccf3 100644 --- a/source/src/qt/avio/movie_loader.cpp +++ b/source/src/qt/avio/movie_loader.cpp @@ -49,6 +49,7 @@ MOVIE_LOADER::MOVIE_LOADER(OSD *osd, config_t *cfg) : QObject(NULL) video_stream = NULL; audio_stream = NULL; for(int i = 0; i < 4; i++) video_dst_data[i] = NULL; + for(int i = 0; i < 4; i++) video_dst_linesize[i] = 0; video_dst_bufsize = 0; video_stream_idx = -1; audio_stream_idx = -1; @@ -68,22 +69,21 @@ MOVIE_LOADER::~MOVIE_LOADER() #if defined(USE_LIBAV) int MOVIE_LOADER::decode_packet(int *got_frame, int cached) { - int ret = 0; - int decoded = pkt.size; + int ret = 0; + int decoded = pkt.size; - *got_frame = 0; + *got_frame = 0; - if (pkt.stream_index == video_stream_idx) { - /* decode video frame */ - ret = avcodec_decode_video2(video_dec_ctx, frame, got_frame, &pkt); - if (ret < 0) { + if (pkt.stream_index == video_stream_idx) { + /* decode video frame */ + ret = avcodec_decode_video2(video_dec_ctx, frame, got_frame, &pkt); + if (ret < 0) { char str_buf[AV_ERROR_MAX_STRING_SIZE] = {0}; av_make_error_string(str_buf, AV_ERROR_MAX_STRING_SIZE, ret); - AGAR_DebugLog(AGAR_LOG_INFO, "Error decoding video frame (%s)\n", str_buf); - return ret; - } - - if (*got_frame) { + AGAR_DebugLog(AGAR_LOG_INFO, "Error decoding video frame (%s)\n", str_buf); + return ret; + } + if (*got_frame) { if (frame->width != src_width || frame->height != src_height || frame->format != pix_fmt) { /* To handle this change, one could call av_image_alloc again and @@ -126,22 +126,19 @@ int MOVIE_LOADER::decode_packet(int *got_frame, int cached) char str_buf2[AV_TS_MAX_STRING_SIZE] = {0}; av_ts_make_time_string(str_buf2, frame->pts, &video_dec_ctx->time_base); - AGAR_DebugLog(AGAR_LOG_DEBUG, "video_frame%s n:%d coded_n:%d pts:%s\n", - cached ? "(cached)" : "", - video_frame_count++, frame->coded_picture_number, - str_buf2); + //AGAR_DebugLog(AGAR_LOG_DEBUG, "video_frame%s n:%d coded_n:%d pts:%s\n", + // cached ? "(cached)" : "", + // video_frame_count++, frame->coded_picture_number, + // str_buf2); /* copy decoded frame to destination buffer: * this is required since rawvideo expects non aligned data */ - //av_image_copy(video_dst_data, video_dst_linesize, - // (const uint8_t **)(frame->data), frame->linesize, - // pix_fmt, src_width, src_height); - +#if 1 if(sws_context == NULL) { sws_context = sws_getContext(frame->width, frame->height, - AV_PIX_FMT_BGRA, + frame->format, dst_width, dst_height, - pix_fmt, + AV_PIX_FMT_BGRA, SCALE_FLAGS, NULL, NULL, NULL); if (sws_context == NULL) { AGAR_DebugLog(AGAR_LOG_INFO, @@ -152,59 +149,65 @@ int MOVIE_LOADER::decode_packet(int *got_frame, int cached) } if(tmp_frame != NULL) { // You must pull final frame (and need locking?) before emit sig_decode_frames_complete(). video_mutex->lock(); - ret = av_frame_make_writable(tmp_frame); + ///ret = av_frame_make_writable(tmp_frame); + //printf("%x %d\n", tmp_frame->data[0], tmp_frame->linesize[0]); sws_scale(sws_context, frame->data, frame->linesize, - 0, dst_height, tmp_frame->data, tmp_frame->linesize); + 0, dst_height, video_dst_data, video_dst_linesize); + //tmp_frame->pts = tmp_frame->pts + 1; video_mutex->unlock(); } - - } else if (pkt.stream_index == audio_stream_idx) { - /* decode audio frame */ - ret = avcodec_decode_audio4(audio_dec_ctx, frame, got_frame, &pkt); - if (ret < 0) { - char str_buf[AV_ERROR_MAX_STRING_SIZE] = {0}; - av_make_error_string(str_buf, AV_ERROR_MAX_STRING_SIZE, ret); - AGAR_DebugLog(AGAR_LOG_INFO, "Error decoding audio frame (%s)\n", str_buf); - return ret; - } - /* Some audio decoders decode only part of the packet, and have to be - * called again with the remainder of the packet data. - * Sample: fate-suite/lossless-audio/luckynight-partial.shn - * Also, some decoders might over-read the packet. */ - decoded = FFMIN(ret, pkt.size); +#endif + //av_image_copy(video_dst_data, video_dst_linesize, + // (const uint8_t **)(tmp_frame->data), tmp_frame->linesize, + // pix_fmt, dst_width, dst_height); + } + } else if (pkt.stream_index == audio_stream_idx) { + /* decode audio frame */ + ret = avcodec_decode_audio4(audio_dec_ctx, frame, got_frame, &pkt); + if (ret < 0) { + char str_buf[AV_ERROR_MAX_STRING_SIZE] = {0}; + av_make_error_string(str_buf, AV_ERROR_MAX_STRING_SIZE, ret); + AGAR_DebugLog(AGAR_LOG_INFO, "Error decoding audio frame (%s)\n", str_buf); + return ret; + } + /* Some audio decoders decode only part of the packet, and have to be + * called again with the remainder of the packet data. + * Sample: fate-suite/lossless-audio/luckynight-partial.shn + * Also, some decoders might over-read the packet. */ + decoded = FFMIN(ret, pkt.size); - if (*got_frame) { - size_t unpadded_linesize = frame->nb_samples * av_get_bytes_per_sample(frame->format); - char str_buf[AV_TS_MAX_STRING_SIZE] = {0}; - av_ts_make_time_string(str_buf, frame->pts, &audio_dec_ctx->time_base); - AGAR_DebugLog(AGAR_LOG_DEBUG,"audio_frame%s n:%d nb_samples:%d pts:%s\n", - cached ? "(cached)" : "", - audio_frame_count++, frame->nb_samples, - str_buf); - - /* Write the raw audio data samples of the first plane. This works - * fine for packed formats (e.g. AV_SAMPLE_FMT_S16). However, - * most audio decoders output planar audio, which uses a separate - * plane of audio samples for each channel (e.g. AV_SAMPLE_FMT_S16P). - * In other words, this code will write only the first audio channel - * in these cases. - * You should use libswresample or libavfilter to convert the frame - * to packed data. */ - sound_data_queue_t *px = (sound_data_queue_t *)malloc(sizeof(sound_data_queue_t)); - if(px != NULL) { - px->data = (uint8_t *)malloc((long)unpadded_linesize); - memcpy(px->data, (uint8_t *)(frame->extended_data[0]), (long)unpadded_linesize); // post tmp-buffer. - px->unpadded_linesize = (long)unpadded_linesize; - snd_write_lock->lock(); - sound_data_queue.enqueue(px); - snd_write_lock->unlock(); - } - //fwrite(frame->extended_data[0], 1, unpadded_linesize, audio_dst_file); + if (*got_frame) { + size_t unpadded_linesize = frame->nb_samples * av_get_bytes_per_sample(frame->format); + char str_buf[AV_TS_MAX_STRING_SIZE] = {0}; + av_ts_make_time_string(str_buf, frame->pts, &audio_dec_ctx->time_base); + //AGAR_DebugLog(AGAR_LOG_DEBUG,"audio_frame%s n:%d nb_samples:%d pts:%s\n", + // cached ? "(cached)" : "", + // audio_frame_count++, frame->nb_samples, + // str_buf); + + /* Write the raw audio data samples of the first plane. This works + * fine for packed formats (e.g. AV_SAMPLE_FMT_S16). However, + * most audio decoders output planar audio, which uses a separate + * plane of audio samples for each channel (e.g. AV_SAMPLE_FMT_S16P). + * In other words, this code will write only the first audio channel + * in these cases. + * You should use libswresample or libavfilter to convert the frame + * to packed data. */ + sound_data_queue_t *px = (sound_data_queue_t *)malloc(sizeof(sound_data_queue_t)); + if(px != NULL) { + px->data = (uint8_t *)malloc((long)unpadded_linesize); + memcpy(px->data, (uint8_t *)(frame->extended_data[0]), (long)unpadded_linesize); // post tmp-buffer. + px->unpadded_linesize = (long)unpadded_linesize; + snd_write_lock->lock(); + sound_data_queue.enqueue(px); + snd_write_lock->unlock(); } + //fwrite(frame->extended_data[0], 1, unpadded_linesize, audio_dst_file); } } + /* If we use frame reference counting, we own the data and need * to de-reference it when we don't use it anymore */ if (*got_frame && refcount) @@ -317,8 +320,8 @@ bool MOVIE_LOADER::open(QString filename) src_width = video_dec_ctx->width; src_height = video_dec_ctx->height; pix_fmt = video_dec_ctx->pix_fmt; - ret = av_image_alloc(video_dst_data, video_dst_linesize, - src_width, src_height, pix_fmt, 1); + //ret = av_image_alloc(video_dst_data, video_dst_linesize, + // src_width, src_height, pix_fmt, 1); if (ret < 0) { AGAR_DebugLog(AGAR_LOG_INFO, "Could not allocate raw video buffer\n"); goto _end; @@ -353,17 +356,17 @@ bool MOVIE_LOADER::open(QString filename) pkt.size = 0; /* read frames from the file */ - while (av_read_frame(fmt_ctx, &pkt) >= 0) { - AVPacket orig_pkt = pkt; - do { - ret = decode_packet(&got_frame, 0); - if (ret < 0) - break; - pkt.data += ret; - pkt.size -= ret; - } while (pkt.size > 0); - av_packet_unref(&orig_pkt); - } + //while (av_read_frame(fmt_ctx, &pkt) >= 0) { + // AVPacket orig_pkt = pkt; + // do { + // ret = decode_packet(&got_frame, 0); + // if (ret < 0) + // break; + // pkt.data += ret; + // pkt.size -= ret; + // } while (pkt.size > 0); + // av_packet_unref(&orig_pkt); + // } /* flush cached frames */ pkt.data = NULL; @@ -371,27 +374,33 @@ bool MOVIE_LOADER::open(QString filename) // Re-allocate buffer; video_mutex->lock(); + ret = av_image_alloc(video_dst_data, video_dst_linesize, + dst_width, dst_height, AV_PIX_FMT_BGRA, 1); tmp_frame = av_frame_alloc(); if (tmp_frame == NULL) { AGAR_DebugLog(AGAR_LOG_INFO, "MOVIE_LOADER: Could not allocate output frame\n"); + video_mutex->unlock(); goto _end; } tmp_frame->format = AV_PIX_FMT_BGRA; tmp_frame->width = dst_width; tmp_frame->height = dst_height; + printf("%d %d\n", dst_width, dst_height); ret = av_frame_get_buffer(tmp_frame, 32); //* video_mutex->unlock(); if(ret < 0) { av_frame_free(&tmp_frame); AGAR_DebugLog(AGAR_LOG_INFO, "MOVIE_LOADER: Could not re-allocate output buffer\n"); + //video_mutex->unlock(); goto _end; } // ToDo : Initialize SWScaler and SWresampler. + AGAR_DebugLog(AGAR_LOG_INFO, "MOVIE_LOADER: Loading movie completed.\n"); return true; _end: this->close(); - return false; + return false; } void MOVIE_LOADER::close(void) @@ -406,6 +415,12 @@ void MOVIE_LOADER::close(void) video_mutex->lock(); if(tmp_frame != NULL) av_frame_free(&tmp_frame); + if(frame != NULL) av_frame_free(&frame); + for(int i = 0; i < 4; i++) { + if(video_dst_data[i] != NULL) av_free(video_dst_data[i]); + video_dst_data[i] = NULL; + video_dst_linesize[i] = 0; + } video_mutex->unlock(); video_dec_ctx = NULL; @@ -415,6 +430,7 @@ void MOVIE_LOADER::close(void) now_playing = false; now_pausing = false; + AGAR_DebugLog(AGAR_LOG_INFO, "MOVIE_LOADER: Close movie."); } double MOVIE_LOADER::get_movie_frame_rate(void) @@ -479,7 +495,7 @@ void MOVIE_LOADER::do_decode_frames(int frames, int width, int height) mod_frames = mod_frames + d_frames; real_frames = (int)mod_frames; mod_frames = fmod(mod_frames, 1.0); - + real_frames = 1; if(width > 0) dst_width = width; if(height > 0) dst_height = height; @@ -512,15 +528,17 @@ void MOVIE_LOADER::do_decode_frames(int frames, int width, int height) video_mutex->unlock(); } } + //printf("##\n"); return; } - for(int i = 0; i < real_frames; i++) { - decode_packet(&got_frame, 1); + for(int i = 0; i < real_frames; i++) { + av_read_frame(fmt_ctx, &pkt); + decode_packet(&got_frame, 0); if(got_frame == 0) { end_of_frame = true; break; } - } + } if(end_of_frame) { // if real_frames > 1 then clear screen ? do_dequeue_audio(); @@ -542,8 +560,10 @@ void MOVIE_LOADER::get_video_frame() if(tmp_frame != NULL) { video_mutex->lock(); for(int yy = 0; yy < dst_height; yy++) { - p = (uint32_t *)(&(tmp_frame->data[0][yy * tmp_frame->linesize[0]])); q = (uint32_t *)(p_osd->get_vm_screen_buffer(yy)); +#if 1 + //p = (uint32_t *)(&(tmp_frame->data[0][yy * tmp_frame->linesize[0]])); + p = (uint32_t *)(&(video_dst_data[0][yy * video_dst_linesize[0]])); if((p == NULL) || (q == NULL)) break; for(xx = dst_width; xx > 7;) { cacheline[0] = p[0]; @@ -572,6 +592,30 @@ void MOVIE_LOADER::get_video_frame() for(; xx > 0; xx--) { *q++ = *p++; } +#else + //uint32_t col = 0xff000000 | (yy & 1) ? 0x00000000 : 0x00ff0000 | (yy & 2) ? 0x00000000 : 0x0000ff00 | (yy & 4) ? 0x00000000 : 0x000000ff; + uint32_t col = 0xffffffff; + if(q == NULL) break; + for(xx = dst_width; xx > 7;) { + + q[0] = col; + q[1] = col; + q[2] = col; + q[3] = col; + q[4] = col; + q[5] = col; + q[6] = col; + q[7] = col; + + p += 8; + q += 8; + xx -= 8; + if(xx < 8) break; + } + for(; xx > 0; xx--) { + *q++ = *p++; + } +#endif } video_mutex->unlock(); } diff --git a/source/src/qt/avio/movie_loader.h b/source/src/qt/avio/movie_loader.h index 6b655f3f2..0376342cc 100644 --- a/source/src/qt/avio/movie_loader.h +++ b/source/src/qt/avio/movie_loader.h @@ -26,8 +26,8 @@ extern "C" { // Copy from FFMPEG-3.0.2; doc/example/muxing.c . #define STREAM_PIX_FMT AV_PIX_FMT_RGBA /* default pix_fmt */ -//#define SCALE_FLAGS SWS_BICUBLIN -#define SCALE_FLAGS SWS_POINT +#define SCALE_FLAGS SWS_BICUBLIN +//#define SCALE_FLAGS SWS_POINT #include #include diff --git a/source/src/qt/common/emu_thread.cpp b/source/src/qt/common/emu_thread.cpp index c5548a3c6..d452f688c 100644 --- a/source/src/qt/common/emu_thread.cpp +++ b/source/src/qt/common/emu_thread.cpp @@ -876,17 +876,17 @@ void EmuThreadClass::do_open_cart(int drv, QString path) } -void EmuThreadClass::do_close_laser_disk(void) +void EmuThreadClass::do_close_laser_disc(void) { -#ifdef USE_LASER_DISK - p_emu->close_laser_disk(); +#ifdef USE_LASER_DISC + p_emu->close_laser_disc(); #endif } -void EmuThreadClass::do_open_laser_disk(QString path) +void EmuThreadClass::do_open_laser_disc(QString path) { -#ifdef USE_LASER_DISK - p_emu->open_laser_disk(path.toLocal8Bit().constData()); +#ifdef USE_LASER_DISC + p_emu->open_laser_disc(path.toLocal8Bit().constData()); #endif } diff --git a/source/src/qt/common/emu_thread.h b/source/src/qt/common/emu_thread.h index b12df7840..b4accbbeb 100644 --- a/source/src/qt/common/emu_thread.h +++ b/source/src/qt/common/emu_thread.h @@ -146,8 +146,8 @@ public slots: void do_open_quickdisk(int drv, QString path); void do_close_cart(int drv); void do_open_cart(int drv, QString path); - void do_close_laser_disk(void); - void do_open_laser_disk(QString path); + void do_close_laser_disc(void); + void do_open_laser_disc(QString path); void do_eject_cdrom(void); void do_open_cdrom(QString path); void do_load_binary(int drv, QString path); diff --git a/source/src/qt/common/qt_utils.cpp b/source/src/qt/common/qt_utils.cpp index 6c2d3edbf..0ae185a3e 100644 --- a/source/src/qt/common/qt_utils.cpp +++ b/source/src/qt/common/qt_utils.cpp @@ -216,7 +216,7 @@ void Ui_MainWindow::LaunchEmuThread(void) connect(this, SIGNAL(sig_close_cdrom()), hRunEmu, SLOT(do_eject_cdrom())); connect(hRunEmu, SIGNAL(sig_change_osd_cdrom(QString)), this, SLOT(do_change_osd_cdrom(QString))); #endif -#if defined(USE_LASER_DISK) +#if defined(USE_LASER_DISC) connect(this, SIGNAL(sig_open_laserdisc(QString)), hRunEmu, SLOT(do_open_laser_disc(QString))); connect(this, SIGNAL(sig_close_laserdisc(void)), hRunEmu, SLOT(do_close_laser_disc(void))); #endif diff --git a/source/src/qt/osd_video.cpp b/source/src/qt/osd_video.cpp index 5d6e45d12..da34bda5b 100644 --- a/source/src/qt/osd_video.cpp +++ b/source/src/qt/osd_video.cpp @@ -27,6 +27,7 @@ void OSD_BASE::release_video() void OSD_BASE::get_video_buffer() { + } void OSD_BASE::mute_video_dev(bool l, bool r) @@ -50,6 +51,7 @@ void OSD_BASE::play_movie() { now_movie_play = true; now_movie_pause = false; + printf("@@\n"); emit sig_movie_play(); } diff --git a/source/src/qt/osd_wrapper.cpp b/source/src/qt/osd_wrapper.cpp index 25d980084..9494e7eb7 100644 --- a/source/src/qt/osd_wrapper.cpp +++ b/source/src/qt/osd_wrapper.cpp @@ -346,8 +346,13 @@ void OSD::initialize_video() movie_loader = NULL; #if defined(USE_MOVIE_PLAYER) || defined(USE_VIDEO_CAPTURE) movie_loader = new MOVIE_LOADER(this, &config); - connect(movie_loader, SIGNAL(sig_send_audio_frame(uint8_t *, long)), this, SLOT(do_run_movie_audio_callback(uint8 *, long))); + connect(movie_loader, SIGNAL(sig_send_audio_frame(uint8_t *, long)), this, SLOT(do_run_movie_audio_callback(uint8_t *, long))); connect(movie_loader, SIGNAL(sig_movie_end(bool)), this, SLOT(do_video_movie_end(bool))); + connect(this, SIGNAL(sig_movie_play(void)), movie_loader, SLOT(do_play())); + connect(this, SIGNAL(sig_movie_stop(void)), movie_loader, SLOT(do_stop())); + connect(this, SIGNAL(sig_movie_pause(bool)), movie_loader, SLOT(do_pause(bool))); + connect(this, SIGNAL(sig_movie_seek_frame(bool, int)), movie_loader, SLOT(do_seek_frame(bool, int))); + //connect(this, SIGNAL(sig_movie_mute(bool, bool)), movie_loader, SLOT(do_mute(bool, bool))); connect(movie_loader, SIGNAL(sig_decoding_error(int)), this, SLOT(do_video_decoding_error(int))); #endif } @@ -424,8 +429,10 @@ void OSD::do_decode_movie(int frames) void OSD::get_video_buffer() { -#if defined(_PX7) +#if defined(USE_MOVIE_PLAYER) || defined(USE_VIDEO_CAPTURE) + //movie_loader->do_decode_frames(1, this->get_vm_window_width(), this->get_vm_window_height()); movie_loader->get_video_frame(); + //printf("**\n"); #endif } -- 2.11.0