Skip to content

Commit

Permalink
Fixes #9861. Rotate upside-down iPhone videos.
Browse files Browse the repository at this point in the history
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
dbadia authored and stichnot committed Jul 28, 2012
1 parent 04715f6 commit 60cf735
Show file tree
Hide file tree
Showing 10 changed files with 49 additions and 5 deletions.
1 change: 1 addition & 0 deletions mythtv/filters/filters.pro
Expand Up @@ -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

Expand Down
6 changes: 6 additions & 0 deletions mythtv/libs/libmythtv/avformatdecoder.cpp
Expand Up @@ -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"
}

Expand Down Expand Up @@ -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;
Expand Down
1 change: 1 addition & 0 deletions mythtv/libs/libmythtv/decoderbase.cpp
Expand Up @@ -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())
Expand Down
2 changes: 2 additions & 0 deletions mythtv/libs/libmythtv/decoderbase.h
Expand Up @@ -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);
Expand Down Expand Up @@ -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;
Expand Down
7 changes: 7 additions & 0 deletions mythtv/libs/libmythtv/mythplayer.cpp
Expand Up @@ -500,6 +500,9 @@ bool MythPlayer::InitVideo(void)
if (embedding && pipState == kPIPOff)
videoOutput->EmbedInWidget(embedRect);

if (decoder && decoder->GetVideoInverted())
videoOutput->SetVideoFlip();

InitFilters();

return true;
Expand Down Expand Up @@ -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();
Expand Down
10 changes: 10 additions & 0 deletions mythtv/libs/libmythtv/videoout_vdpau.cpp
Expand Up @@ -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();
}
1 change: 1 addition & 0 deletions mythtv/libs/libmythtv/videoout_vdpau.h
Expand Up @@ -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; }
Expand Down
3 changes: 3 additions & 0 deletions mythtv/libs/libmythtv/videooutbase.h
Expand Up @@ -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,
Expand Down
21 changes: 16 additions & 5 deletions mythtv/libs/libmythui/mythrender_vdpau.cpp
Expand Up @@ -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
Expand Down Expand Up @@ -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,
Expand Down
2 changes: 2 additions & 0 deletions mythtv/libs/libmythui/mythrender_vdpau.h
Expand Up @@ -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();
Expand Down Expand Up @@ -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;
Expand Down

0 comments on commit 60cf735

Please sign in to comment.