Permalink
Browse files

Fixes #9861. Rotate upside-down iPhone videos.

Thanks to David Badia for the patch (slightly modified to eliminate
compiler warnings and conform to coding standards).

This has been tested under the Slim and VDPAU Normal playback profiles.

Signed-off-by: Jim Stichnoth <jstichnoth@mythtv.org>
  • Loading branch information...
1 parent 04715f6 commit 60cf735196cf267226dd8f7ec937a82fb5f8d4b3 @dbadia dbadia committed with stichnot Jul 28, 2012
@@ -6,6 +6,7 @@ TEMPLATE = subdirs
# Directories
SUBDIRS += invert linearblend denoise3d quickdnr kerneldeint crop force
SUBDIRS += adjust onefield bobdeint ivtc greedyhdeint yadif fieldorder
+SUBDIRS += vflip
contains(CONFIG_POSTPROC, yes): SUBDIRS += postprocess
@@ -70,6 +70,7 @@ extern "C" {
#include "libavformat/avio.h"
#include "libavformat/internal.h"
#include "libswscale/swscale.h"
+#include "libavformat/isom.h"
#include "ivtv_myth.h"
}
@@ -1314,6 +1315,11 @@ void AvFormatDecoder::InitVideoCodec(AVStream *stream, AVCodecContext *enc,
}
}
+ AVDictionaryEntry *metatag =
+ av_dict_get(stream->metadata, "rotate", NULL, 0);
+ if (metatag && metatag->value && QString("180") == metatag->value)
+ video_inverted = true;
+
if (CODEC_IS_VDPAU(codec))
{
enc->get_buffer = get_avf_buffer_vdpau;
@@ -44,6 +44,7 @@ DecoderBase::DecoderBase(MythPlayer *parent, const ProgramInfo &pginfo)
getrawframes(false), getrawvideo(false),
errored(false), waitingForChange(false), readAdjust(0),
justAfterChange(false),
+ video_inverted(false),
decodeAllSubtitles(false),
// language preference
languagePreference(iso639_get_language_key_list())
@@ -216,6 +216,7 @@ class DecoderBase
void SaveTotalDuration(void);
void ResetTotalDuration(void) { totalDuration = 0; }
void SaveTotalFrames(void);
+ bool GetVideoInverted(void) const { return video_inverted; }
protected:
virtual int AutoSelectTrack(uint type);
@@ -286,6 +287,7 @@ class DecoderBase
bool waitingForChange;
long long readAdjust;
bool justAfterChange;
+ bool video_inverted;
// Audio/Subtitle/EIA-608/EIA-708 stream selection
bool decodeAllSubtitles;
@@ -500,6 +500,9 @@ bool MythPlayer::InitVideo(void)
if (embedding && pipState == kPIPOff)
videoOutput->EmbedInWidget(embedRect);
+ if (decoder && decoder->GetVideoInverted())
+ videoOutput->SetVideoFlip();
+
InitFilters();
return true;
@@ -1049,6 +1052,10 @@ void MythPlayer::InitFilters(void)
if (!videoFiltersOverride.isEmpty())
filters = videoFiltersOverride;
+ AvFormatDecoder *afd = dynamic_cast<AvFormatDecoder *>(decoder);
+ if (afd && afd->GetVideoInverted() && !filters.contains("vflip"))
+ filters += ",vflip";
+
filters.detach();
videofiltersLock.lock();
@@ -1309,3 +1309,13 @@ QStringList VideoOutputVDPAU::GetVisualiserList(void)
return VideoVisual::GetVisualiserList(m_render->Type());
return VideoOutput::GetVisualiserList();
}
+
+void VideoOutputVDPAU::SetVideoFlip(void)
+{
+ if (!m_render)
+ {
+ LOG(VB_PLAYBACK, LOG_ERR, QString("SetVideoFlip failed."));
+ return;
+ }
+ m_render->SetVideoFlip();
+}
@@ -71,6 +71,7 @@ class VideoOutputVDPAU : public VideoOutput
{ return VideoOutput::SetupVisualisation(audio, m_render, name); }
virtual QStringList GetVisualiserList(void);
virtual void ClearDummyFrame(VideoFrame* frame);
+ virtual void SetVideoFlip(void);
private:
virtual bool hasFullScreenOSD(void) const { return true; }
@@ -230,6 +230,9 @@ class VideoOutput
/// \brief check if video underscan/overscan is allowed
bool IsVideoScalingAllowed(void) const;
+ /// \brief Tells the player to flip the video frames for proper display
+ virtual void SetVideoFlip(void) { };
+
/// \brief returns QRect of PIP based on PIPLocation
virtual QRect GetPIPRect(PIPLocation location,
MythPlayer *pipplayer = NULL,
@@ -273,6 +273,7 @@ MythRenderVDPAU::MythRenderVDPAU()
m_render_lock(QMutex::Recursive), m_decode_lock(QMutex::Recursive),
m_display(NULL), m_window(0), m_device(0), m_surface(0),
m_flipQueue(0), m_flipTarget(0), m_flipReady(false), m_colorKey(0),
+ m_flipFrames(false),
vdp_get_proc_address(NULL), vdp_get_error_string(NULL)
{
LOCK_ALL
@@ -1105,16 +1106,26 @@ bool MythRenderVDPAU::MixAndRend(uint id, VdpVideoMixerPictureStructure field,
outRect.y0 = dst.top();
outRect.x1 = dst.left() + dst.width();
outRect.y1 = dst.top() + dst.height();
- srcRect.x0 = src.left();
- srcRect.y0 = src.top();
- srcRect.x1 = src.left() + src.width();
- srcRect.y1 = src.top() + src.height();
+ if (m_flipFrames)
+ {
+ // flip the image
+ srcRect.x0 = src.left() + src.width();
+ srcRect.y0 = src.top() + src.height();
+ srcRect.x1 = src.left();
+ srcRect.y1 = src.top();
+ }
+ else
+ {
+ srcRect.x0 = src.left();
+ srcRect.y0 = src.top();
+ srcRect.x1 = src.left() + src.width();
+ srcRect.y1 = src.top() + src.height();
+ }
outRectVid.x0 = dst_vid.left();
outRectVid.y0 = dst_vid.top();
outRectVid.x1 = dst_vid.left() + dst_vid.width();
outRectVid.y1 = dst_vid.top() + dst_vid.height();
-
vdp_st = vdp_video_mixer_render(mixer, VDP_INVALID_HANDLE,
NULL, field, deint ? 2 : 0,
deint ? past_surfaces : NULL,
@@ -135,6 +135,7 @@ class MUI_PUBLIC MythRenderVDPAU : public MythRender
void ChangeVideoSurfaceOwner(uint id);
void Decode(uint id, struct vdpau_render_state *render);
+ void SetVideoFlip(void) { m_flipFrames = true; }
private:
virtual ~MythRenderVDPAU();
@@ -180,6 +181,7 @@ class MUI_PUBLIC MythRenderVDPAU : public MythRender
VdpPresentationQueueTarget m_flipTarget;
bool m_flipReady;
uint m_colorKey;
+ bool m_flipFrames;
QVector<uint> m_surfaces;
QHash<uint, VDPAUOutputSurface> m_outputSurfaces;

0 comments on commit 60cf735

Please sign in to comment.