Commit d4f89884 authored by suderman@chromium.org's avatar suderman@chromium.org

Update to Pipeline Metadata and Decoder stream

to track the set of video rotation metadata. This 
will later be used to correctly orient rotated videos.

BUG=47554

Review URL: https://codereview.chromium.org/363813002

git-svn-id: svn://svn.chromium.org/chrome/trunk/src@282236 0039d316-1c4b-4281-b951-d872f2087c98
parent 5b8cfced
...@@ -8,6 +8,7 @@ ...@@ -8,6 +8,7 @@
#include "base/callback.h" #include "base/callback.h"
#include "base/memory/ref_counted.h" #include "base/memory/ref_counted.h"
#include "media/base/media_export.h" #include "media/base/media_export.h"
#include "media/base/video_rotation.h"
namespace media { namespace media {
...@@ -80,6 +81,8 @@ class MEDIA_EXPORT DemuxerStream { ...@@ -80,6 +81,8 @@ class MEDIA_EXPORT DemuxerStream {
// on this. // on this.
virtual bool SupportsConfigChanges() = 0; virtual bool SupportsConfigChanges() = 0;
virtual VideoRotation video_rotation() = 0;
protected: protected:
// Only allow concrete implementations to get deleted. // Only allow concrete implementations to get deleted.
virtual ~DemuxerStream(); virtual ~DemuxerStream();
......
...@@ -38,6 +38,10 @@ DemuxerStream::Type FakeTextTrackStream::type() { ...@@ -38,6 +38,10 @@ DemuxerStream::Type FakeTextTrackStream::type() {
bool FakeTextTrackStream::SupportsConfigChanges() { return false; } bool FakeTextTrackStream::SupportsConfigChanges() { return false; }
VideoRotation FakeTextTrackStream::video_rotation() {
return VIDEO_ROTATION_0;
}
void FakeTextTrackStream::SatisfyPendingRead( void FakeTextTrackStream::SatisfyPendingRead(
const base::TimeDelta& start, const base::TimeDelta& start,
const base::TimeDelta& duration, const base::TimeDelta& duration,
......
...@@ -24,6 +24,7 @@ class FakeTextTrackStream : public DemuxerStream { ...@@ -24,6 +24,7 @@ class FakeTextTrackStream : public DemuxerStream {
virtual Type type() OVERRIDE; virtual Type type() OVERRIDE;
MOCK_METHOD0(EnableBitstreamConverter, void()); MOCK_METHOD0(EnableBitstreamConverter, void());
virtual bool SupportsConfigChanges(); virtual bool SupportsConfigChanges();
virtual VideoRotation video_rotation() OVERRIDE;
void SatisfyPendingRead(const base::TimeDelta& start, void SatisfyPendingRead(const base::TimeDelta& start,
const base::TimeDelta& duration, const base::TimeDelta& duration,
......
...@@ -48,6 +48,10 @@ void MockDemuxerStream::set_video_decoder_config( ...@@ -48,6 +48,10 @@ void MockDemuxerStream::set_video_decoder_config(
video_decoder_config_ = config; video_decoder_config_ = config;
} }
VideoRotation MockDemuxerStream::video_rotation() {
return VIDEO_ROTATION_0;
}
MockVideoDecoder::MockVideoDecoder() { MockVideoDecoder::MockVideoDecoder() {
EXPECT_CALL(*this, HasAlpha()).WillRepeatedly(Return(false)); EXPECT_CALL(*this, HasAlpha()).WillRepeatedly(Return(false));
} }
......
...@@ -61,6 +61,8 @@ class MockDemuxerStream : public DemuxerStream { ...@@ -61,6 +61,8 @@ class MockDemuxerStream : public DemuxerStream {
void set_audio_decoder_config(const AudioDecoderConfig& config); void set_audio_decoder_config(const AudioDecoderConfig& config);
void set_video_decoder_config(const VideoDecoderConfig& config); void set_video_decoder_config(const VideoDecoderConfig& config);
virtual VideoRotation video_rotation() OVERRIDE;
private: private:
DemuxerStream::Type type_; DemuxerStream::Type type_;
AudioDecoderConfig audio_decoder_config_; AudioDecoderConfig audio_decoder_config_;
......
...@@ -389,6 +389,7 @@ void Pipeline::StateTransitionTask(PipelineStatus status) { ...@@ -389,6 +389,7 @@ void Pipeline::StateTransitionTask(PipelineStatus status) {
if (stream) { if (stream) {
metadata.natural_size = metadata.natural_size =
stream->video_decoder_config().natural_size(); stream->video_decoder_config().natural_size();
metadata.video_rotation = stream->video_rotation();
} }
metadata_cb_.Run(metadata); metadata_cb_.Run(metadata);
} }
......
...@@ -19,6 +19,7 @@ ...@@ -19,6 +19,7 @@
#include "media/base/pipeline_status.h" #include "media/base/pipeline_status.h"
#include "media/base/ranges.h" #include "media/base/ranges.h"
#include "media/base/serial_runner.h" #include "media/base/serial_runner.h"
#include "media/base/video_rotation.h"
#include "ui/gfx/size.h" #include "ui/gfx/size.h"
namespace base { namespace base {
...@@ -37,11 +38,13 @@ class VideoRenderer; ...@@ -37,11 +38,13 @@ class VideoRenderer;
// Metadata describing a pipeline once it has been initialized. // Metadata describing a pipeline once it has been initialized.
struct PipelineMetadata { struct PipelineMetadata {
PipelineMetadata() : has_audio(false), has_video(false) {} PipelineMetadata()
: has_audio(false), has_video(false), video_rotation(VIDEO_ROTATION_0) {}
bool has_audio; bool has_audio;
bool has_video; bool has_video;
gfx::Size natural_size; gfx::Size natural_size;
VideoRotation video_rotation;
base::Time timeline_offset; base::Time timeline_offset;
}; };
......
// Copyright 2014 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef MEDIA_BASE_VIDEO_ROTATION_H_
#define MEDIA_BASE_VIDEO_ROTATION_H_
namespace media {
// Enumeration to represent 90 degree video rotation for MP4 videos
// where it can be rotated by 90 degree intervals.
enum VideoRotation {
VIDEO_ROTATION_0 = 0,
VIDEO_ROTATION_90,
VIDEO_ROTATION_180,
VIDEO_ROTATION_270
};
} // namespace media
#endif // MEDIA_BASE_VIDEO_ROTATION_H_
...@@ -952,6 +952,10 @@ TextTrackConfig ChunkDemuxerStream::text_track_config() { ...@@ -952,6 +952,10 @@ TextTrackConfig ChunkDemuxerStream::text_track_config() {
return stream_->GetCurrentTextTrackConfig(); return stream_->GetCurrentTextTrackConfig();
} }
VideoRotation ChunkDemuxerStream::video_rotation() {
return VIDEO_ROTATION_0;
}
void ChunkDemuxerStream::ChangeState_Locked(State state) { void ChunkDemuxerStream::ChangeState_Locked(State state) {
lock_.AssertAcquired(); lock_.AssertAcquired();
DVLOG(1) << "ChunkDemuxerStream::ChangeState_Locked() : " DVLOG(1) << "ChunkDemuxerStream::ChangeState_Locked() : "
......
...@@ -86,6 +86,7 @@ class MEDIA_EXPORT ChunkDemuxerStream : public DemuxerStream { ...@@ -86,6 +86,7 @@ class MEDIA_EXPORT ChunkDemuxerStream : public DemuxerStream {
virtual AudioDecoderConfig audio_decoder_config() OVERRIDE; virtual AudioDecoderConfig audio_decoder_config() OVERRIDE;
virtual VideoDecoderConfig video_decoder_config() OVERRIDE; virtual VideoDecoderConfig video_decoder_config() OVERRIDE;
virtual bool SupportsConfigChanges() OVERRIDE; virtual bool SupportsConfigChanges() OVERRIDE;
virtual VideoRotation video_rotation() OVERRIDE;
// Returns the text track configuration. It is an error to call this method // Returns the text track configuration. It is an error to call this method
// if type() != TEXT. // if type() != TEXT.
......
...@@ -165,6 +165,10 @@ bool DecryptingDemuxerStream::SupportsConfigChanges() { ...@@ -165,6 +165,10 @@ bool DecryptingDemuxerStream::SupportsConfigChanges() {
return demuxer_stream_->SupportsConfigChanges(); return demuxer_stream_->SupportsConfigChanges();
} }
VideoRotation DecryptingDemuxerStream::video_rotation() {
return VIDEO_ROTATION_0;
}
DecryptingDemuxerStream::~DecryptingDemuxerStream() { DecryptingDemuxerStream::~DecryptingDemuxerStream() {
DVLOG(2) << __FUNCTION__ << " : state_ = " << state_; DVLOG(2) << __FUNCTION__ << " : state_ = " << state_;
} }
......
...@@ -56,6 +56,7 @@ class MEDIA_EXPORT DecryptingDemuxerStream : public DemuxerStream { ...@@ -56,6 +56,7 @@ class MEDIA_EXPORT DecryptingDemuxerStream : public DemuxerStream {
virtual Type type() OVERRIDE; virtual Type type() OVERRIDE;
virtual void EnableBitstreamConverter() OVERRIDE; virtual void EnableBitstreamConverter() OVERRIDE;
virtual bool SupportsConfigChanges() OVERRIDE; virtual bool SupportsConfigChanges() OVERRIDE;
virtual VideoRotation video_rotation() OVERRIDE;
private: private:
// For a detailed state diagram please see this link: http://goo.gl/8jAok // For a detailed state diagram please see this link: http://goo.gl/8jAok
......
...@@ -97,6 +97,10 @@ bool FakeDemuxerStream::SupportsConfigChanges() { ...@@ -97,6 +97,10 @@ bool FakeDemuxerStream::SupportsConfigChanges() {
return config_changes_; return config_changes_;
} }
VideoRotation FakeDemuxerStream::video_rotation() {
return VIDEO_ROTATION_0;
}
void FakeDemuxerStream::HoldNextRead() { void FakeDemuxerStream::HoldNextRead() {
DCHECK(task_runner_->BelongsToCurrentThread()); DCHECK(task_runner_->BelongsToCurrentThread());
read_to_hold_ = next_read_num_; read_to_hold_ = next_read_num_;
......
...@@ -34,6 +34,7 @@ class FakeDemuxerStream : public DemuxerStream { ...@@ -34,6 +34,7 @@ class FakeDemuxerStream : public DemuxerStream {
virtual Type type() OVERRIDE; virtual Type type() OVERRIDE;
virtual void EnableBitstreamConverter() OVERRIDE; virtual void EnableBitstreamConverter() OVERRIDE;
virtual bool SupportsConfigChanges() OVERRIDE; virtual bool SupportsConfigChanges() OVERRIDE;
virtual VideoRotation video_rotation() OVERRIDE;
void Initialize(); void Initialize();
......
...@@ -14,6 +14,7 @@ ...@@ -14,6 +14,7 @@
#include "base/memory/scoped_ptr.h" #include "base/memory/scoped_ptr.h"
#include "base/message_loop/message_loop_proxy.h" #include "base/message_loop/message_loop_proxy.h"
#include "base/metrics/sparse_histogram.h" #include "base/metrics/sparse_histogram.h"
#include "base/strings/string_number_conversions.h"
#include "base/strings/string_util.h" #include "base/strings/string_util.h"
#include "base/strings/stringprintf.h" #include "base/strings/stringprintf.h"
#include "base/sys_byteorder.h" #include "base/sys_byteorder.h"
...@@ -92,11 +93,14 @@ FFmpegDemuxerStream::FFmpegDemuxerStream(FFmpegDemuxer* demuxer, ...@@ -92,11 +93,14 @@ FFmpegDemuxerStream::FFmpegDemuxerStream(FFmpegDemuxer* demuxer,
type_(UNKNOWN), type_(UNKNOWN),
end_of_stream_(false), end_of_stream_(false),
last_packet_timestamp_(kNoTimestamp()), last_packet_timestamp_(kNoTimestamp()),
video_rotation_(VIDEO_ROTATION_0),
bitstream_converter_enabled_(false), bitstream_converter_enabled_(false),
fixup_negative_ogg_timestamps_(false) { fixup_negative_ogg_timestamps_(false) {
DCHECK(demuxer_); DCHECK(demuxer_);
bool is_encrypted = false; bool is_encrypted = false;
int rotation = 0;
AVDictionaryEntry* rotation_entry = NULL;
// Determine our media format. // Determine our media format.
switch (stream->codec->codec_type) { switch (stream->codec->codec_type) {
...@@ -109,6 +113,28 @@ FFmpegDemuxerStream::FFmpegDemuxerStream(FFmpegDemuxer* demuxer, ...@@ -109,6 +113,28 @@ FFmpegDemuxerStream::FFmpegDemuxerStream(FFmpegDemuxer* demuxer,
type_ = VIDEO; type_ = VIDEO;
AVStreamToVideoDecoderConfig(stream, &video_config_, true); AVStreamToVideoDecoderConfig(stream, &video_config_, true);
is_encrypted = video_config_.is_encrypted(); is_encrypted = video_config_.is_encrypted();
rotation_entry = av_dict_get(stream->metadata, "rotate", NULL, 0);
if (rotation_entry && rotation_entry->value && rotation_entry->value[0])
base::StringToInt(rotation_entry->value, &rotation);
switch (rotation) {
case 0:
break;
case 90:
video_rotation_ = VIDEO_ROTATION_90;
break;
case 180:
video_rotation_ = VIDEO_ROTATION_180;
break;
case 270:
video_rotation_ = VIDEO_ROTATION_270;
break;
default:
LOG(ERROR) << "Unsupported video rotation metadata: " << rotation;
break;
}
break; break;
case AVMEDIA_TYPE_SUBTITLE: case AVMEDIA_TYPE_SUBTITLE:
type_ = TEXT; type_ = TEXT;
...@@ -380,6 +406,10 @@ VideoDecoderConfig FFmpegDemuxerStream::video_decoder_config() { ...@@ -380,6 +406,10 @@ VideoDecoderConfig FFmpegDemuxerStream::video_decoder_config() {
return video_config_; return video_config_;
} }
VideoRotation FFmpegDemuxerStream::video_rotation() {
return video_rotation_;
}
FFmpegDemuxerStream::~FFmpegDemuxerStream() { FFmpegDemuxerStream::~FFmpegDemuxerStream() {
DCHECK(!demuxer_); DCHECK(!demuxer_);
DCHECK(read_cb_.is_null()); DCHECK(read_cb_.is_null());
......
...@@ -92,6 +92,7 @@ class FFmpegDemuxerStream : public DemuxerStream { ...@@ -92,6 +92,7 @@ class FFmpegDemuxerStream : public DemuxerStream {
virtual bool SupportsConfigChanges() OVERRIDE; virtual bool SupportsConfigChanges() OVERRIDE;
virtual AudioDecoderConfig audio_decoder_config() OVERRIDE; virtual AudioDecoderConfig audio_decoder_config() OVERRIDE;
virtual VideoDecoderConfig video_decoder_config() OVERRIDE; virtual VideoDecoderConfig video_decoder_config() OVERRIDE;
virtual VideoRotation video_rotation() OVERRIDE;
// Returns the range of buffered data in this stream. // Returns the range of buffered data in this stream.
Ranges<base::TimeDelta> GetBufferedRanges() const; Ranges<base::TimeDelta> GetBufferedRanges() const;
...@@ -133,6 +134,7 @@ class FFmpegDemuxerStream : public DemuxerStream { ...@@ -133,6 +134,7 @@ class FFmpegDemuxerStream : public DemuxerStream {
bool end_of_stream_; bool end_of_stream_;
base::TimeDelta last_packet_timestamp_; base::TimeDelta last_packet_timestamp_;
Ranges<base::TimeDelta> buffered_ranges_; Ranges<base::TimeDelta> buffered_ranges_;
VideoRotation video_rotation_;
DecoderBufferQueue buffer_queue_; DecoderBufferQueue buffer_queue_;
ReadCB read_cb_; ReadCB read_cb_;
...@@ -277,6 +279,8 @@ class MEDIA_EXPORT FFmpegDemuxer : public Demuxer { ...@@ -277,6 +279,8 @@ class MEDIA_EXPORT FFmpegDemuxer : public Demuxer {
// time if the file doesn't have an association to Time. // time if the file doesn't have an association to Time.
base::Time timeline_offset_; base::Time timeline_offset_;
VideoRotation video_rotation_;
// Liveness of the stream. // Liveness of the stream.
Liveness liveness_; Liveness liveness_;
......
...@@ -916,6 +916,42 @@ TEST_F(FFmpegDemuxerTest, IsValidAnnexB) { ...@@ -916,6 +916,42 @@ TEST_F(FFmpegDemuxerTest, IsValidAnnexB) {
} }
} }
TEST_F(FFmpegDemuxerTest, Rotate_Metadata_0) {
CreateDemuxer("bear_rotate_0.mp4");
InitializeDemuxer();
DemuxerStream* stream = demuxer_->GetStream(DemuxerStream::VIDEO);
ASSERT_TRUE(stream);
ASSERT_EQ(VIDEO_ROTATION_0, stream->video_rotation());
}
TEST_F(FFmpegDemuxerTest, Rotate_Metadata_90) {
CreateDemuxer("bear_rotate_90.mp4");
InitializeDemuxer();
DemuxerStream* stream = demuxer_->GetStream(DemuxerStream::VIDEO);
ASSERT_TRUE(stream);
ASSERT_EQ(VIDEO_ROTATION_90, stream->video_rotation());
}
TEST_F(FFmpegDemuxerTest, Rotate_Metadata_180) {
CreateDemuxer("bear_rotate_180.mp4");
InitializeDemuxer();
DemuxerStream* stream = demuxer_->GetStream(DemuxerStream::VIDEO);
ASSERT_TRUE(stream);
ASSERT_EQ(VIDEO_ROTATION_180, stream->video_rotation());
}
TEST_F(FFmpegDemuxerTest, Rotate_Metadata_270) {
CreateDemuxer("bear_rotate_270.mp4");
InitializeDemuxer();
DemuxerStream* stream = demuxer_->GetStream(DemuxerStream::VIDEO);
ASSERT_TRUE(stream);
ASSERT_EQ(VIDEO_ROTATION_270, stream->video_rotation());
}
#endif #endif
} // namespace media } // namespace media
...@@ -1394,6 +1394,28 @@ TEST_F(PipelineIntegrationTest, DISABLED_SeekWhilePlaying) { ...@@ -1394,6 +1394,28 @@ TEST_F(PipelineIntegrationTest, DISABLED_SeekWhilePlaying) {
ASSERT_TRUE(WaitUntilOnEnded()); ASSERT_TRUE(WaitUntilOnEnded());
} }
#if defined(USE_PROPRIETARY_CODECS)
TEST_F(PipelineIntegrationTest, Rotated_Metadata_0) {
ASSERT_TRUE(Start(GetTestDataFilePath("bear_rotate_0.mp4"), PIPELINE_OK));
ASSERT_EQ(VIDEO_ROTATION_0, metadata_.video_rotation);
}
TEST_F(PipelineIntegrationTest, Rotated_Metadata_90) {
ASSERT_TRUE(Start(GetTestDataFilePath("bear_rotate_90.mp4"), PIPELINE_OK));
ASSERT_EQ(VIDEO_ROTATION_90, metadata_.video_rotation);
}
TEST_F(PipelineIntegrationTest, Rotated_Metadata_180) {
ASSERT_TRUE(Start(GetTestDataFilePath("bear_rotate_180.mp4"), PIPELINE_OK));
ASSERT_EQ(VIDEO_ROTATION_180, metadata_.video_rotation);
}
TEST_F(PipelineIntegrationTest, Rotated_Metadata_270) {
ASSERT_TRUE(Start(GetTestDataFilePath("bear_rotate_270.mp4"), PIPELINE_OK));
ASSERT_EQ(VIDEO_ROTATION_270, metadata_.video_rotation);
}
#endif
// Verify audio decoder & renderer can handle aborted demuxer reads. // Verify audio decoder & renderer can handle aborted demuxer reads.
TEST_F(PipelineIntegrationTest, ChunkDemuxerAbortRead_AudioOnly) { TEST_F(PipelineIntegrationTest, ChunkDemuxerAbortRead_AudioOnly) {
ASSERT_TRUE(TestSeekDuringRead("bear-320x240-audio-only.webm", kAudioOnlyWebM, ASSERT_TRUE(TestSeekDuringRead("bear-320x240-audio-only.webm", kAudioOnlyWebM,
......
...@@ -349,6 +349,7 @@ ...@@ -349,6 +349,7 @@
'base/video_frame_pool.h', 'base/video_frame_pool.h',
'base/video_renderer.cc', 'base/video_renderer.cc',
'base/video_renderer.h', 'base/video_renderer.h',
'base/video_rotation.h',
'base/video_util.cc', 'base/video_util.cc',
'base/video_util.h', 'base/video_util.h',
'base/yuv_convert.cc', 'base/yuv_convert.cc',
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment