diff --git a/KeyConfig.cpp b/KeyConfig.cpp index 200022cf..0e5b5831 100644 --- a/KeyConfig.cpp +++ b/KeyConfig.cpp @@ -58,7 +58,10 @@ int convertStringToAction(string str_action) return KeyConfig::ACTION_SEEK_FORWARD_LARGE; if(str_action == "STEP") return KeyConfig::ACTION_STEP; - + if(str_action == "ROTATE") + return KeyConfig::ACTION_ROTATE; + if(str_action == "MUTE_AUDIO") + return KeyConfig::ACTION_MUTE_AUDIO; return -1; } /* Grabs the substring prior to the ':', this is the Action */ @@ -94,8 +97,8 @@ map KeyConfig::buildDefaultKeymap() { map keymap; - keymap['1'] = ACTION_DECREASE_SPEED; - keymap['2'] = ACTION_INCREASE_SPEED; + keymap['/'] = ACTION_DECREASE_SPEED; + keymap['*'] = ACTION_INCREASE_SPEED; keymap['<'] = ACTION_REWIND; keymap[','] = ACTION_REWIND; keymap['>'] = ACTION_FAST_FORWARD; @@ -122,6 +125,8 @@ map KeyConfig::buildDefaultKeymap() keymap[KEY_DOWN] = ACTION_SEEK_BACK_LARGE; keymap[KEY_UP] = ACTION_SEEK_FORWARD_LARGE; keymap['v'] = ACTION_STEP; + keymap['r'] = ACTION_ROTATE; + keymap['a'] = ACTION_MUTE_AUDIO; return keymap; } diff --git a/KeyConfig.h b/KeyConfig.h index 95e91833..530faeba 100644 --- a/KeyConfig.h +++ b/KeyConfig.h @@ -30,7 +30,9 @@ class KeyConfig ACTION_SEEK_BACK_LARGE, ACTION_SEEK_FORWARD_LARGE, ACTION_STEP, - ACTION_BLANK + ACTION_BLANK, + ACTION_ROTATE, + ACTION_MUTE_AUDIO }; #define KEY_LEFT 0x5b44 diff --git a/OMXPlayerVideo.cpp b/OMXPlayerVideo.cpp index d7c7c5f3..e822655e 100644 --- a/OMXPlayerVideo.cpp +++ b/OMXPlayerVideo.cpp @@ -152,6 +152,12 @@ bool OMXPlayerVideo::Open(COMXStreamInfo &hints, OMXClock *av_clock, const CRect return true; } +void OMXPlayerVideo::SetOrientation(int orientation) +{ + m_hints.orientation = orientation; + if(m_decoder) m_decoder->SetOrientation(orientation); +} + bool OMXPlayerVideo::Close() { m_bAbort = true; diff --git a/OMXPlayerVideo.h b/OMXPlayerVideo.h index c2e92eed..9130f4ca 100644 --- a/OMXPlayerVideo.h +++ b/OMXPlayerVideo.h @@ -95,6 +95,7 @@ class OMXPlayerVideo : public OMXThread ~OMXPlayerVideo(); bool Open(COMXStreamInfo &hints, OMXClock *av_clock, const CRect& DestRect, EDEINTERLACEMODE deinterlace, bool hdmi_clock_sync, bool use_thread, float display_aspect, float queue_size, float fifo_size); + void SetOrientation(int orientation); bool Close(); bool Decode(OMXPacket *pkt); void Process(); diff --git a/OMXReader.cpp b/OMXReader.cpp index 40ab67ef..b1945829 100644 --- a/OMXReader.cpp +++ b/OMXReader.cpp @@ -818,6 +818,17 @@ bool OMXReader::GetHints(AVStream *stream, COMXStreamInfo *hints) hints->height = stream->codec->height; hints->profile = stream->codec->profile; + //FCC : Stream Orientation + hints->orientation = 0; +#if LIBAVFORMAT_VERSION_INT >= AV_VERSION_INT(52,83,0) + AVDictionaryEntry *rotTag = m_dllAvUtil.av_dict_get(stream->metadata,"rotate", NULL, 0); + if (rotTag) + hints->orientation = atoi(rotTag->value); +#else + hints->orientation = atoi(stream->rotate); +#endif + CLog::Log(LOGDEBUG, "COMXPlayer::OpenFile - Orientation %d", hints->orientation); + if(stream->codec->codec_type == AVMEDIA_TYPE_VIDEO) { hints->fpsrate = stream->r_frame_rate.num; diff --git a/OMXStreamInfo.cpp b/OMXStreamInfo.cpp index 781e8106..af21690f 100644 --- a/OMXStreamInfo.cpp +++ b/OMXStreamInfo.cpp @@ -64,6 +64,8 @@ void COMXStreamInfo::Clear() bitrate = 0; bitspersample = 0; + orientation = 0; + identifier = 0; framesize = 0; diff --git a/OMXStreamInfo.h b/OMXStreamInfo.h index d95f5606..475911e1 100644 --- a/OMXStreamInfo.h +++ b/OMXStreamInfo.h @@ -58,6 +58,7 @@ class COMXStreamInfo int level; // encoder level of the stream reported by the decoder. used to qualify hw decoders. int profile; // encoder profile of the stream reported by the decoder. used to qualify hw decoders. bool ptsinvalid; // pts cannot be trusted (avi's). + int orientation; // orientation of the video in degress counter clockwise // AUDIO int channels; diff --git a/OMXVideo.cpp b/OMXVideo.cpp index 3270d735..40012f72 100644 --- a/OMXVideo.cpp +++ b/OMXVideo.cpp @@ -724,7 +724,7 @@ bool COMXVideo::Open(COMXStreamInfo &hints, OMXClock *clock, const CRect &DestRe m_setStartTime = true; m_setStartTimeText = true; - switch(0) + switch(hints.orientation) { case 90: m_transform = OMX_DISPLAY_ROT90; @@ -758,6 +758,32 @@ bool COMXVideo::Open(COMXStreamInfo &hints, OMXClock *clock, const CRect &DestRe return true; } +void COMXVideo::SetOrientation(int orientation) +{ + switch(orientation) + { + case 90: + m_transform = OMX_DISPLAY_ROT90; + break; + case 180: + m_transform = OMX_DISPLAY_ROT180; + break; + case 270: + m_transform = OMX_DISPLAY_ROT270; + break; + default: + m_transform = OMX_DISPLAY_ROT0; + break; + } + OMX_CONFIG_DISPLAYREGIONTYPE configDisplay; + OMX_INIT_STRUCTURE(configDisplay); + configDisplay.nPortIndex = m_omx_render.GetInputPort(); + + configDisplay.set = OMX_DISPLAY_SET_TRANSFORM; + configDisplay.transform = m_transform; + m_omx_render.SetConfig(OMX_IndexConfigDisplayRegion, &configDisplay); +} + void COMXVideo::Close() { m_omx_tunnel_decoder.Flush(); diff --git a/OMXVideo.h b/OMXVideo.h index c1f5fbf8..0d28903a 100644 --- a/OMXVideo.h +++ b/OMXVideo.h @@ -56,6 +56,7 @@ class COMXVideo bool NaluFormatStartCodes(enum AVCodecID codec, uint8_t *in_extradata, int in_extrasize); bool Open(COMXStreamInfo &hints, OMXClock *clock, const CRect &m_DestRect, float display_aspect = 0.0f, EDEINTERLACEMODE deinterlace = VS_DEINTERLACEMODE_OFF, bool hdmi_clock_sync = false, float fifo_size = 0.0f); bool PortSettingsChanged(); + void SetOrientation(int orientation); void Close(void); unsigned int GetFreeSpace(); unsigned int GetSize(); diff --git a/omxplayer b/omxplayer index db650d0a..18724956 100755 --- a/omxplayer +++ b/omxplayer @@ -41,12 +41,33 @@ if [ -e $FBSET ]; then fbset -xres 1 -yres 1 fi -if test -z "$DBUS_SESSION_BUS_ADDRESS"; then - eval $(dbus-launch --sh-syntax) -fi +exec 5> omxplayer.address +exec 6> omxplayer.pid + +cleanup () +{ + pid=`head -n1 omxplayer.pid` + if test -n "$pid" ; then + kill -INT "$pid" + fi + rm -f omxplayer.address + rm -f omxplayer.pid +} + +trap cleanup INT HUP TERM + +dbus-daemon --fork --print-address 5 --print-pid 6 --session + +DBUS_SESSION_BUS_ADDRESS="`cat omxplayer.address`" +export DBUS_SESSION_BUS_ADDRESS +DBUS_SESSION_BUS_PID="`cat omxplayer.pid`" +export DBUS_SESSION_BUS_PID $OMXPLAYER --font $FONT --italic-font $ITALIC_FONT "$@" +trap - INT HUP TERM +cleanup + if [ -e $FBSET ]; then fbset -xres ${XRES} -yres ${YRES} echo 1 > /sys/class/vtconsole/vtcon1/bind diff --git a/omxplayer.cpp b/omxplayer.cpp index 400ac6c7..97bf904a 100644 --- a/omxplayer.cpp +++ b/omxplayer.cpp @@ -79,7 +79,9 @@ enum PCMChannels *m_pChannelMap = NULL; volatile sig_atomic_t g_abort = false; bool m_passthrough = false; long m_Volume = 0; +DISPMANX_ELEMENT_HANDLE_T element_Video = DISPMANX_NO_HANDLE; long m_Amplification = 0; +bool m_Mute_Audio = false; bool m_Deinterlace = false; bool m_NoDeinterlace = false; bool m_HWDecode = false; @@ -163,6 +165,7 @@ void print_usage() printf(" -g / --genlog generate log file\n"); printf(" -l / --pos n start position (in seconds)\n"); printf(" -b / --blank set background to black\n"); + printf(" --orientation n set Video rotation, (eg. 0/90/180/270) (default 0)\n"); printf(" --boost-on-downmix boost volume when downmixing\n"); printf(" --vol n Set initial volume in millibels (default 0)\n"); printf(" --amp n Set initial amplification in millibels (default 0)\n"); @@ -474,10 +477,8 @@ static int get_mem_gpu(void) return gpu_mem; } -static void blank_background(bool enable) +static DISPMANX_ELEMENT_HANDLE_T blank_omx(int layer) { - if (!enable) - return; // we create a 1x1 black pixel image that is added to display just behind video DISPMANX_DISPLAY_HANDLE_T display; DISPMANX_UPDATE_HANDLE_T update; @@ -499,7 +500,7 @@ static void blank_background(bool enable) vc_dispmanx_rect_set( &dst_rect, 0, 0, 1, 1); ret = vc_dispmanx_resource_write_data( resource, type, sizeof(image), &image, &dst_rect ); - assert(ret == 0); + assert(ret == DISPMANX_SUCCESS); vc_dispmanx_rect_set( &src_rect, 0, 0, 1<<16, 1<<16); vc_dispmanx_rect_set( &dst_rect, 0, 0, 0, 0); @@ -507,12 +508,53 @@ static void blank_background(bool enable) update = vc_dispmanx_update_start(0); assert(update); - element = vc_dispmanx_element_add(update, display, -1 /*layer*/, &dst_rect, resource, &src_rect, + element = vc_dispmanx_element_add(update, display, layer, &dst_rect, resource, &src_rect, DISPMANX_PROTECTION_NONE, NULL, NULL, (DISPMANX_TRANSFORM_T)0 ); assert(element); - + ret = vc_dispmanx_update_submit_sync( update ); - assert( ret == 0 ); + assert( ret == DISPMANX_SUCCESS ); + + ret = vc_dispmanx_resource_delete( resource ); + assert( ret == DISPMANX_SUCCESS ); + + return element; +} + +static void blank_background(bool enable) +{ + DISPMANX_ELEMENT_HANDLE_T element; + + if (!enable) + return; + + element = blank_omx(m_layer - 1); + assert(element); +} + +static void blank_video(bool mute) +{ + DISPMANX_UPDATE_HANDLE_T update; + int ret; + + if (mute) { + element_Video = blank_omx(m_layer + 1); + assert(element_Video); + } + else { + if (element_Video != DISPMANX_NO_HANDLE) { + update = vc_dispmanx_update_start(0); + assert(update); + + ret = vc_dispmanx_element_remove(update, element_Video); + assert( ret == DISPMANX_SUCCESS ); + + ret = vc_dispmanx_update_submit_sync( update ); + assert( ret == DISPMANX_SUCCESS ); + + element_Video = DISPMANX_NO_HANDLE; + } + } } int main(int argc, char *argv[]) @@ -536,7 +578,9 @@ int main(int argc, char *argv[]) double startpts = 0; CRect DestRect = {0,0,0,0}; bool m_blank_background = false; - bool sentStarted = false; + bool sentStarted = false; + int m_orientation = 0; + bool m_has_orientation = false; float audio_fifo_size = 0.0; // zero means use default float video_fifo_size = 0.0; float audio_queue_size = 0.0; @@ -563,6 +607,8 @@ int main(int argc, char *argv[]) const int key_config_opt = 0x10d; const int amp_opt = 0x10e; const int no_osd_opt = 0x202; + + const int orientation_opt = 0x400; struct option longopts[] = { { "info", no_argument, NULL, 'i' }, @@ -602,6 +648,7 @@ int main(int argc, char *argv[]) { "boost-on-downmix", no_argument, NULL, boost_on_downmix_opt }, { "key-config", required_argument, NULL, key_config_opt }, { "no-osd", no_argument, NULL, no_osd_opt }, + { "orientation", required_argument, NULL, orientation_opt }, { 0, 0, 0, 0 } }; @@ -730,19 +777,23 @@ int main(int argc, char *argv[]) m_boost_on_downmix = true; break; case audio_fifo_opt: - audio_fifo_size = atof(optarg); + audio_fifo_size = atof(optarg); break; case video_fifo_opt: - video_fifo_size = atof(optarg); + video_fifo_size = atof(optarg); break; case audio_queue_opt: - audio_queue_size = atof(optarg); + audio_queue_size = atof(optarg); break; case video_queue_opt: - video_queue_size = atof(optarg); + video_queue_size = atof(optarg); break; case threshold_opt: - m_threshold = atof(optarg); + m_threshold = atof(optarg); + break; + case orientation_opt: + m_has_orientation = true; + m_orientation = atoi(optarg); break; case 'b': m_blank_background = true; @@ -924,7 +975,11 @@ int main(int argc, char *argv[]) printf("Seeking start of video to %i seconds\n", m_seek_pos); m_omx_reader.SeekTime(m_seek_pos * 1000.0f, false, &startpts); // from seconds to DVD_TIME_BASE } - + + // insert orientation + if(m_has_orientation) + m_hints_video.orientation = m_orientation; + if(m_has_video && !m_player_video.Open(m_hints_video, m_av_clock, DestRect, m_Deinterlace ? VS_DEINTERLACEMODE_FORCE:m_NoDeinterlace ? VS_DEINTERLACEMODE_OFF:VS_DEINTERLACEMODE_AUTO, m_hdmi_clock_sync, m_thread_player, m_display_aspect, video_queue_size, video_fifo_size)) goto do_exit; @@ -1070,6 +1125,14 @@ int main(int argc, char *argv[]) printf("Playspeed %.3f\n", playspeeds[playspeed_current]/1000.0f); m_Pause = false; break; + case KeyConfig::ACTION_ROTATE: + if(m_orientation >= 0) + { + m_orientation += 90; + if(m_orientation == 360) m_orientation = 0; + m_player_video.SetOrientation(m_orientation); + } + break; case KeyConfig::ACTION_STEP: m_av_clock->OMXStep(); printf("Step\n"); @@ -1262,6 +1325,19 @@ int main(int argc, char *argv[]) m_Volume / 100.0f)); printf("Current Volume: %.2fdB\n", m_Volume / 100.0f); break; + case KeyConfig::ACTION_MUTE_AUDIO: + m_player_audio.SetMute(m_Mute_Audio); + if(m_Mute_Audio) + { + m_Mute_Audio = false; + DISPLAY_TEXT_SHORT("MUTE : ON"); + } + else + { + m_Mute_Audio = true; + DISPLAY_TEXT_SHORT("MUTE : OFF"); + } + break; default: break; }