From: K.Ohta Date: Wed, 10 Aug 2016 17:50:26 +0000 (+0900) Subject: [MOVIE_LOADER][PX7] Sound Laser Disc, but not be smooth. X-Git-Url: http://git.osdn.net/view?a=commitdiff_plain;h=494dc3c3e27a6a70066f297717caa37d9e8c87eb;p=csp-qt%2Fcommon_source_project-fm7.git [MOVIE_LOADER][PX7] Sound Laser Disc, but not be smooth. --- diff --git a/source/src/qt/avio/movie_loader.cpp b/source/src/qt/avio/movie_loader.cpp index 594b0ccf3..170c8f267 100644 --- a/source/src/qt/avio/movie_loader.cpp +++ b/source/src/qt/avio/movie_loader.cpp @@ -40,6 +40,8 @@ MOVIE_LOADER::MOVIE_LOADER(OSD *osd, config_t *cfg) : QObject(NULL) old_dst_width = dst_width; old_dst_height = dst_height; mod_frames = 0.0; + sound_rate = 44100; + req_transfer = true; #if defined(USE_LIBAV) fmt_ctx = NULL; video_dec_ctx = NULL; @@ -54,7 +56,6 @@ MOVIE_LOADER::MOVIE_LOADER(OSD *osd, config_t *cfg) : QObject(NULL) video_stream_idx = -1; audio_stream_idx = -1; frame = NULL; - tmp_frame = NULL; refcount = 0; #endif @@ -71,58 +72,50 @@ int MOVIE_LOADER::decode_packet(int *got_frame, int cached) { int ret = 0; int decoded = pkt.size; - + *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) { + 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) { + 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 * decode the following frames into another rawvideo file. */ AGAR_DebugLog(AGAR_LOG_INFO, "Error: Width, height and pixel format have to be " - "constant in a rawvideo file, but the width, height or " - "pixel format of the input video changed:\n" - "old: width = %d, height = %d, format = %s\n" - "new: width = %d, height = %d, format = %s\n", - src_width, src_height, av_get_pix_fmt_name(pix_fmt), - frame->width, frame->height, - av_get_pix_fmt_name(frame->format)); + "constant in a rawvideo file, but the width, height or " + "pixel format of the input video changed:\n" + "old: width = %d, height = %d, format = %s\n" + "new: width = %d, height = %d, format = %s\n", + src_width, src_height, av_get_pix_fmt_name(pix_fmt), + frame->width, frame->height, + av_get_pix_fmt_name(frame->format)); return -1; } if((old_dst_width != dst_width) || (old_dst_height != dst_height)) { // You sould allocate on opening. - if(tmp_frame != NULL) { - video_mutex->lock(); - av_frame_free(&tmp_frame); - tmp_frame = av_frame_alloc(); - if (tmp_frame == NULL) { - AGAR_DebugLog(AGAR_LOG_INFO, "MOVIE_LOADER: Could not re-allocate video frame\n"); - video_mutex->unlock(); - return -1; - } - tmp_frame->format = AV_PIX_FMT_BGRA; - tmp_frame->width = dst_width; - tmp_frame->height = dst_height; - ret = av_frame_get_buffer(tmp_frame, 32); //* - 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(); - return -1; - } + video_mutex->lock(); + for(int i = 0; i < 4; i++) av_free(video_dst_data[i]); + ret = av_image_alloc(video_dst_data, video_dst_linesize, + dst_width, dst_height, AV_PIX_FMT_BGRA, 1); + + if(ret < 0) { + AGAR_DebugLog(AGAR_LOG_INFO, "MOVIE_LOADER: Could not re-allocate output buffer\n"); + old_dst_width = dst_width; + old_dst_height = dst_height; video_mutex->unlock(); + return -1; } + old_dst_width = dst_width; + old_dst_height = dst_height; + video_mutex->unlock(); } - old_dst_width = dst_width; - old_dst_height = dst_height; char str_buf2[AV_TS_MAX_STRING_SIZE] = {0}; av_ts_make_time_string(str_buf2, frame->pts, &video_dec_ctx->time_base); @@ -147,20 +140,13 @@ 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); - //printf("%x %d\n", tmp_frame->data[0], tmp_frame->linesize[0]); - sws_scale(sws_context, - frame->data, frame->linesize, - 0, dst_height, video_dst_data, video_dst_linesize); - //tmp_frame->pts = tmp_frame->pts + 1; - video_mutex->unlock(); - } + video_mutex->lock(); + sws_scale(sws_context, + frame->data, frame->linesize, + 0, dst_height, video_dst_data, video_dst_linesize); + req_transfer = true; + video_mutex->unlock(); #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 */ @@ -180,6 +166,9 @@ int MOVIE_LOADER::decode_packet(int *got_frame, int cached) 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}; + AVCodecContext *c = audio_stream->codec; + int dst_nb_samples = av_rescale_rnd(swr_get_delay(swr_context, c->sample_rate) + frame->nb_samples, + c->sample_rate, c->sample_rate, AV_ROUND_UP); 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)" : "", @@ -196,14 +185,30 @@ int MOVIE_LOADER::decode_packet(int *got_frame, int cached) * 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; + px->data[0] = (uint8_t *)malloc((long)dst_nb_samples * 2 * sizeof(int16_t)); + px->data[1] = px->data[2] = px->data[3] = NULL; + if(px->data[0] == NULL) { + free(px); + AGAR_DebugLog(AGAR_LOG_INFO, "Error while converting\n"); + return -1; + } + ret = swr_convert(swr_context, + px->data, dst_nb_samples, + (const uint8_t **)frame->data, frame->nb_samples); + if (ret < 0) { + free(px->data[0]); + free(px); + AGAR_DebugLog(AGAR_LOG_INFO, "Error while converting\n"); + return -1; + } + px->unpadded_linesize = (long)dst_nb_samples * 2 * sizeof(int16_t); snd_write_lock->lock(); sound_data_queue.enqueue(px); snd_write_lock->unlock(); + } else { + AGAR_DebugLog(AGAR_LOG_INFO, "Error while converting\n"); + return -1; } - //fwrite(frame->extended_data[0], 1, unpadded_linesize, audio_dst_file); } } @@ -297,6 +302,7 @@ bool MOVIE_LOADER::open(QString filename) audio_frame_count = 0; video_frame_count = 0; mod_frames = 0.0; + req_transfer = true; /* register all formats and codecs */ av_register_all(); @@ -320,8 +326,9 @@ 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); + AVRational rate; + rate = av_stream_get_r_frame_rate(video_stream); + frame_rate = av_q2d(rate); if (ret < 0) { AGAR_DebugLog(AGAR_LOG_INFO, "Could not allocate raw video buffer\n"); goto _end; @@ -332,11 +339,30 @@ bool MOVIE_LOADER::open(QString filename) if (open_codec_context(&audio_stream_idx, fmt_ctx, AVMEDIA_TYPE_AUDIO) >= 0) { audio_stream = fmt_ctx->streams[audio_stream_idx]; audio_dec_ctx = audio_stream->codec; + sound_rate = audio_stream->codec->sample_rate; } + swr_context = swr_alloc(); + if(swr_context == NULL) { + AGAR_DebugLog(AGAR_LOG_INFO, "Could not allocate resampler context\n"); + goto _end; + } + av_opt_set_int (swr_context, "in_channel_count", audio_stream->codec->channels, 0); + av_opt_set_int (swr_context, "in_sample_rate", audio_stream->codec->sample_rate, 0); + av_opt_set_sample_fmt(swr_context, "in_sample_fmt", audio_stream->codec->sample_fmt, 0); + av_opt_set_int (swr_context, "out_channel_count", 2, 0); + av_opt_set_int (swr_context, "out_sample_rate", sound_rate, 0); + av_opt_set_sample_fmt(swr_context, "out_sample_fmt", AV_SAMPLE_FMT_S16, 0); + + /* initialize the resampling context */ + if ((ret = swr_init(swr_context)) < 0) { + AGAR_DebugLog(AGAR_LOG_INFO, "Failed to initialize the resampling context\n"); + goto _end; + } /* dump input information to stderr */ av_dump_format(fmt_ctx, 0, _filename.toLocal8Bit().constData(), 0); - + AGAR_DebugLog(AGAR_LOG_INFO, "Video is %f fps", frame_rate); + AGAR_DebugLog(AGAR_LOG_INFO, "Audio is %d Hz ", sound_rate); if (!audio_stream && !video_stream) { AGAR_DebugLog(AGAR_LOG_INFO, "Could not find audio or video stream in the input, aborting\n"); ret = 1; @@ -355,41 +381,14 @@ bool MOVIE_LOADER::open(QString filename) pkt.data = NULL; 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); - // } - - /* flush cached frames */ - pkt.data = NULL; - pkt.size = 0; - // Re-allocate buffer; video_mutex->lock(); - ret = av_image_alloc(video_dst_data, video_dst_linesize, + 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); //* + old_dst_width = dst_width; + old_dst_height = dst_height; 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; @@ -414,7 +413,7 @@ void MOVIE_LOADER::close(void) swr_free(&swr_context); video_mutex->lock(); - if(tmp_frame != NULL) av_frame_free(&tmp_frame); + req_transfer = true; 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]); @@ -491,11 +490,11 @@ void MOVIE_LOADER::do_decode_frames(int frames, int width, int height) int got_frame; bool end_of_frame = false; int real_frames = 0; - double d_frames = (double)frames * (p_osd->vm_frame_rate() / frame_rate); + double d_frames = (double)frames * (frame_rate /p_osd->vm_frame_rate()); mod_frames = mod_frames + d_frames; real_frames = (int)mod_frames; - mod_frames = fmod(mod_frames, 1.0); - real_frames = 1; + mod_frames = mod_frames - (double)real_frames; + if(width > 0) dst_width = width; if(height > 0) dst_height = height; @@ -504,6 +503,7 @@ void MOVIE_LOADER::do_decode_frames(int frames, int width, int height) //if(frames < 0) emit sig_decoding_error(MOVIE_LOADER_ILL_FRAME_NUMBER); return; } + if(!now_playing || now_pausing) { uint8_t *null_sound; double t; @@ -516,11 +516,11 @@ void MOVIE_LOADER::do_decode_frames(int frames, int width, int height) emit sig_send_audio_frame(null_sound, l); } if(!now_pausing) { - if(tmp_frame != NULL) { + if(video_dst_data[0] != NULL) { uint32_t q; video_mutex->lock(); for(int yy = 0; yy < dst_height; yy++) { - q = (uint32_t *)(&(tmp_frame->data[0][yy * tmp_frame->linesize[0]])); + q = (uint32_t *)(&(video_dst_data[0][yy * video_dst_linesize[0]])); if((q != NULL) && (dst_width != 0)) { memset(q, 0x00, dst_width * sizeof(uint32_t)); } @@ -528,7 +528,6 @@ 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++) { @@ -557,12 +556,12 @@ void MOVIE_LOADER::get_video_frame() int xx; p_osd->screen_mutex->lock(); - if(tmp_frame != NULL) { - video_mutex->lock(); + video_mutex->lock(); + if(req_transfer) { + req_transfer = false; for(int yy = 0; yy < dst_height; yy++) { 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;) { @@ -618,8 +617,8 @@ void MOVIE_LOADER::get_video_frame() #endif } video_mutex->unlock(); + p_osd->screen_mutex->unlock(); } - p_osd->screen_mutex->unlock(); } void MOVIE_LOADER::do_seek_frame(bool relative, int frames) @@ -651,14 +650,14 @@ void MOVIE_LOADER::do_dequeue_audio() for(ii = 0; ii < il; ii++) { tmpq = sound_data_queue.dequeue(); if(tmpq != NULL) { - if(tmpq->data != NULL) { + if(tmpq->data[0] != NULL) { if((tmpq->unpadded_linesize != 0) && (dptr < audio_data_size)) { if(tmpdata != NULL) { - memcpy(&tmpdata[dptr], tmpq->data, tmpq->unpadded_linesize); + memcpy(&tmpdata[dptr], tmpq->data[0], tmpq->unpadded_linesize); } dptr += tmpq->unpadded_linesize; } - free(tmpq->data); + free(tmpq->data[0]); } free(tmpq); } @@ -666,7 +665,9 @@ void MOVIE_LOADER::do_dequeue_audio() } snd_write_lock->unlock(); if((tmpdata != NULL) && (dptr != 0)) { - emit sig_send_audio_frame(tmpdata,dptr); // Please free arg1 after calling sound_callback of vm. + //emit sig_send_audio_frame(tmpdata,dptr); // Please free arg1 after calling sound_callback of vm. + //if(p_osd != NULL) p_osd->do_run_movie_audio_callback(tmpdata, dptr / (sizeof(int16_t) * 2)); + if(p_osd != NULL) p_osd->do_run_movie_audio_callback(tmpdata, dptr); } } diff --git a/source/src/qt/avio/movie_loader.h b/source/src/qt/avio/movie_loader.h index 0376342cc..1e353e70b 100644 --- a/source/src/qt/avio/movie_loader.h +++ b/source/src/qt/avio/movie_loader.h @@ -37,7 +37,7 @@ extern "C" { #include "config.h" typedef struct { - uint8_t *data; + uint8_t *data[4]; long unpadded_linesize; } sound_data_queue_t; @@ -49,7 +49,7 @@ class MOVIE_LOADER: public QObject { Q_OBJECT private: - + bool req_transfer; #if defined(USE_LIBAV) AVFormatContext *fmt_ctx; // = NULL; AVCodecContext *video_dec_ctx;// = NULL @@ -61,7 +61,6 @@ private: int video_dst_bufsize; int video_stream_idx, audio_stream_idx; //int video_stream_idx = -1, audio_stream_idx = -1; AVFrame *frame; //AVFrame *frame = NULL; - AVFrame *tmp_frame; //AVFrame *tmp_frame = NULL; AVPacket pkt; struct SwsContext *sws_context; struct SwrContext *swr_context; diff --git a/source/src/qt/osd.h b/source/src/qt/osd.h index b328db7d5..224980bd3 100644 --- a/source/src/qt/osd.h +++ b/source/src/qt/osd.h @@ -84,6 +84,7 @@ public: bool open_movie_file(const _TCHAR* file_path); void close_movie_file(); uint32_t get_cur_movie_frame(); + int get_movie_sound_rate(); public slots: void do_decode_movie(int frames); diff --git a/source/src/qt/osd_base.h b/source/src/qt/osd_base.h index 62188c3c7..0927733bd 100644 --- a/source/src/qt/osd_base.h +++ b/source/src/qt/osd_base.h @@ -354,7 +354,7 @@ public: void stop_movie(); void pause_movie(); double get_movie_frame_rate(); - int get_movie_sound_rate(); + virtual int get_movie_sound_rate(); void set_cur_movie_frame(int frame, bool relative); uint32_t get_cur_movie_frame(); bool now_movie_play, now_movie_pause; diff --git a/source/src/qt/osd_sound.cpp b/source/src/qt/osd_sound.cpp index 131edfe48..4d2b02997 100644 --- a/source/src/qt/osd_sound.cpp +++ b/source/src/qt/osd_sound.cpp @@ -173,8 +173,10 @@ void OSD_BASE::release_sound() #endif if(snd_apply_sem != NULL) { SDL_DestroySemaphore(snd_apply_sem); + snd_apply_sem = NULL; } if(sound_buf_ptr != NULL) free(sound_buf_ptr); + sound_buf_ptr = NULL; // stop recording stop_record_sound(); } diff --git a/source/src/qt/osd_video.cpp b/source/src/qt/osd_video.cpp index da34bda5b..4f327f063 100644 --- a/source/src/qt/osd_video.cpp +++ b/source/src/qt/osd_video.cpp @@ -51,7 +51,6 @@ 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 9494e7eb7..56bf1141d 100644 --- a/source/src/qt/osd_wrapper.cpp +++ b/source/src/qt/osd_wrapper.cpp @@ -346,7 +346,7 @@ 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_t *, long))); + //connect(movie_loader, SIGNAL(sig_send_audio_frame(uint8_t *, long)), this, SLOT(do_run_movie_audio_callback2(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())); @@ -436,3 +436,10 @@ void OSD::get_video_buffer() #endif } + +int OSD::get_movie_sound_rate() +{ +#if defined(USE_MOVIE_PLAYER) || defined(USE_VIDEO_CAPTURE) + return movie_loader->get_movie_sound_rate(); +#endif +}