/*------------------------------------------------------------------------------ | OMX_VideoProcessor::cleanup +-----------------------------------------------------------------------------*/ void OMX_MediaProcessor::cleanup() { LOG_INFORMATION(LOG_TAG, "Cleaning up..."); #if 0 if (m_refresh) { m_BcmHost.vc_tv_hdmi_power_on_best( tv_state.width, tv_state.height, tv_state.frame_rate, HDMI_NONINTERLACED, (EDID_MODE_MATCH_FLAG_T)(HDMI_MODE_MATCH_FRAMERATE| HDMI_MODE_MATCH_RESOLUTION|HDMI_MODE_MATCH_SCANMODE) ); } #endif LOG_VERBOSE(LOG_TAG, "Closing players..."); #ifdef ENABLE_SUBTITLES m_player_subtitles->Close(); #endif m_player_video->Close(); m_player_audio->Close(); if (m_omx_pkt) { m_omx_reader->FreePacket(m_omx_pkt); m_omx_pkt = NULL; } LOG_VERBOSE(LOG_TAG, "Closing players..."); m_omx_reader->Close(); m_metadata.clear(); emit metadataChanged(m_metadata); vc_tv_show_info(0); // lcarlon: free the texture. Invoke freeTexture so that it is the user // of the class to do it cause it is commonly required to do it in the // current OpenGL and EGL context. Do it here, after the stop command is // considered finished: this is needed to avoid hardlock in case the // used wants to free the texture in his own thread, which would still // be blocked waiting for the stop command to finish. LOG_VERBOSE(LOG_TAG, "Freeing texture..."); m_provider->freeTexture(m_textureData); m_textureData = NULL; emit textureInvalidated(); LOG_INFORMATION(LOG_TAG, "Cleanup done."); }
static int show_info( int on ) { return vc_tv_show_info(on); }
int main(int argc, char *argv[]) { struct termios new_termios; tcgetattr(STDIN_FILENO, &orig_termios); new_termios = orig_termios; new_termios.c_lflag &= ~(ICANON | ECHO | ECHOCTL | ECHONL); new_termios.c_cflag |= HUPCL; new_termios.c_cc[VMIN] = 0; CStdString last_sub = ""; tcsetattr(STDIN_FILENO, TCSANOW, &new_termios); on_exit(restore_termios, &orig_termios); CStdString m_filename; double m_incr = 0; CRBP g_RBP; COMXCore g_OMX; bool m_stats = false; bool m_dump_format = false; bool m_3d = false; bool m_refresh = false; double startpts = 0; TV_GET_STATE_RESP_T tv_state; struct option longopts[] = { { "info", no_argument, NULL, 'i' }, { "help", no_argument, NULL, 'h' }, { "aidx", required_argument, NULL, 'n' }, { "adev", required_argument, NULL, 'o' }, { "stats", no_argument, NULL, 's' }, { "passthrough", no_argument, NULL, 'p' }, { "deinterlace", no_argument, NULL, 'd' }, { "hw", no_argument, NULL, 'w' }, { "3d", no_argument, NULL, '3' }, { "hdmiclocksync", no_argument, NULL, 'y' }, { "refresh", no_argument, NULL, 'r' }, { "sid", required_argument, NULL, 't' }, { 0, 0, 0, 0 } }; int c; while ((c = getopt_long(argc, argv, "wihn:o:cslpd3yt:r", longopts, NULL)) != -1) { switch (c) { case 'r': m_refresh = true; break; case 'y': m_hdmi_clock_sync = true; break; case '3': m_3d = true; break; case 'd': m_Deinterlace = true; break; case 'w': m_use_hw_audio = true; break; case 'p': m_passthrough = true; break; case 's': m_stats = true; break; case 'o': deviceString = optarg; if(deviceString != CStdString("local") && deviceString != CStdString("hdmi")) { print_usage(); return 0; } deviceString = "omx:" + deviceString; break; case 'i': m_dump_format = true; break; case 't': m_subtitle_index = atoi(optarg) - 1; if(m_subtitle_index < 0) m_subtitle_index = 0; m_show_subtitle = true; break; case 'n': m_audio_index_use = atoi(optarg) - 1; if(m_audio_index_use < 0) m_audio_index_use = 0; break; case 0: break; case 'h': print_usage(); return 0; break; case ':': return 0; break; default: return 0; break; } } if (optind >= argc) { print_usage(); return 0; } m_filename = argv[optind]; CLog::Init("./"); g_RBP.Initialize(); g_OMX.Initialize(); m_av_clock = new OMXClock(); m_thread_player = true; if(!m_omx_reader.Open(m_filename.c_str(), m_dump_format)) goto do_exit; if(m_dump_format) goto do_exit; m_bMpeg = m_omx_reader.IsMpegVideo(); m_has_video = m_omx_reader.VideoStreamCount(); m_has_audio = m_omx_reader.AudioStreamCount(); m_has_subtitle = m_omx_reader.SubtitleStreamCount(); if(!m_av_clock->OMXInitialize(m_has_video, m_has_audio)) goto do_exit; if(m_hdmi_clock_sync && !m_av_clock->HDMIClockSync()) goto do_exit; m_omx_reader.GetHints(OMXSTREAM_AUDIO, m_hints_audio); m_omx_reader.GetHints(OMXSTREAM_VIDEO, m_hints_video); if(m_audio_index_use != -1) m_omx_reader.SetActiveStream(OMXSTREAM_AUDIO, m_audio_index_use); if(m_has_video && !m_player_video.Open(m_hints_video, m_av_clock, m_Deinterlace, m_bMpeg, m_hdmi_clock_sync, m_thread_player)) goto do_exit; if(m_has_video && m_refresh) { memset(&tv_state, 0, sizeof(TV_GET_STATE_RESP_T)); m_BcmHost.vc_tv_get_state(&tv_state); if(m_filename.find("3DSBS") != string::npos) m_3d = true; SetVideoMode(m_hints_video.width, m_hints_video.height, m_player_video.GetFPS(), m_3d); } // This is an upper bound check on the subtitle limits. When we pulled the subtitle // index from the user we check to make sure that the value is larger than zero, but // we couldn't know without scanning the file if it was too high. If this is the case // then we replace the subtitle index with the maximum value possible. if(m_has_subtitle && m_subtitle_index > (m_omx_reader.SubtitleStreamCount() - 1)) { m_subtitle_index = m_omx_reader.SubtitleStreamCount() - 1; } // Here we actually enable the subtitle streams if we have one available. if (m_has_subtitle && m_subtitle_index <= (m_omx_reader.SubtitleStreamCount() - 1)) { m_omx_reader.SetActiveStream(OMXSTREAM_SUBTITLE, m_subtitle_index); m_show_subtitle = true; } else { m_show_subtitle = false; } m_omx_reader.GetHints(OMXSTREAM_AUDIO, m_hints_audio); if(m_has_audio && !m_player_audio.Open(m_hints_audio, m_av_clock, &m_omx_reader, deviceString, m_passthrough, m_use_hw_audio, m_thread_player)) goto do_exit; m_av_clock->SetSpeed(DVD_PLAYSPEED_NORMAL); m_av_clock->OMXStateExecute(); m_av_clock->OMXStart(); struct timespec starttime, endtime; while(!m_stop) { int ch[8]; int chnum = 0; if(g_abort) goto do_exit; while((ch[chnum] = getchar()) != EOF) chnum++; if (chnum > 1) ch[0] = ch[chnum - 1] | (ch[chnum - 2] << 8); switch(ch[0]) { case 'z': m_tv_show_info = !m_tv_show_info; vc_tv_show_info(m_tv_show_info); break; case '1': SetSpeed(m_av_clock->OMXPlaySpeed() - 1); break; case '2': SetSpeed(m_av_clock->OMXPlaySpeed() + 1); break; case 'j': m_omx_reader.SetActiveStream(OMXSTREAM_AUDIO, m_omx_reader.GetAudioIndex() - 1); break; case 'k': m_omx_reader.SetActiveStream(OMXSTREAM_AUDIO, m_omx_reader.GetAudioIndex() + 1); break; case 'i': if(m_omx_reader.GetChapterCount() > 0) { m_omx_reader.SeekChapter(m_omx_reader.GetChapter() - 1, &startpts); FlushStreams(startpts); } else { m_incr = -600.0; } break; case 'o': if(m_omx_reader.GetChapterCount() > 0) { m_omx_reader.SeekChapter(m_omx_reader.GetChapter() + 1, &startpts); FlushStreams(startpts); } else { m_incr = 600.0; } break; case 'n': if(m_omx_reader.GetSubtitleIndex() > 0) { m_omx_reader.SetActiveStream(OMXSTREAM_SUBTITLE, m_omx_reader.GetSubtitleIndex() - 1); m_player_video.FlushSubtitles(); } break; case 'm': if(m_omx_reader.GetSubtitleIndex() > 0) { m_omx_reader.SetActiveStream(OMXSTREAM_SUBTITLE, m_omx_reader.GetSubtitleIndex() + 1); m_player_video.FlushSubtitles(); } break; case 's': m_show_subtitle = !m_show_subtitle; break; case 'q': m_stop = true; goto do_exit; break; case 0x5b44: // key left if(m_omx_reader.CanSeek()) m_incr = -30.0; break; case 0x5b43: // key right if(m_omx_reader.CanSeek()) m_incr = 30.0; break; case 0x5b41: // key up if(m_omx_reader.CanSeek()) m_incr = 600.0; break; case 0x5b42: // key down if(m_omx_reader.CanSeek()) m_incr = -600.0; break; case ' ': case 'p': m_Pause = !m_Pause; if(m_Pause) { SetSpeed(OMX_PLAYSPEED_PAUSE); m_av_clock->OMXPause(); } else { SetSpeed(OMX_PLAYSPEED_NORMAL); m_av_clock->OMXResume(); } break; case '-': m_player_audio.SetCurrentVolume(m_player_audio.GetCurrentVolume() - 50); printf("Current Volume: %.2fdB\n", m_player_audio.GetCurrentVolume() / 100.0f); break; case '+': m_player_audio.SetCurrentVolume(m_player_audio.GetCurrentVolume() + 50); printf("Current Volume: %.2fdB\n", m_player_audio.GetCurrentVolume() / 100.0f); break; default: break; } if(m_Pause) { OMXClock::OMXSleep(2); continue; } if(m_incr != 0 && !m_bMpeg) { int seek_flags = 0; double seek_pos = 0; double pts = 0; pts = m_av_clock->GetPTS(); seek_pos = (pts / DVD_TIME_BASE) + m_incr; seek_flags = m_incr < 0.0f ? AVSEEK_FLAG_BACKWARD : 0; seek_pos *= 1000.0f; m_incr = 0; if(m_omx_reader.SeekTime(seek_pos, seek_flags, &startpts)) FlushStreams(startpts); m_player_video.Close(); if(m_has_video && !m_player_video.Open(m_hints_video, m_av_clock, m_Deinterlace, m_bMpeg, m_hdmi_clock_sync, m_thread_player)) goto do_exit; } /* when the audio buffer runs under 0.1 seconds we buffer up */ if(m_has_audio) { if(m_player_audio.GetDelay() < 0.1f && !m_buffer_empty) { if(!m_av_clock->OMXIsPaused()) { m_av_clock->OMXPause(); //printf("buffering start\n"); m_buffer_empty = true; clock_gettime(CLOCK_REALTIME, &starttime); } } if(m_player_audio.GetDelay() > (AUDIO_BUFFER_SECONDS * 0.75f) && m_buffer_empty) { if(m_av_clock->OMXIsPaused()) { m_av_clock->OMXResume(); //printf("buffering end\n"); m_buffer_empty = false; } } if(m_buffer_empty) { clock_gettime(CLOCK_REALTIME, &endtime); if((endtime.tv_sec - starttime.tv_sec) > 1) { m_buffer_empty = false; m_av_clock->OMXResume(); //printf("buffering timed out\n"); } } } if(!m_omx_pkt) m_omx_pkt = m_omx_reader.Read(); if(m_has_video && m_omx_pkt && m_omx_reader.IsActive(OMXSTREAM_VIDEO, m_omx_pkt->stream_index)) { if(m_player_video.AddPacket(m_omx_pkt)) m_omx_pkt = NULL; else OMXClock::OMXSleep(10); if(m_tv_show_info) { char response[80]; vc_gencmd(response, sizeof response, "render_bar 4 video_fifo %d %d %d %d", m_player_video.GetDecoderBufferSize()-m_player_video.GetDecoderFreeSpace(), 0 , 0, m_player_video.GetDecoderBufferSize()); vc_gencmd(response, sizeof response, "render_bar 5 audio_fifo %d %d %d %d", (int)(100.0*m_player_audio.GetDelay()), 0, 0, 100*AUDIO_BUFFER_SECONDS); } } else if(m_has_audio && m_omx_pkt && m_omx_pkt->codec_type == AVMEDIA_TYPE_AUDIO) { if(m_player_audio.AddPacket(m_omx_pkt)) m_omx_pkt = NULL; else OMXClock::OMXSleep(10); } else if(m_omx_pkt && m_omx_reader.IsActive(OMXSTREAM_SUBTITLE, m_omx_pkt->stream_index)) { if(m_omx_pkt->size && (m_omx_pkt->hints.codec == CODEC_ID_TEXT || m_omx_pkt->hints.codec == CODEC_ID_SSA)) { if(m_player_video.AddPacket(m_omx_pkt)) m_omx_pkt = NULL; else OMXClock::OMXSleep(10); } else { m_omx_reader.FreePacket(m_omx_pkt); m_omx_pkt = NULL; } } else { if(m_omx_pkt) { m_omx_reader.FreePacket(m_omx_pkt); m_omx_pkt = NULL; } } /* player got in an error state */ if(m_player_audio.Error()) { printf("audio player error. emergency exit!!!\n"); goto do_exit; } CStdString strSubTitle = m_player_video.GetText(); if(strSubTitle.length() && m_show_subtitle) { if(last_sub != strSubTitle) { last_sub = strSubTitle; printf("Text : %s\n", strSubTitle.c_str()); } } if(m_stats) { printf("V : %8.02f %8d %8d A : %8.02f %8.02f Cv : %8d Ca : %8d \r", m_player_video.GetCurrentPTS() / DVD_TIME_BASE, m_player_video.GetDecoderBufferSize(), m_player_video.GetDecoderFreeSpace(), m_player_audio.GetCurrentPTS() / DVD_TIME_BASE, m_player_audio.GetDelay(), m_player_video.GetCached(), m_player_audio.GetCached()); } if(m_omx_reader.IsEof()) break; } do_exit: printf("\n"); if(!m_stop) { if(m_has_audio) m_player_audio.WaitCompletion(); else if(m_has_video) m_player_video.WaitCompletion(); } if(m_refresh) { m_BcmHost.vc_tv_hdmi_power_on_best(tv_state.width, tv_state.height, tv_state.frame_rate, HDMI_NONINTERLACED, (EDID_MODE_MATCH_FLAG_T)(HDMI_MODE_MATCH_FRAMERATE|HDMI_MODE_MATCH_RESOLUTION|HDMI_MODE_MATCH_SCANMODE)); } m_av_clock->OMXStop(); m_av_clock->OMXStateIdle(); m_player_video.Close(); m_player_audio.Close(); if(m_omx_pkt) { m_omx_reader.FreePacket(m_omx_pkt); m_omx_pkt = NULL; } m_omx_reader.Close(); vc_tv_show_info(0); g_OMX.Deinitialize(); g_RBP.Deinitialize(); printf("have a nice day ;)\n"); return 1; }
/*------------------------------------------------------------------------------ | OMX_VideoProcessor::cleanup +-----------------------------------------------------------------------------*/ void OMX_MediaProcessor::cleanup() { LOG_INFORMATION(LOG_TAG, "Cleaning up..."); if (!m_pendingStop /* && !g_abort */) { LOG_VERBOSE(LOG_TAG, "Waiting for audio completion..."); if (m_has_audio) m_player_audio->WaitCompletion(); LOG_VERBOSE(LOG_TAG, "Waiting for video completion..."); if (m_has_video) m_player_video->WaitCompletion(); } #if 0 if (m_refresh) { m_BcmHost.vc_tv_hdmi_power_on_best( tv_state.width, tv_state.height, tv_state.frame_rate, HDMI_NONINTERLACED, (EDID_MODE_MATCH_FLAG_T)(HDMI_MODE_MATCH_FRAMERATE| HDMI_MODE_MATCH_RESOLUTION|HDMI_MODE_MATCH_SCANMODE) ); } #endif LOG_VERBOSE(LOG_TAG, "Stopping OMX clock..."); m_av_clock->OMXStop(); m_av_clock->OMXStateIdle(); LOG_VERBOSE(LOG_TAG, "Closing players..."); #ifdef ENABLE_SUBTITLES m_player_subtitles->Close(); #endif m_player_video->Close(); m_player_audio->Close(); if (m_omx_pkt) { m_omx_reader.FreePacket(m_omx_pkt); m_omx_pkt = NULL; } LOG_VERBOSE(LOG_TAG, "Closing players..."); m_omx_reader.Close(); vc_tv_show_info(0); // lcarlon: this should only be done in object destructor. //LOG_VERBOSE(LOG_TAG, "Deinitializing engines..."); //m_OMX.Deinitialize(); //m_RBP.Deinitialize(); // lcarlon: free the texture. LOG_VERBOSE(LOG_TAG, "Freeing texture..."); emit textureInvalidated(); #if 0 QMetaObject::invokeMethod( (QObject*)m_provider, "freeTexture", Qt::QueuedConnection, Q_ARG(OMX_TextureData*, m_textureData) ); #endif m_textureData = NULL; // Actually change the state here and reset flags. m_state = STATE_STOPPED; m_mutexPending.lock(); if (m_pendingStop) { m_pendingStop = false; m_waitPendingCommand.wakeAll(); } m_mutexPending.unlock(); LOG_INFORMATION(LOG_TAG, "Cleanup done."); }
int main(int argc, char *argv[]) { signal(SIGINT, sig_handler); if (isatty(STDIN_FILENO)) { struct termios new_termios; tcgetattr(STDIN_FILENO, &orig_termios); new_termios = orig_termios; new_termios.c_lflag &= ~(ICANON | ECHO | ECHOCTL | ECHONL); new_termios.c_cflag |= HUPCL; new_termios.c_cc[VMIN] = 0; tcsetattr(STDIN_FILENO, TCSANOW, &new_termios); atexit(restore_termios); } else { orig_fl = fcntl(STDIN_FILENO, F_GETFL); fcntl(STDIN_FILENO, F_SETFL, orig_fl | O_NONBLOCK); atexit(restore_fl); } std::string m_filename; double m_incr = 0; CRBP g_RBP; COMXCore g_OMX; bool m_stats = false; bool m_dump_format = false; FORMAT_3D_T m_3d = CONF_FLAGS_FORMAT_NONE; bool m_refresh = false; double startpts = 0; CRect DestRect = {0,0,0,0}; TV_DISPLAY_STATE_T tv_state; const int font_opt = 0x100; const int font_size_opt = 0x101; const int align_opt = 0x102; const int subtitles_opt = 0x103; const int lines_opt = 0x104; const int pos_opt = 0x105; const int boost_on_downmix_opt = 0x200; struct option longopts[] = { { "info", no_argument, NULL, 'i' }, { "help", no_argument, NULL, 'h' }, { "aidx", required_argument, NULL, 'n' }, { "adev", required_argument, NULL, 'o' }, { "stats", no_argument, NULL, 's' }, { "passthrough", no_argument, NULL, 'p' }, { "deinterlace", no_argument, NULL, 'd' }, { "hw", no_argument, NULL, 'w' }, { "3d", required_argument, NULL, '3' }, { "hdmiclocksync", no_argument, NULL, 'y' }, { "nohdmiclocksync", no_argument, NULL, 'z' }, { "refresh", no_argument, NULL, 'r' }, { "sid", required_argument, NULL, 't' }, { "pos", required_argument, NULL, 'l' }, { "font", required_argument, NULL, font_opt }, { "font-size", required_argument, NULL, font_size_opt }, { "align", required_argument, NULL, align_opt }, { "subtitles", required_argument, NULL, subtitles_opt }, { "lines", required_argument, NULL, lines_opt }, { "win", required_argument, NULL, pos_opt }, { "boost-on-downmix", no_argument, NULL, boost_on_downmix_opt }, { 0, 0, 0, 0 } }; int c; std::string mode; while ((c = getopt_long(argc, argv, "wihn:l:o:cslpd3:yzt:r", longopts, NULL)) != -1) { switch (c) { case 'r': m_refresh = true; break; case 'y': m_hdmi_clock_sync = true; break; case 'z': m_no_hdmi_clock_sync = true; break; case '3': mode = optarg; if(mode != "SBS" && mode != "TB") { print_usage(); return 0; } if(mode == "TB") m_3d = CONF_FLAGS_FORMAT_TB; else m_3d = CONF_FLAGS_FORMAT_SBS; break; case 'd': m_Deinterlace = true; break; case 'w': m_use_hw_audio = true; break; case 'p': m_passthrough = true; break; case 's': m_stats = true; break; case 'o': deviceString = optarg; if(deviceString != "local" && deviceString != "hdmi") { print_usage(); return 0; } deviceString = "omx:" + deviceString; break; case 'i': m_dump_format = true; break; case 't': m_subtitle_index = atoi(optarg) - 1; if(m_subtitle_index < 0) m_subtitle_index = 0; break; case 'n': m_audio_index_use = atoi(optarg) - 1; if(m_audio_index_use < 0) m_audio_index_use = 0; break; case 'l': m_seek_pos = atoi(optarg) ; if (m_seek_pos < 0) m_seek_pos = 0; break; case font_opt: m_font_path = optarg; m_has_font = true; break; case font_size_opt: { const int thousands = atoi(optarg); if (thousands > 0) m_font_size = thousands*0.001f; } break; case align_opt: m_centered = !strcmp(optarg, "center"); break; case subtitles_opt: m_external_subtitles_path = optarg; m_has_external_subtitles = true; break; case lines_opt: m_subtitle_lines = std::max(atoi(optarg), 1); break; case pos_opt: sscanf(optarg, "%f %f %f %f", &DestRect.x1, &DestRect.y1, &DestRect.x2, &DestRect.y2); break; case boost_on_downmix_opt: m_boost_on_downmix = true; break; case 0: break; case 'h': print_usage(); return 0; break; case ':': return 0; break; default: return 0; break; } } if (optind >= argc) { print_usage(); return 0; } m_filename = argv[optind]; auto PrintFileNotFound = [](const std::string& path) { printf("File \"%s\" not found.\n", path.c_str()); }; bool filename_is_URL = IsURL(m_filename); if(!filename_is_URL && !Exists(m_filename)) { PrintFileNotFound(m_filename); return 0; } if(m_has_font && !Exists(m_font_path)) { PrintFileNotFound(m_font_path); return 0; } if(m_has_external_subtitles && !Exists(m_external_subtitles_path)) { PrintFileNotFound(m_external_subtitles_path); return 0; } if(!m_has_external_subtitles && !filename_is_URL) { auto subtitles_path = m_filename.substr(0, m_filename.find_last_of(".")) + ".srt"; if(Exists(subtitles_path)) { m_external_subtitles_path = subtitles_path; m_has_external_subtitles = true; } } CLog::Init("./"); g_RBP.Initialize(); g_OMX.Initialize(); m_av_clock = new OMXClock(); m_thread_player = true; if(!m_omx_reader.Open(m_filename.c_str(), m_dump_format)) goto do_exit; if(m_dump_format) goto do_exit; m_bMpeg = m_omx_reader.IsMpegVideo(); m_has_video = m_omx_reader.VideoStreamCount(); m_has_audio = m_omx_reader.AudioStreamCount(); m_has_subtitle = m_has_external_subtitles || m_omx_reader.SubtitleStreamCount(); if(m_filename.find("3DSBS") != string::npos || m_filename.find("HSBS") != string::npos) m_3d = CONF_FLAGS_FORMAT_SBS; else if(m_filename.find("3DTAB") != string::npos || m_filename.find("HTAB") != string::npos) m_3d = CONF_FLAGS_FORMAT_TB; // 3d modes don't work without switch hdmi mode if (m_3d != CONF_FLAGS_FORMAT_NONE) m_refresh = true; // you really don't want want to match refresh rate without hdmi clock sync if (m_refresh && !m_no_hdmi_clock_sync) m_hdmi_clock_sync = true; if(!m_av_clock->OMXInitialize(m_has_video, m_has_audio)) goto do_exit; if(m_hdmi_clock_sync && !m_av_clock->HDMIClockSync()) goto do_exit; m_omx_reader.GetHints(OMXSTREAM_AUDIO, m_hints_audio); m_omx_reader.GetHints(OMXSTREAM_VIDEO, m_hints_video); if(m_audio_index_use != -1) m_omx_reader.SetActiveStream(OMXSTREAM_AUDIO, m_audio_index_use); if(m_has_video && m_refresh) { memset(&tv_state, 0, sizeof(TV_DISPLAY_STATE_T)); m_BcmHost.vc_tv_get_display_state(&tv_state); SetVideoMode(m_hints_video.width, m_hints_video.height, m_hints_video.fpsrate, m_hints_video.fpsscale, m_3d); } // get display aspect TV_DISPLAY_STATE_T current_tv_state; memset(¤t_tv_state, 0, sizeof(TV_DISPLAY_STATE_T)); m_BcmHost.vc_tv_get_display_state(¤t_tv_state); if(current_tv_state.state & ( VC_HDMI_HDMI | VC_HDMI_DVI )) { //HDMI or DVI on m_display_aspect = get_display_aspect_ratio((HDMI_ASPECT_T)current_tv_state.display.hdmi.aspect_ratio); } else { //composite on m_display_aspect = get_display_aspect_ratio((SDTV_ASPECT_T)current_tv_state.display.sdtv.display_options.aspect); } m_display_aspect *= (float)current_tv_state.display.hdmi.height/(float)current_tv_state.display.hdmi.width; // seek on start if (m_seek_pos !=0 && m_omx_reader.CanSeek()) { printf("Seeking start of video to %i seconds\n", m_seek_pos); m_omx_reader.SeekTime(m_seek_pos * 1000.0f, 0, &startpts); // from seconds to DVD_TIME_BASE } if(m_has_video && !m_player_video.Open(m_hints_video, m_av_clock, DestRect, m_Deinterlace, m_bMpeg, m_hdmi_clock_sync, m_thread_player, m_display_aspect)) goto do_exit; { std::vector<Subtitle> external_subtitles; if(m_has_external_subtitles && !ReadSrt(m_external_subtitles_path, external_subtitles)) { puts("Unable to read the subtitle file."); goto do_exit; } if(m_has_subtitle && !m_player_subtitles.Open(m_omx_reader.SubtitleStreamCount(), std::move(external_subtitles), m_font_path, m_font_size, m_centered, m_subtitle_lines, m_av_clock)) goto do_exit; } if(m_has_subtitle) { if(!m_has_external_subtitles) { if(m_subtitle_index != -1) { m_player_subtitles.SetActiveStream( std::min(m_subtitle_index, m_omx_reader.SubtitleStreamCount()-1)); } m_player_subtitles.SetUseExternalSubtitles(false); } if(m_subtitle_index == -1 && !m_has_external_subtitles) m_player_subtitles.SetVisible(false); } m_omx_reader.GetHints(OMXSTREAM_AUDIO, m_hints_audio); if(m_has_audio && !m_player_audio.Open(m_hints_audio, m_av_clock, &m_omx_reader, deviceString, m_passthrough, m_use_hw_audio, m_boost_on_downmix, m_thread_player)) goto do_exit; m_av_clock->SetSpeed(DVD_PLAYSPEED_NORMAL); m_av_clock->OMXStateExecute(); m_av_clock->OMXStart(0.0); struct timespec starttime, endtime; PrintSubtitleInfo(); while(!m_stop) { int ch[8]; int chnum = 0; if(g_abort) goto do_exit; while((ch[chnum] = getchar()) != EOF) chnum++; if (chnum > 1) ch[0] = ch[chnum - 1] | (ch[chnum - 2] << 8); switch(ch[0]) { case 'z': m_tv_show_info = !m_tv_show_info; vc_tv_show_info(m_tv_show_info); break; case '1': SetSpeed(m_av_clock->OMXPlaySpeed() - 1); break; case '2': SetSpeed(m_av_clock->OMXPlaySpeed() + 1); break; case 'j': if(m_has_audio) { int new_index = m_omx_reader.GetAudioIndex() - 1; if (new_index >= 0) m_omx_reader.SetActiveStream(OMXSTREAM_AUDIO, new_index); } break; case 'k': if(m_has_audio) m_omx_reader.SetActiveStream(OMXSTREAM_AUDIO, m_omx_reader.GetAudioIndex() + 1); break; case 'i': if(m_omx_reader.GetChapterCount() > 0) { m_omx_reader.SeekChapter(m_omx_reader.GetChapter() - 1, &startpts); FlushStreams(startpts); } else { m_incr = -600.0; } break; case 'o': if(m_omx_reader.GetChapterCount() > 0) { m_omx_reader.SeekChapter(m_omx_reader.GetChapter() + 1, &startpts); FlushStreams(startpts); } else { m_incr = 600.0; } break; case 'n': if(m_has_subtitle) { if(!m_player_subtitles.GetUseExternalSubtitles()) { if (m_player_subtitles.GetActiveStream() == 0) { if(m_has_external_subtitles) m_player_subtitles.SetUseExternalSubtitles(true); } else { m_player_subtitles.SetActiveStream( m_player_subtitles.GetActiveStream()-1); } } m_player_subtitles.SetVisible(true); PrintSubtitleInfo(); } break; case 'm': if(m_has_subtitle) { if(m_player_subtitles.GetUseExternalSubtitles()) { if(m_omx_reader.SubtitleStreamCount()) { assert(m_player_subtitles.GetActiveStream() == 0); m_player_subtitles.SetUseExternalSubtitles(false); } } else { auto new_index = m_player_subtitles.GetActiveStream()+1; if(new_index < (size_t) m_omx_reader.SubtitleStreamCount()) m_player_subtitles.SetActiveStream(new_index); } m_player_subtitles.SetVisible(true); PrintSubtitleInfo(); } break; case 's': if(m_has_subtitle) { m_player_subtitles.SetVisible(!m_player_subtitles.GetVisible()); PrintSubtitleInfo(); } break; case 'd': if(m_has_subtitle && m_player_subtitles.GetVisible()) { m_player_subtitles.SetDelay(m_player_subtitles.GetDelay() - 250); PrintSubtitleInfo(); } break; case 'f': if(m_has_subtitle && m_player_subtitles.GetVisible()) { m_player_subtitles.SetDelay(m_player_subtitles.GetDelay() + 250); PrintSubtitleInfo(); } break; case 'q': m_stop = true; goto do_exit; break; case 0x5b44: // key left if(m_omx_reader.CanSeek()) m_incr = -30.0; break; case 0x5b43: // key right if(m_omx_reader.CanSeek()) m_incr = 30.0; break; case 0x5b41: // key up if(m_omx_reader.CanSeek()) m_incr = 600.0; break; case 0x5b42: // key down if(m_omx_reader.CanSeek()) m_incr = -600.0; break; case ' ': case 'p': m_Pause = !m_Pause; if(m_Pause) { SetSpeed(OMX_PLAYSPEED_PAUSE); m_av_clock->OMXPause(); if(m_has_subtitle) m_player_subtitles.Pause(); } else { if(m_has_subtitle) m_player_subtitles.Resume(); SetSpeed(OMX_PLAYSPEED_NORMAL); m_av_clock->OMXResume(); } break; case '-': m_player_audio.SetCurrentVolume(m_player_audio.GetCurrentVolume() - 300); printf("Current Volume: %.2fdB\n", m_player_audio.GetCurrentVolume() / 100.0f); break; case '+': m_player_audio.SetCurrentVolume(m_player_audio.GetCurrentVolume() + 300); printf("Current Volume: %.2fdB\n", m_player_audio.GetCurrentVolume() / 100.0f); break; default: break; } if(m_Pause) { OMXClock::OMXSleep(2); continue; } if(m_incr != 0 && !m_bMpeg) { int seek_flags = 0; double seek_pos = 0; double pts = 0; if(m_has_subtitle) m_player_subtitles.Pause(); m_av_clock->OMXStop(); pts = m_av_clock->GetPTS(); seek_pos = (pts / DVD_TIME_BASE) + m_incr; seek_flags = m_incr < 0.0f ? AVSEEK_FLAG_BACKWARD : 0; seek_pos *= 1000.0f; m_incr = 0; if(m_omx_reader.SeekTime(seek_pos, seek_flags, &startpts)) FlushStreams(startpts); m_player_video.Close(); if(m_has_video && !m_player_video.Open(m_hints_video, m_av_clock, DestRect, m_Deinterlace, m_bMpeg, m_hdmi_clock_sync, m_thread_player, m_display_aspect)) goto do_exit; m_av_clock->OMXStart(startpts); if(m_has_subtitle) m_player_subtitles.Resume(); } /* player got in an error state */ if(m_player_audio.Error()) { printf("audio player error. emergency exit!!!\n"); goto do_exit; } if(m_stats) { printf("V : %8.02f %8d %8d A : %8.02f %8.02f Cv : %8d Ca : %8d \r", m_av_clock->OMXMediaTime(), m_player_video.GetDecoderBufferSize(), m_player_video.GetDecoderFreeSpace(), m_player_audio.GetCurrentPTS() / DVD_TIME_BASE, m_player_audio.GetDelay(), m_player_video.GetCached(), m_player_audio.GetCached()); } if(m_omx_reader.IsEof() && !m_omx_pkt) { if (!m_player_audio.GetCached() && !m_player_video.GetCached()) break; // Abort audio buffering, now we're on our own if (m_buffer_empty) m_av_clock->OMXResume(); OMXClock::OMXSleep(10); continue; } /* when the audio buffer runs under 0.1 seconds we buffer up */ if(m_has_audio) { if(m_player_audio.GetDelay() < 0.1f && !m_buffer_empty) { if(!m_av_clock->OMXIsPaused()) { m_av_clock->OMXPause(); //printf("buffering start\n"); m_buffer_empty = true; clock_gettime(CLOCK_REALTIME, &starttime); } } if(m_player_audio.GetDelay() > (AUDIO_BUFFER_SECONDS * 0.75f) && m_buffer_empty) { if(m_av_clock->OMXIsPaused()) { m_av_clock->OMXResume(); //printf("buffering end\n"); m_buffer_empty = false; } } if(m_buffer_empty) { clock_gettime(CLOCK_REALTIME, &endtime); if((endtime.tv_sec - starttime.tv_sec) > 1) { m_buffer_empty = false; m_av_clock->OMXResume(); //printf("buffering timed out\n"); } } } if(!m_omx_pkt) m_omx_pkt = m_omx_reader.Read(); if(m_has_video && m_omx_pkt && m_omx_reader.IsActive(OMXSTREAM_VIDEO, m_omx_pkt->stream_index)) { if(m_player_video.AddPacket(m_omx_pkt)) m_omx_pkt = NULL; else OMXClock::OMXSleep(10); if(m_tv_show_info) { char response[80]; vc_gencmd(response, sizeof response, "render_bar 4 video_fifo %d %d %d %d", m_player_video.GetDecoderBufferSize()-m_player_video.GetDecoderFreeSpace(), 0 , 0, m_player_video.GetDecoderBufferSize()); vc_gencmd(response, sizeof response, "render_bar 5 audio_fifo %d %d %d %d", (int)(100.0*m_player_audio.GetDelay()), 0, 0, 100*AUDIO_BUFFER_SECONDS); } } else if(m_has_audio && m_omx_pkt && m_omx_pkt->codec_type == AVMEDIA_TYPE_AUDIO) { if(m_player_audio.AddPacket(m_omx_pkt)) m_omx_pkt = NULL; else OMXClock::OMXSleep(10); } else if(m_has_subtitle && m_omx_pkt && m_omx_pkt->codec_type == AVMEDIA_TYPE_SUBTITLE) { auto result = m_player_subtitles.AddPacket(m_omx_pkt, m_omx_reader.GetRelativeIndex(m_omx_pkt->stream_index)); if (result) m_omx_pkt = NULL; else OMXClock::OMXSleep(10); } else { if(m_omx_pkt) { m_omx_reader.FreePacket(m_omx_pkt); m_omx_pkt = NULL; } } } do_exit: printf("\n"); if(!m_stop && !g_abort) { if(m_has_audio) m_player_audio.WaitCompletion(); else if(m_has_video) m_player_video.WaitCompletion(); } if(m_has_video && m_refresh && tv_state.display.hdmi.group && tv_state.display.hdmi.mode) { m_BcmHost.vc_tv_hdmi_power_on_explicit_new(HDMI_MODE_HDMI, (HDMI_RES_GROUP_T)tv_state.display.hdmi.group, tv_state.display.hdmi.mode); } m_av_clock->OMXStop(); m_av_clock->OMXStateIdle(); m_player_subtitles.Close(); m_player_video.Close(); m_player_audio.Close(); if(m_omx_pkt) { m_omx_reader.FreePacket(m_omx_pkt); m_omx_pkt = NULL; } m_omx_reader.Close(); vc_tv_show_info(0); g_OMX.Deinitialize(); g_RBP.Deinitialize(); printf("have a nice day ;)\n"); return 1; }
int SyncVideo::play() { // signal(SIGINT, sig_handler); bool m_first = true; #if WANT_KEYS if (isatty(STDIN_FILENO)) { struct termios new_termios; tcgetattr(STDIN_FILENO, &orig_termios); new_termios = orig_termios; new_termios.c_lflag &= ~(ICANON | ECHO | ECHOCTL | ECHONL); new_termios.c_cflag |= HUPCL; new_termios.c_cc[VMIN] = 0; tcsetattr(STDIN_FILENO, TCSANOW, &new_termios); atexit(restore_termios); } else { orig_fl = fcntl(STDIN_FILENO, F_GETFL); fcntl(STDIN_FILENO, F_SETFL, orig_fl | O_NONBLOCK); atexit(restore_fl); } #endif /* WANT_KEYS */ double m_incr = 0; CRBP g_RBP; COMXCore g_OMX; bool m_quiet = false; bool m_stats = false; bool m_dump_format = false; FORMAT_3D_T m_3d = CONF_FLAGS_FORMAT_NONE; bool m_refresh = false; double startpts = 0; CRect DestRect = {0,0,0,0}; TV_DISPLAY_STATE_T tv_state; GError *error = NULL; const int font_opt = 0x100; const int font_size_opt = 0x101; const int align_opt = 0x102; const int subtitles_opt = 0x103; const int lines_opt = 0x104; const int pos_opt = 0x105; const int vol_opt = 0x106; const int boost_on_downmix_opt = 0x200; const int tile_code_opt = 0x300; const int frame_size_opt = 0x301; //LOOP double loop_offset = 0.0; double last_packet_pts = 0.0; double last_packet_dts = 0.0; double last_packet_duration = 0.0; // int c; // std::string mode; // while ((c = getopt_long(argc, argv, "wihn:l:o:cqslpd3:yzt:rW:T:O:F:AR:C:", longopts, NULL)) != -1) // { // switch (c) // { // case 'q': // m_quiet = true; // break; // case 'l': // m_seek_pos = atoi(optarg) ; // if (m_seek_pos < 0) // m_seek_pos = 0; // break; // case pos_opt: // sscanf(optarg, "%f %f %f %f", &DestRect.x1, &DestRect.y1, &DestRect.x2, &DestRect.y2); // break; // case tile_code_opt: // if (! m_tilemap) m_tilemap = pwtilemap_create(); // pwtilemap_set_tilecode(m_tilemap, atoi(optarg)); // break; // case frame_size_opt: // { // float fx, fy; // char c; // if (! m_tilemap) m_tilemap = pwtilemap_create(); // if (sscanf(optarg, "%gx%g%c", &fx, &fy, &c) != 2) { // fprintf(stderr, "pwomxplayer --frame-size: invalid FXxFY\n"); // return 2; // } // pwtilemap_set_framesize(m_tilemap, fx, fy); // } // break; // case 'W': // { // PwRect wall; // if (! m_tilemap) m_tilemap = pwtilemap_create(); // if (! pwrect_from_string(&wall, optarg, &error)) { // fprintf(stderr, "pwomxplayer --wall: %s\n", error->message); // return 2; // } else { // pwtilemap_set_wall(m_tilemap, &wall); // } // } // break; // case 'T': // { // PwRect tile; // if (! m_tilemap) m_tilemap = pwtilemap_create(); // if (! pwrect_from_string(&tile, optarg, &error)) { // fprintf(stderr, "pwomxplayer --tile: %s\n", error->message); // return 2; // } else { // pwtilemap_set_tile(m_tilemap, &tile); // } // } // break; // case 'O': // { // PwOrient orient; // if (! m_tilemap) m_tilemap = pwtilemap_create(); // if (! pworient_from_string(&orient, optarg, &error)) { // fprintf(stderr, "pwomxplayer --orient: %s\n", error->message); // return 2; // } else { // pwtilemap_set_orient(m_tilemap, orient); // } // } // break; // case 'F': // { // PwFit fit; // if (! m_tilemap) m_tilemap = pwtilemap_create(); // if (! pwfit_from_string(&fit, optarg, &error)) { // fprintf(stderr, "pwomxplayer --fit: %s\n", error->message); // return 2; // } else { // pwtilemap_set_fit(m_tilemap, fit); // } // } // break; // case 'A': // if (! m_tilemap) m_tilemap = pwtilemap_create(); // pwtilemap_set_auto(m_tilemap); // break; // case 'R': // if (! m_tilemap) m_tilemap = pwtilemap_create(); // pwtilemap_set_role(m_tilemap, optarg); // break; // case 'C': // if (! m_tilemap) m_tilemap = pwtilemap_create(); // pwtilemap_set_config(m_tilemap, optarg); // break; // case 0: // break; // case 'h': // print_usage(); // return 0; // break; // case ':': // return 0; // break; // default: // return 0; // break; // } // } //changement de taille ICI if(m_wallWidth > 0 && m_wallHeight > 0) { ostringstream wallStr; wallStr << m_wallWidth << "x" << m_wallHeight << "+0+0"; cout << "WALL " << wallStr.str() << endl; PwRect wall; if (! m_tilemap) m_tilemap = pwtilemap_create(); if (! pwrect_from_string(&wall, wallStr.str().c_str(), &error)) { fprintf(stderr, "pwomxplayer --wall: %s\n", error->message); return 2; } else { pwtilemap_set_wall(m_tilemap, &wall); } } if(m_tileWidth > 0 && m_tileHeight > 0 && m_tileX >= 0 && m_tileY >= 0) { ostringstream tileStr; tileStr << m_tileWidth << "x" << m_tileHeight << "+" << m_tileX << "+" << m_tileY; cout << "TILE " << tileStr.str() << endl; PwRect tile; if (! m_tilemap) m_tilemap = pwtilemap_create(); if (! pwrect_from_string(&tile, tileStr.str().c_str(), &error)) { fprintf(stderr, "pwomxplayer --tile: %s\n", error->message); return 2; } else { pwtilemap_set_tile(m_tilemap, &tile); } } auto PrintFileNotFound = [](const std::string& path) { printf("File \"%s\" not found.\n", path.c_str()); }; bool filename_is_URL = IsURL(m_filename); if(!filename_is_URL && !Exists(m_filename)) { PrintFileNotFound(m_filename); return 0; } if(m_has_font && !Exists(m_font_path)) { PrintFileNotFound(m_font_path); return 0; } if(m_has_external_subtitles && !Exists(m_external_subtitles_path)) { PrintFileNotFound(m_external_subtitles_path); return 0; } if(!m_has_external_subtitles && !filename_is_URL) { auto subtitles_path = m_filename.substr(0, m_filename.find_last_of(".")) + ".srt"; if(Exists(subtitles_path)) { m_external_subtitles_path = subtitles_path; m_has_external_subtitles = true; } } if (m_tilemap != NULL) { if (! pwtilemap_define(m_tilemap, &error)) { fprintf(stderr, "pwomxplayer: %s\n", error->message); return 1; } } g_RBP.Initialize(); g_OMX.Initialize(); m_av_clock = new OMXClock(); m_thread_player = true; if(!m_omx_reader.Open(m_filename.c_str(), m_dump_format, ! m_quiet)) goto do_exit; if(m_dump_format) goto do_exit; //LOOP if(m_loop && !m_omx_reader.CanSeek()) { printf("Looping requested on an input that doesn't support seeking\n"); goto do_exit; } struct timeval now; gettimeofday(&now, NULL); //start date is over and we can navigate through the stream if(m_dateStart < now.tv_sec && m_omx_reader.CanSeek()) { if(m_omx_reader.GetStreamLength() < 15000) { struct tm * timeinfo; char buffer [80]; timeinfo = localtime (&(m_dateStart)); strftime (buffer,80," %I:%M:%S%p.",timeinfo); printf("previous time %s\n", buffer); m_seek_pos = 0; m_dateStart = now.tv_sec + 15 + m_omx_reader.GetStreamLength()/1000 - ((now.tv_sec+15)%(m_omx_reader.GetStreamLength()/1000)); timeinfo = localtime (&(m_dateStart)); strftime (buffer,80," %I:%M:%S%p.",timeinfo); printf("after time %s\n", buffer); }else { //but there is still some video to play (with a safety) if(m_dateEnd > now.tv_sec + 15) { printf("Start on the go\n"); m_seek_pos = now.tv_sec - m_dateStart + 15; if(m_seek_pos > m_omx_reader.GetStreamLength()/1000 && m_loop) { printf("seekpos %i\n", m_seek_pos); printf("duration %i\n", m_omx_reader.GetStreamLength()); m_seek_pos = m_seek_pos % (m_omx_reader.GetStreamLength()/1000); printf("new seekpos %i\n", m_seek_pos); } m_dateStart = now.tv_sec + 15; } } } m_bMpeg = m_omx_reader.IsMpegVideo(); m_has_video = m_omx_reader.VideoStreamCount(); m_has_audio = m_omx_reader.AudioStreamCount(); m_has_subtitle = m_has_external_subtitles || m_omx_reader.SubtitleStreamCount(); if(m_filename.find("3DSBS") != string::npos || m_filename.find("HSBS") != string::npos) m_3d = CONF_FLAGS_FORMAT_SBS; else if(m_filename.find("3DTAB") != string::npos || m_filename.find("HTAB") != string::npos) m_3d = CONF_FLAGS_FORMAT_TB; // 3d modes don't work without switch hdmi mode if (m_3d != CONF_FLAGS_FORMAT_NONE) m_refresh = true; // you really don't want want to match refresh rate without hdmi clock sync if (m_refresh && !m_no_hdmi_clock_sync) m_hdmi_clock_sync = true; if(!m_av_clock->OMXInitialize(m_has_video, m_has_audio)) goto do_exit; if(m_hdmi_clock_sync && !m_av_clock->HDMIClockSync()) goto do_exit; m_omx_reader.GetHints(OMXSTREAM_AUDIO, m_hints_audio); m_omx_reader.GetHints(OMXSTREAM_VIDEO, m_hints_video); if(m_audio_index_use != -1) m_omx_reader.SetActiveStream(OMXSTREAM_AUDIO, m_audio_index_use); if(m_has_video && m_refresh) { memset(&tv_state, 0, sizeof(TV_DISPLAY_STATE_T)); m_BcmHost.vc_tv_get_display_state(&tv_state); SetVideoMode(m_hints_video.width, m_hints_video.height, m_hints_video.fpsrate, m_hints_video.fpsscale, m_3d, ! m_quiet); } // get display aspect TV_DISPLAY_STATE_T current_tv_state; memset(¤t_tv_state, 0, sizeof(TV_DISPLAY_STATE_T)); m_BcmHost.vc_tv_get_display_state(¤t_tv_state); if(current_tv_state.state & ( VC_HDMI_HDMI | VC_HDMI_DVI )) { //HDMI or DVI on m_display_aspect = get_display_aspect_ratio((HDMI_ASPECT_T)current_tv_state.display.hdmi.aspect_ratio); } else { //composite on m_display_aspect = get_display_aspect_ratio((SDTV_ASPECT_T)current_tv_state.display.sdtv.display_options.aspect); } m_display_aspect *= (float)current_tv_state.display.hdmi.height/(float)current_tv_state.display.hdmi.width; if (m_tilemap != NULL) { PwIntRect screen; PWRECT_SET0(screen, current_tv_state.display.hdmi.width, current_tv_state.display.hdmi.height); pwtilemap_set_screen(m_tilemap, &screen); } // seek on start if (m_seek_pos !=0 && m_omx_reader.CanSeek()) { if (! m_quiet) printf("Seeking start of video to %i seconds\n", m_seek_pos); m_omx_reader.SeekTime(m_seek_pos * 1000.0f, 0, &startpts); // from seconds to DVD_TIME_BASE } if(m_has_video && !m_player_video.Open(m_hints_video, m_av_clock, m_tilemap, DestRect, ! m_quiet, m_Deinterlace, m_bMpeg, m_hdmi_clock_sync, m_thread_player, m_display_aspect)) goto do_exit; { std::vector<Subtitle> external_subtitles; if(m_has_external_subtitles && !ReadSrt(m_external_subtitles_path, external_subtitles)) { puts("Unable to read the subtitle file."); goto do_exit; } if(m_has_subtitle && !m_player_subtitles.Open(m_omx_reader.SubtitleStreamCount(), std::move(external_subtitles), m_font_path, m_font_size, m_centered, m_subtitle_lines, m_av_clock)) goto do_exit; } if(m_has_subtitle) { if(!m_has_external_subtitles) { if(m_subtitle_index != -1) { m_player_subtitles.SetActiveStream( std::min(m_subtitle_index, m_omx_reader.SubtitleStreamCount()-1)); } m_player_subtitles.SetUseExternalSubtitles(false); } if(m_subtitle_index == -1 && !m_has_external_subtitles) m_player_subtitles.SetVisible(false); } m_omx_reader.GetHints(OMXSTREAM_AUDIO, m_hints_audio); if (deviceString == "") { if (m_BcmHost.vc_tv_hdmi_audio_supported(EDID_AudioFormat_ePCM, 2, EDID_AudioSampleRate_e44KHz, EDID_AudioSampleSize_16bit ) == 0) deviceString = "omx:hdmi"; else deviceString = "omx:local"; } if(m_has_audio && !m_player_audio.Open(m_hints_audio, m_av_clock, &m_omx_reader, deviceString, m_passthrough, m_initialVolume, m_use_hw_audio, m_boost_on_downmix, m_thread_player)) goto do_exit; m_av_clock->SetSpeed(DVD_PLAYSPEED_NORMAL); m_av_clock->OMXStateExecute(); m_av_clock->OMXStart(0.0); struct timespec starttime, endtime; if (! m_quiet) PrintSubtitleInfo(); while(!m_stop) { //verifie le temps de fin struct timeval now; gettimeofday(&now, NULL); if(now.tv_sec > m_dateEnd) { Stop(); goto do_exit; } if(SyncVideo::g_abort) goto do_exit; // #if WANT_KEYS // int ch[8]; // int chnum = 0; // #endif // #if WANT_KEYS // while((ch[chnum] = getchar()) != EOF) chnum++; // if (chnum > 1) ch[0] = ch[chnum - 1] | (ch[chnum - 2] << 8); // switch(ch[0]) // { // case 'z': // m_tv_show_info = !m_tv_show_info; // vc_tv_show_info(m_tv_show_info); // break; // case '1': // SetSpeed(m_av_clock->OMXPlaySpeed() - 1); // break; // case '2': // SetSpeed(m_av_clock->OMXPlaySpeed() + 1); // break; // case 'j': // if(m_has_audio) // { // int new_index = m_omx_reader.GetAudioIndex() - 1; // if (new_index >= 0) // m_omx_reader.SetActiveStream(OMXSTREAM_AUDIO, new_index); // } // break; // case 'k': // if(m_has_audio) // m_omx_reader.SetActiveStream(OMXSTREAM_AUDIO, m_omx_reader.GetAudioIndex() + 1); // break; // case 'i': // if(m_omx_reader.GetChapterCount() > 0) // { // m_omx_reader.SeekChapter(m_omx_reader.GetChapter() - 1, &startpts); // FlushStreams(startpts); // } // else // { // m_incr = -600.0; // } // break; // case 'o': // if(m_omx_reader.GetChapterCount() > 0) // { // m_omx_reader.SeekChapter(m_omx_reader.GetChapter() + 1, &startpts); // FlushStreams(startpts); // } // else // { // m_incr = 600.0; // } // break; // case 'n': // if(m_has_subtitle) // { // if(!m_player_subtitles.GetUseExternalSubtitles()) // { // if (m_player_subtitles.GetActiveStream() == 0) // { // if(m_has_external_subtitles) // m_player_subtitles.SetUseExternalSubtitles(true); // } // else // { // m_player_subtitles.SetActiveStream( // m_player_subtitles.GetActiveStream()-1); // } // } // m_player_subtitles.SetVisible(true); // PrintSubtitleInfo(); // } // break; // case 'm': // if(m_has_subtitle) // { // if(m_player_subtitles.GetUseExternalSubtitles()) // { // if(m_omx_reader.SubtitleStreamCount()) // { // assert(m_player_subtitles.GetActiveStream() == 0); // m_player_subtitles.SetUseExternalSubtitles(false); // } // } // else // { // auto new_index = m_player_subtitles.GetActiveStream()+1; // if(new_index < (size_t) m_omx_reader.SubtitleStreamCount()) // m_player_subtitles.SetActiveStream(new_index); // } // m_player_subtitles.SetVisible(true); // PrintSubtitleInfo(); // } // break; // case 's': // if(m_has_subtitle) // { // m_player_subtitles.SetVisible(!m_player_subtitles.GetVisible()); // PrintSubtitleInfo(); // } // break; // case 'd': // if(m_has_subtitle && m_player_subtitles.GetVisible()) // { // m_player_subtitles.SetDelay(m_player_subtitles.GetDelay() - 250); // PrintSubtitleInfo(); // } // break; // case 'f': // if(m_has_subtitle && m_player_subtitles.GetVisible()) // { // m_player_subtitles.SetDelay(m_player_subtitles.GetDelay() + 250); // PrintSubtitleInfo(); // } // break; // case 'q': case 27: // m_stop = true; // goto do_exit; // break; // case 0x5b44: // key left // if(m_omx_reader.CanSeek()) m_incr = -30.0; // break; // case 0x5b43: // key right // if(m_omx_reader.CanSeek()) m_incr = 30.0; // break; // case 0x5b41: // key up // if(m_omx_reader.CanSeek()) m_incr = 600.0; // break; // case 0x5b42: // key down // if(m_omx_reader.CanSeek()) m_incr = -600.0; // break; // case ' ': // case 'p': // m_Pause = !m_Pause; // if(m_Pause) // { // SetSpeed(OMX_PLAYSPEED_PAUSE); // m_av_clock->OMXPause(); // if(m_has_subtitle) // m_player_subtitles.Pause(); // } // else // { // if(m_has_subtitle) // m_player_subtitles.Resume(); // SetSpeed(OMX_PLAYSPEED_NORMAL); // m_av_clock->OMXResume(); // } // break; // case '-': // m_player_audio.SetCurrentVolume(m_player_audio.GetCurrentVolume() - 300); // if (! m_quiet) // printf("Current Volume: %.2fdB\n", m_player_audio.GetCurrentVolume() / 100.0f); // break; // case '+': case '=': // m_player_audio.SetCurrentVolume(m_player_audio.GetCurrentVolume() + 300); // if (! m_quiet) // printf("Current Volume: %.2fdB\n", m_player_audio.GetCurrentVolume() / 100.0f); // break; // default: // break; // } // #endif /* WANT_KEYS */ if(m_Pause) { OMXClock::OMXSleep(2); continue; } if(m_incr != 0 && !m_bMpeg) { int seek_flags = 0; double seek_pos = 0; double pts = 0; if(m_has_subtitle) m_player_subtitles.Pause(); m_av_clock->OMXStop(); pts = m_av_clock->GetPTS(); seek_pos = (pts / DVD_TIME_BASE) + m_incr; seek_flags = m_incr < 0.0f ? AVSEEK_FLAG_BACKWARD : 0; seek_pos *= 1000.0f; m_incr = 0; if(m_omx_reader.SeekTime(seek_pos, seek_flags, &startpts)) FlushStreams(startpts); m_player_video.Close(); if(m_has_video && !m_player_video.Open(m_hints_video, m_av_clock, m_tilemap, DestRect, ! m_quiet, m_Deinterlace, m_bMpeg, m_hdmi_clock_sync, m_thread_player, m_display_aspect)) goto do_exit; m_av_clock->OMXStart(startpts); if(m_has_subtitle) m_player_subtitles.Resume(); } /* player got in an error state */ if(m_player_audio.Error()) { fprintf(stderr, "audio player error. emergency exit!!!\n"); goto do_exit; } if(m_stats) { printf("V : %8.02f %8d %8d A : %8.02f %8.02f Cv : %8d Ca : %8d \r", m_av_clock->OMXMediaTime(), m_player_video.GetDecoderBufferSize(), m_player_video.GetDecoderFreeSpace(), m_player_audio.GetCurrentPTS() / DVD_TIME_BASE, m_player_audio.GetDelay(), m_player_video.GetCached(), m_player_audio.GetCached()); } //DEBUT LOOP if(m_loop && m_omx_reader.IsEof() && !m_omx_pkt && m_isOver) { m_isOver = false; CLog::Log(LOGINFO, "EOF detected; looping requested"); printf("RESTART !!\n"); m_incr = -DBL_MAX; m_first= true; struct timeval now; gettimeofday(&now, NULL); m_dateStart += (m_omx_reader.GetStreamLength()/1000) + 2 - m_seek_pos; printf("length of stream %i\n", m_omx_reader.GetStreamLength()/1000); printf("seek %i\n", m_seek_pos); m_seek_pos = 0; } if(m_omx_reader.IsEof() && !m_omx_pkt) { if (!m_player_audio.GetCached() && !m_player_video.GetCached()) { if(m_loop) { cout << "abort ABORT !!" << endl; m_isOver = true; if(m_has_audio) m_player_audio.WaitCompletion(); else if(m_has_video) m_player_video.WaitCompletion(); }else { break; } } // Abort audio buffering, now we're on our own if (m_buffer_empty && m_first) { printf("en attente (empty buffer)\n"); m_timer.SleepUntilTime(m_dateStart); printf("GO\n"); m_av_clock->OMXResume(); m_first = false; } OMXClock::OMXSleep(10); continue; } /* when the audio buffer runs under 0.1 seconds we buffer up */ if(m_has_audio) { if(m_player_audio.GetDelay() < 0.1f && !m_buffer_empty) { if(!m_av_clock->OMXIsPaused()) { m_av_clock->OMXPause(); //printf("buffering start\n"); m_buffer_empty = true; clock_gettime(CLOCK_REALTIME, &starttime); } } // printf("A\n"); if(m_player_audio.GetDelay() > (AUDIO_BUFFER_SECONDS * 0.75f) && m_buffer_empty) { if(m_av_clock->OMXIsPaused()) { printf("en attente\n"); m_timer.SleepUntilTime(m_dateStart); m_av_clock->OMXResume(); printf("GO\n"); m_buffer_empty = false; } } if(m_buffer_empty) { clock_gettime(CLOCK_REALTIME, &endtime); if((endtime.tv_sec - starttime.tv_sec) > 1) { m_buffer_empty = false; m_av_clock->OMXResume(); //printf("buffering timed out\n"); } } } if(!m_omx_pkt) m_omx_pkt = m_omx_reader.Read(); if(m_has_video && m_omx_pkt && m_omx_reader.IsActive(OMXSTREAM_VIDEO, m_omx_pkt->stream_index)) { if(m_player_video.AddPacket(m_omx_pkt)) m_omx_pkt = NULL; else OMXClock::OMXSleep(10); if(m_tv_show_info) { char response[80]; vc_gencmd(response, sizeof response, "render_bar 4 video_fifo %d %d %d %d", m_player_video.GetDecoderBufferSize()-m_player_video.GetDecoderFreeSpace(), 0 , 0, m_player_video.GetDecoderBufferSize()); vc_gencmd(response, sizeof response, "render_bar 5 audio_fifo %d %d %d %d", (int)(100.0*m_player_audio.GetDelay()), 0, 0, 100*AUDIO_BUFFER_SECONDS); } } else if(m_has_audio && m_omx_pkt && m_omx_pkt->codec_type == AVMEDIA_TYPE_AUDIO) { if(m_player_audio.AddPacket(m_omx_pkt)) m_omx_pkt = NULL; else OMXClock::OMXSleep(10); } else if(m_has_subtitle && m_omx_pkt && m_omx_pkt->codec_type == AVMEDIA_TYPE_SUBTITLE) { auto result = m_player_subtitles.AddPacket(m_omx_pkt, m_omx_reader.GetRelativeIndex(m_omx_pkt->stream_index)); if (result) m_omx_pkt = NULL; else OMXClock::OMXSleep(10); } else { if(m_omx_pkt) { m_omx_reader.FreePacket(m_omx_pkt); m_omx_pkt = NULL; } } } do_exit: if (m_stats) printf("\n"); if(!m_stop && !SyncVideo::g_abort) { cout << "WAIT" << endl; if(m_has_audio) m_player_audio.WaitCompletion(); else if(m_has_video) m_player_video.WaitCompletion(); cout << "WAIT OVER" << endl; } if(m_has_video && m_refresh && tv_state.display.hdmi.group && tv_state.display.hdmi.mode) { m_BcmHost.vc_tv_hdmi_power_on_explicit_new(HDMI_MODE_HDMI, (HDMI_RES_GROUP_T)tv_state.display.hdmi.group, tv_state.display.hdmi.mode); } m_av_clock->OMXStop(); m_av_clock->OMXStateIdle(); m_player_subtitles.Close(); m_player_video.Close(); m_player_audio.Close(); if(m_omx_pkt) { m_omx_reader.FreePacket(m_omx_pkt); m_omx_pkt = NULL; } m_omx_reader.Close(); vc_tv_show_info(0); g_OMX.Deinitialize(); g_RBP.Deinitialize(); if (! m_quiet) printf("have a nice day ;)\n"); return 1; }
//int main(int argc, char *argv[]) int startVideo(OMX_TextureProvider* provider, OMX_VideoSurfaceElement* element) { #ifdef ENABLE_ORIGINAL signal(SIGINT, sig_handler); if (isatty(STDIN_FILENO)) { struct termios new_termios; tcgetattr(STDIN_FILENO, &orig_termios); new_termios = orig_termios; new_termios.c_lflag &= ~(ICANON | ECHO | ECHOCTL | ECHONL); new_termios.c_cflag |= HUPCL; new_termios.c_cc[VMIN] = 0; tcsetattr(STDIN_FILENO, TCSANOW, &new_termios); atexit(restore_termios); } else { orig_fl = fcntl(STDIN_FILENO, F_GETFL); fcntl(STDIN_FILENO, F_SETFL, orig_fl | O_NONBLOCK); atexit(restore_fl); } #endif LOG_VERBOSE(LOG_TAG, "Starting video..."); std::string last_sub = ""; std::string m_filename; double m_incr = 0; CRBP g_RBP; COMXCore g_OMX; bool m_stats = false; bool m_dump_format = false; bool m_3d = false; bool m_refresh = false; double startpts = 0; m_player_video = new OMXPlayerVideo(provider); m_player_audio = new OMXPlayerAudio; m_player_subtitles = new OMXPlayerSubtitles; QObject::connect(m_player_video, SIGNAL(textureReady(uint)), element, SLOT(onTextureChanged(uint))); TV_GET_STATE_RESP_T tv_state; const int boost_on_downmix_opt = 0x200; #ifdef ENABLE_ORIGINAL struct option longopts[] = { { "info", no_argument, NULL, 'i' }, { "help", no_argument, NULL, 'h' }, { "aidx", required_argument, NULL, 'n' }, { "adev", required_argument, NULL, 'o' }, { "stats", no_argument, NULL, 's' }, { "passthrough", no_argument, NULL, 'p' }, { "deinterlace", no_argument, NULL, 'd' }, { "hw", no_argument, NULL, 'w' }, { "3d", no_argument, NULL, '3' }, { "hdmiclocksync", no_argument, NULL, 'y' }, { "refresh", no_argument, NULL, 'r' }, { "sid", required_argument, NULL, 't' }, { "pos", required_argument, NULL, 'l' }, { "font", required_argument, NULL, 0x100 }, { "font-size", required_argument, NULL, 0x101 }, { "align", required_argument, NULL, 0x102 }, { "boost-on-downmix", no_argument, NULL, boost_on_downmix_opt }, { 0, 0, 0, 0 } }; int c; while ((c = getopt_long(argc, argv, "wihnl:o:cslpd3yt:r", longopts, NULL)) != -1) { switch (c) { case 'r': m_refresh = true; break; case 'y': m_hdmi_clock_sync = true; break; case '3': m_3d = true; break; case 'd': m_Deinterlace = true; break; case 'w': m_use_hw_audio = true; break; case 'p': m_passthrough = true; break; case 's': m_stats = true; break; case 'o': deviceString = optarg; if(deviceString != "local" && deviceString != "hdmi") { print_usage(); return 0; } deviceString = "omx:" + deviceString; break; case 'i': m_dump_format = true; break; case 't': m_subtitle_index = atoi(optarg) - 1; if(m_subtitle_index < 0) m_subtitle_index = 0; m_show_subtitle = true; break; case 'n': m_audio_index_use = atoi(optarg) - 1; if(m_audio_index_use < 0) m_audio_index_use = 0; break; case 'l': m_seek_pos = atoi(optarg) ; if (m_seek_pos < 0) m_seek_pos = 0; break; case 0x100: m_font_path = optarg; break; case 0x101: { const int thousands = atoi(optarg); if (thousands > 0) m_font_size = thousands*0.001f; } break; case 0x102: if (!strcmp(optarg, "center")) m_centered = true; else m_centered = false; break; case boost_on_downmix_opt: m_boost_on_downmix = true; break; case 0: break; case 'h': print_usage(); return 0; break; case ':': return 0; break; default: return 0; break; } } if (optind >= argc) { print_usage(); return 0; } #endif //m_filename = argv[optind]; m_filename = "/home/pi/usb/big_buck_bunny_1080p_h264.mov"; #ifdef ENABLE_ORIGINAL CLog::Init("./"); #endif g_RBP.Initialize(); g_OMX.Initialize(); m_av_clock = new OMXClock(); m_thread_player = true; LOG_VERBOSE(LOG_TAG, "Opening video file..."); if(!m_omx_reader.Open(m_filename.c_str(), m_dump_format)) #if 0 goto do_exit; #endif return 0; #ifdef ENABLE_ORIGINAL if(m_dump_format) goto do_exit; #endif m_bMpeg = m_omx_reader.IsMpegVideo(); m_has_video = m_omx_reader.VideoStreamCount(); m_has_audio = m_omx_reader.AudioStreamCount(); m_has_subtitle = m_omx_reader.SubtitleStreamCount(); LOG_VERBOSE(LOG_TAG, "Initializing OMX clock..."); if(!m_av_clock->OMXInitialize(m_has_video, m_has_audio)) #if 0 goto do_exit; #endif return 0; if(m_hdmi_clock_sync && !m_av_clock->HDMIClockSync()) #if 0 goto do_exit; #endif return 0; m_omx_reader.GetHints(OMXSTREAM_AUDIO, m_hints_audio); m_omx_reader.GetHints(OMXSTREAM_VIDEO, m_hints_video); if(m_audio_index_use != -1) m_omx_reader.SetActiveStream(OMXSTREAM_AUDIO, m_audio_index_use); if(m_has_video && m_refresh) { memset(&tv_state, 0, sizeof(TV_GET_STATE_RESP_T)); m_BcmHost.vc_tv_get_state(&tv_state); if(m_filename.find("3DSBS") != string::npos) m_3d = true; SetVideoMode(m_hints_video.width, m_hints_video.height, m_hints_video.fpsrate, m_hints_video.fpsscale, m_3d); } // get display aspect TV_GET_STATE_RESP_T current_tv_state; memset(¤t_tv_state, 0, sizeof(TV_GET_STATE_RESP_T)); m_BcmHost.vc_tv_get_state(¤t_tv_state); if(current_tv_state.width && current_tv_state.height) m_display_aspect = (float)current_tv_state.width / (float)current_tv_state.height; // seek on start if (m_seek_pos !=0 && m_omx_reader.CanSeek()) { printf("Seeking start of video to %i seconds\n", m_seek_pos); m_omx_reader.SeekTime(m_seek_pos * 1000.0f, 0, &startpts); // from seconds to DVD_TIME_BASE } LOG_VERBOSE(LOG_TAG, "Opening video using OMX..."); uint textureId; if(m_has_video && !m_player_video->Open(m_hints_video, m_av_clock, textureId, m_Deinterlace, m_bMpeg, m_hdmi_clock_sync, m_thread_player, m_display_aspect)) #if 0 goto do_exit; #endif return 0; LOG_VERBOSE(LOG_TAG, "Opening subtitles using OMX..."); if(m_has_subtitle && !m_player_subtitles->Open(m_font_path, m_font_size, m_centered, m_av_clock)) #if 0 goto do_exit; #endif return 0; // This is an upper bound check on the subtitle limits. When we pulled the subtitle // index from the user we check to make sure that the value is larger than zero, but // we couldn't know without scanning the file if it was too high. If this is the case // then we replace the subtitle index with the maximum value possible. if(m_has_subtitle && m_subtitle_index > (m_omx_reader.SubtitleStreamCount() - 1)) { m_subtitle_index = m_omx_reader.SubtitleStreamCount() - 1; } // Here we actually enable the subtitle streams if we have one available. if (m_show_subtitle && m_has_subtitle && m_subtitle_index <= (m_omx_reader.SubtitleStreamCount() - 1)) m_omx_reader.SetActiveStream(OMXSTREAM_SUBTITLE, m_subtitle_index); m_omx_reader.GetHints(OMXSTREAM_AUDIO, m_hints_audio); LOG_VERBOSE(LOG_TAG, "Opening audio using OMX..."); if(m_has_audio && !m_player_audio->Open(m_hints_audio, m_av_clock, &m_omx_reader, "omx:hdmi", m_passthrough, m_use_hw_audio, m_boost_on_downmix, m_thread_player)) #if 0 goto do_exit; #endif return 0; LOG_VERBOSE(LOG_TAG, "Executing clock..."); m_av_clock->SetSpeed(DVD_PLAYSPEED_NORMAL); m_av_clock->OMXStateExecute(); m_av_clock->OMXStart(); struct timespec starttime, endtime; printf("Subtitle count : %d state %s : index %d\n", m_omx_reader.SubtitleStreamCount(), m_show_subtitle ? "on" : "off", (m_omx_reader.SubtitleStreamCount() > 0) ? m_subtitle_index + 1 : m_subtitle_index); while(!m_stop) { int ch[8]; int chnum = 0; if(g_abort) goto do_exit; #if 0 while((ch[chnum] = getchar()) != EOF) chnum++; if (chnum > 1) ch[0] = ch[chnum - 1] | (ch[chnum - 2] << 8); switch(ch[0]) { case 'z': m_tv_show_info = !m_tv_show_info; vc_tv_show_info(m_tv_show_info); break; case '1': SetSpeed(m_av_clock->OMXPlaySpeed() - 1); break; case '2': SetSpeed(m_av_clock->OMXPlaySpeed() + 1); break; case 'j': if(m_has_audio) { int new_index = m_omx_reader.GetAudioIndex() - 1; if (new_index >= 0) m_omx_reader.SetActiveStream(OMXSTREAM_AUDIO, new_index); } break; case 'k': if(m_has_audio) m_omx_reader.SetActiveStream(OMXSTREAM_AUDIO, m_omx_reader.GetAudioIndex() + 1); break; case 'i': if(m_omx_reader.GetChapterCount() > 0) { m_omx_reader.SeekChapter(m_omx_reader.GetChapter() - 1, &startpts); FlushStreams(startpts); } else { m_incr = -600.0; } break; case 'o': if(m_omx_reader.GetChapterCount() > 0) { m_omx_reader.SeekChapter(m_omx_reader.GetChapter() + 1, &startpts); FlushStreams(startpts); } else { m_incr = 600.0; } break; case 'n': if(m_has_subtitle) { int new_index = m_subtitle_index-1; if(new_index >= 0) { m_subtitle_index = new_index; printf("Subtitle count : %d state %s : index %d\n", m_omx_reader.SubtitleStreamCount(), m_show_subtitle ? "on" : "off", (m_omx_reader.SubtitleStreamCount() > 0) ? m_subtitle_index + 1 : m_subtitle_index); m_omx_reader.SetActiveStream(OMXSTREAM_SUBTITLE, m_subtitle_index); m_player_subtitles->Flush(); } } break; case 'm': if(m_has_subtitle) { int new_index = m_subtitle_index+1; if(new_index < m_omx_reader.SubtitleStreamCount()) { m_subtitle_index = new_index; printf("Subtitle count : %d state %s : index %d\n", m_omx_reader.SubtitleStreamCount(), m_show_subtitle ? "on" : "off", (m_omx_reader.SubtitleStreamCount() > 0) ? m_subtitle_index + 1 : m_subtitle_index); m_omx_reader.SetActiveStream(OMXSTREAM_SUBTITLE, m_subtitle_index); m_player_subtitles->Flush(); } } break; case 's': if(m_has_subtitle) { if(m_show_subtitle) { m_omx_reader.SetActiveStream(OMXSTREAM_SUBTITLE, -1); m_player_subtitles->Flush(); m_show_subtitle = false; } else { m_omx_reader.SetActiveStream(OMXSTREAM_SUBTITLE, m_subtitle_index); m_show_subtitle = true; } printf("Subtitle count : %d state %s : index %d\n", m_omx_reader.SubtitleStreamCount(), m_show_subtitle ? "on" : "off", (m_omx_reader.SubtitleStreamCount() > 0) ? m_subtitle_index + 1 : m_subtitle_index); } break; case 'q': m_stop = true; goto do_exit; break; case 0x5b44: // key left if(m_omx_reader.CanSeek()) m_incr = -30.0; break; case 0x5b43: // key right if(m_omx_reader.CanSeek()) m_incr = 30.0; break; case 0x5b41: // key up if(m_omx_reader.CanSeek()) m_incr = 600.0; break; case 0x5b42: // key down if(m_omx_reader.CanSeek()) m_incr = -600.0; break; case ' ': case 'p': m_Pause = !m_Pause; if(m_Pause) { SetSpeed(OMX_PLAYSPEED_PAUSE); m_av_clock->OMXPause(); } else { SetSpeed(OMX_PLAYSPEED_NORMAL); m_av_clock->OMXResume(); } break; case '-': m_player_audio->SetCurrentVolume(m_player_audio->GetCurrentVolume() - 300); printf("Current Volume: %.2fdB\n", m_player_audio->GetCurrentVolume() / 100.0f); break; case '+': m_player_audio->SetCurrentVolume(m_player_audio->GetCurrentVolume() + 300); printf("Current Volume: %.2fdB\n", m_player_audio->GetCurrentVolume() / 100.0f); break; default: break; } #endif if(m_Pause) { OMXClock::OMXSleep(2); continue; } if(m_incr != 0 && !m_bMpeg) { int seek_flags = 0; double seek_pos = 0; double pts = 0; pts = m_av_clock->GetPTS(); seek_pos = (pts / DVD_TIME_BASE) + m_incr; seek_flags = m_incr < 0.0f ? AVSEEK_FLAG_BACKWARD : 0; seek_pos *= 1000.0f; m_incr = 0; if(m_omx_reader.SeekTime(seek_pos, seek_flags, &startpts)) FlushStreams(startpts); m_player_video->Close(); if(m_has_video && !m_player_video->Open(m_hints_video, m_av_clock, textureId, m_Deinterlace, m_bMpeg, m_hdmi_clock_sync, m_thread_player, m_display_aspect)) goto do_exit; } /* player got in an error state */ if(m_player_audio->Error()) { printf("audio player error. emergency exit!!!\n"); goto do_exit; } if(m_stats) { printf("V : %8.02f %8d %8d A : %8.02f %8.02f Cv : %8d Ca : %8d \r", m_av_clock->OMXMediaTime(), m_player_video->GetDecoderBufferSize(), m_player_video->GetDecoderFreeSpace(), m_player_audio->GetCurrentPTS() / DVD_TIME_BASE, m_player_audio->GetDelay(), m_player_video->GetCached(), m_player_audio->GetCached()); } if(m_omx_reader.IsEof() && !m_omx_pkt) { if (!m_player_audio->GetCached() && !m_player_video->GetCached()) break; // Abort audio buffering, now we're on our own if (m_buffer_empty) m_av_clock->OMXResume(); OMXClock::OMXSleep(10); continue; } /* when the audio buffer runs under 0.1 seconds we buffer up */ if(m_has_audio) { if(m_player_audio->GetDelay() < 0.1f && !m_buffer_empty) { if(!m_av_clock->OMXIsPaused()) { m_av_clock->OMXPause(); //printf("buffering start\n"); m_buffer_empty = true; clock_gettime(CLOCK_REALTIME, &starttime); } } if(m_player_audio->GetDelay() > (AUDIO_BUFFER_SECONDS * 0.75f) && m_buffer_empty) { if(m_av_clock->OMXIsPaused()) { m_av_clock->OMXResume(); //printf("buffering end\n"); m_buffer_empty = false; } } if(m_buffer_empty) { clock_gettime(CLOCK_REALTIME, &endtime); if((endtime.tv_sec - starttime.tv_sec) > 1) { m_buffer_empty = false; m_av_clock->OMXResume(); //printf("buffering timed out\n"); } } } if(!m_omx_pkt) m_omx_pkt = m_omx_reader.Read(); if(m_has_video && m_omx_pkt && m_omx_reader.IsActive(OMXSTREAM_VIDEO, m_omx_pkt->stream_index)) { if(m_player_video->AddPacket(m_omx_pkt)) m_omx_pkt = NULL; else OMXClock::OMXSleep(10); if(m_tv_show_info) { char response[80]; vc_gencmd(response, sizeof response, "render_bar 4 video_fifo %d %d %d %d", m_player_video->GetDecoderBufferSize()-m_player_video->GetDecoderFreeSpace(), 0 , 0, m_player_video->GetDecoderBufferSize()); vc_gencmd(response, sizeof response, "render_bar 5 audio_fifo %d %d %d %d", (int)(100.0*m_player_audio->GetDelay()), 0, 0, 100*AUDIO_BUFFER_SECONDS); } } else if(m_has_audio && m_omx_pkt && m_omx_pkt->codec_type == AVMEDIA_TYPE_AUDIO) { if(m_player_audio->AddPacket(m_omx_pkt)) m_omx_pkt = NULL; else OMXClock::OMXSleep(10); } else if(m_omx_pkt && m_omx_reader.IsActive(OMXSTREAM_SUBTITLE, m_omx_pkt->stream_index)) { if(m_omx_pkt->size && m_show_subtitle && (m_omx_pkt->hints.codec == CODEC_ID_TEXT || m_omx_pkt->hints.codec == CODEC_ID_SSA)) { if(m_player_subtitles->AddPacket(m_omx_pkt)) m_omx_pkt = NULL; else OMXClock::OMXSleep(10); } else { m_omx_reader.FreePacket(m_omx_pkt); m_omx_pkt = NULL; } } else { if(m_omx_pkt) { m_omx_reader.FreePacket(m_omx_pkt); m_omx_pkt = NULL; } } } do_exit: printf("\n"); if(!m_stop && !g_abort) { if(m_has_audio) m_player_audio->WaitCompletion(); else if(m_has_video) m_player_video->WaitCompletion(); } if(m_refresh) { m_BcmHost.vc_tv_hdmi_power_on_best(tv_state.width, tv_state.height, tv_state.frame_rate, HDMI_NONINTERLACED, (EDID_MODE_MATCH_FLAG_T)(HDMI_MODE_MATCH_FRAMERATE|HDMI_MODE_MATCH_RESOLUTION|HDMI_MODE_MATCH_SCANMODE)); } m_av_clock->OMXStop(); m_av_clock->OMXStateIdle(); m_player_subtitles->Close(); m_player_video->Close(); m_player_audio->Close(); if(m_omx_pkt) { m_omx_reader.FreePacket(m_omx_pkt); m_omx_pkt = NULL; } m_omx_reader.Close(); vc_tv_show_info(0); g_OMX.Deinitialize(); g_RBP.Deinitialize(); printf("have a nice day ;)\n"); return 1; }