Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include "base/logging.h" | 5 #include "base/logging.h" |
| 6 #include "base/memory/scoped_ptr.h" | 6 #include "base/memory/scoped_ptr.h" |
| 7 #include "media/base/mock_filters.h" | 7 #include "media/base/mock_filters.h" |
| 8 #include "media/base/test_data_util.h" | |
| 8 #include "media/ffmpeg/ffmpeg_common.h" | 9 #include "media/ffmpeg/ffmpeg_common.h" |
| 9 #include "media/filters/ffmpeg_glue.h" | 10 #include "media/filters/ffmpeg_glue.h" |
| 11 #include "media/filters/in_memory_url_protocol.h" | |
| 10 #include "testing/gtest/include/gtest/gtest.h" | 12 #include "testing/gtest/include/gtest/gtest.h" |
| 11 | 13 |
| 12 using ::testing::_; | 14 using ::testing::_; |
| 13 using ::testing::DoAll; | 15 using ::testing::DoAll; |
| 14 using ::testing::InSequence; | 16 using ::testing::InSequence; |
| 15 using ::testing::Return; | 17 using ::testing::Return; |
| 16 using ::testing::SetArgumentPointee; | 18 using ::testing::SetArgumentPointee; |
| 17 using ::testing::StrictMock; | 19 using ::testing::StrictMock; |
| 18 | 20 |
| 19 namespace media { | 21 namespace media { |
| 20 | 22 |
| 21 class MockProtocol : public FFmpegURLProtocol { | 23 class MockProtocol : public FFmpegURLProtocol { |
| 22 public: | 24 public: |
| 23 MockProtocol() { | 25 MockProtocol() {} |
| 24 } | |
| 25 | 26 |
| 26 MOCK_METHOD2(Read, size_t(size_t size, uint8* data)); | 27 MOCK_METHOD2(Read, int(int size, uint8* data)); |
| 27 MOCK_METHOD1(GetPosition, bool(int64* position_out)); | 28 MOCK_METHOD1(GetPosition, bool(int64* position_out)); |
| 28 MOCK_METHOD1(SetPosition, bool(int64 position)); | 29 MOCK_METHOD1(SetPosition, bool(int64 position)); |
| 29 MOCK_METHOD1(GetSize, bool(int64* size_out)); | 30 MOCK_METHOD1(GetSize, bool(int64* size_out)); |
| 30 MOCK_METHOD0(IsStreaming, bool()); | 31 MOCK_METHOD0(IsStreaming, bool()); |
| 31 | 32 |
| 32 private: | 33 private: |
| 33 DISALLOW_COPY_AND_ASSIGN(MockProtocol); | 34 DISALLOW_COPY_AND_ASSIGN(MockProtocol); |
| 34 }; | 35 }; |
| 35 | 36 |
| 36 class FFmpegGlueTest : public ::testing::Test { | 37 class FFmpegGlueTest : public ::testing::Test { |
| 37 public: | 38 public: |
| 38 FFmpegGlueTest() : protocol_(NULL) {} | 39 FFmpegGlueTest() |
| 39 | 40 : protocol_(new StrictMock<MockProtocol>()) { |
| 40 static void SetUpTestCase() { | |
| 41 // Singleton should initialize FFmpeg. | |
| 42 CHECK(FFmpegGlue::GetInstance()); | |
| 43 } | |
| 44 | |
| 45 virtual void SetUp() { | |
| 46 // Assign our static copy of URLProtocol for the rest of the tests. | |
| 47 protocol_ = FFmpegGlue::url_protocol(); | |
| 48 CHECK(protocol_); | |
| 49 } | |
| 50 | |
| 51 MOCK_METHOD1(CheckPoint, void(int val)); | |
| 52 | |
| 53 // Helper to open a URLContext pointing to the given mocked protocol. | |
| 54 // Callers are expected to close the context at the end of their test. | |
| 55 virtual void OpenContext(MockProtocol* protocol, URLContext* context) { | |
| 56 // IsStreaming() is called when opening. | 41 // IsStreaming() is called when opening. |
| 57 EXPECT_CALL(*protocol, IsStreaming()).WillOnce(Return(true)); | 42 EXPECT_CALL(*protocol_.get(), IsStreaming()).WillOnce(Return(true)); |
| 58 | 43 glue_.reset(new FFmpegGlue(protocol_.get())); |
| 59 // Add the protocol to the glue layer and open a context. | 44 CHECK(glue_->format_context()); |
| 60 std::string key = FFmpegGlue::GetInstance()->AddProtocol(protocol); | 45 CHECK(glue_->format_context()->pb); |
| 61 memset(context, 0, sizeof(*context)); | 46 } |
| 62 EXPECT_EQ(0, protocol_->url_open(context, key.c_str(), 0)); | 47 |
| 63 FFmpegGlue::GetInstance()->RemoveProtocol(protocol); | 48 virtual ~FFmpegGlueTest() { |
| 49 // Ensure |glue_| and |protocol_| are still alive. | |
| 50 CHECK(glue_.get()); | |
| 51 CHECK(protocol_.get()); | |
| 52 | |
| 53 // |protocol_| should outlive |glue_|, so ensure it's destructed first. | |
| 54 glue_.reset(); | |
| 55 } | |
| 56 | |
| 57 int ReadPacket(int size, uint8* data) { | |
| 58 return glue_->format_context()->pb->read_packet( | |
| 59 protocol_.get(), data, size); | |
| 60 } | |
| 61 | |
| 62 int64 Seek(int64 offset, int whence) { | |
| 63 return glue_->format_context()->pb->seek(protocol_.get(), offset, whence); | |
| 64 } | 64 } |
| 65 | 65 |
| 66 protected: | 66 protected: |
| 67 // Fixture members. | 67 scoped_ptr<FFmpegGlue> glue_; |
| 68 URLProtocol* protocol_; | 68 scoped_ptr< StrictMock<MockProtocol> > protocol_; |
| 69 | 69 |
| 70 private: | 70 private: |
| 71 DISALLOW_COPY_AND_ASSIGN(FFmpegGlueTest); | 71 DISALLOW_COPY_AND_ASSIGN(FFmpegGlueTest); |
| 72 }; | 72 }; |
| 73 | 73 |
| 74 TEST_F(FFmpegGlueTest, InitializeFFmpeg) { | 74 class FFmpegGlueDestructionTest : public ::testing::Test { |
| 75 // Make sure URLProtocol was filled out correctly. | 75 public: |
| 76 EXPECT_STREQ("http", protocol_->name); | 76 FFmpegGlueDestructionTest() {} |
| 77 EXPECT_TRUE(protocol_->url_close); | 77 |
| 78 EXPECT_TRUE(protocol_->url_open); | 78 void Initialize(const char* filename) { |
| 79 EXPECT_TRUE(protocol_->url_read); | 79 data_ = ReadTestDataFile(filename); |
| 80 EXPECT_TRUE(protocol_->url_seek); | 80 protocol_.reset(new InMemoryUrlProtocol( |
| 81 EXPECT_TRUE(protocol_->url_write); | 81 data_->GetData(), data_->GetDataSize(), false)); |
| 82 } | 82 glue_.reset(new FFmpegGlue(protocol_.get())); |
| 83 | 83 CHECK(glue_->format_context()); |
| 84 TEST_F(FFmpegGlueTest, AddRemoveGetProtocol) { | 84 CHECK(glue_->format_context()->pb); |
| 85 // Prepare testing data. | 85 } |
| 86 FFmpegGlue* glue = FFmpegGlue::GetInstance(); | 86 |
| 87 | 87 virtual ~FFmpegGlueDestructionTest() { |
| 88 // Create our protocols and add them to the glue layer. | 88 // Ensure Initialize() was called. |
| 89 scoped_ptr<StrictMock<Destroyable<MockProtocol> > > protocol_a( | 89 CHECK(glue_.get()); |
| 90 new StrictMock<Destroyable<MockProtocol> >()); | 90 CHECK(protocol_.get()); |
| 91 scoped_ptr<StrictMock<Destroyable<MockProtocol> > > protocol_b( | 91 // |glue_| should be destroyed before |protocol_|. |
|
scherkus (not reviewing)
2012/10/02 00:20:56
nit: blank lines before // comments to avoid wall-
DaleCurtis
2012/10/02 01:24:23
Done.
| |
| 92 new StrictMock<Destroyable<MockProtocol> >()); | 92 glue_.reset(); |
| 93 | 93 // |protocol_| should be destroyed before |data_|. |
| 94 // Make sure the keys are unique. | 94 protocol_.reset(); |
| 95 std::string key_a = glue->AddProtocol(protocol_a.get()); | 95 data_ = NULL; |
| 96 std::string key_b = glue->AddProtocol(protocol_b.get()); | 96 } |
| 97 EXPECT_EQ(0u, key_a.find("http://")); | 97 |
| 98 EXPECT_EQ(0u, key_b.find("http://")); | 98 protected: |
| 99 EXPECT_NE(key_a, key_b); | 99 scoped_ptr<FFmpegGlue> glue_; |
| 100 | 100 |
| 101 // Our keys should return our protocols. | 101 private: |
| 102 FFmpegURLProtocol* protocol_c; | 102 scoped_ptr<InMemoryUrlProtocol> protocol_; |
| 103 FFmpegURLProtocol* protocol_d; | 103 scoped_refptr<DecoderBuffer> data_; |
| 104 glue->GetProtocol(key_a, &protocol_c); | 104 |
| 105 glue->GetProtocol(key_b, &protocol_d); | 105 DISALLOW_COPY_AND_ASSIGN(FFmpegGlueDestructionTest); |
| 106 EXPECT_EQ(protocol_a.get(), protocol_c); | 106 }; |
| 107 EXPECT_EQ(protocol_b.get(), protocol_d); | 107 |
| 108 | 108 // Ensure writing has been disabled. |
| 109 // Adding the same Protocol should create the same key and not add an extra | |
| 110 // reference. | |
| 111 std::string key_a2 = glue->AddProtocol(protocol_a.get()); | |
| 112 EXPECT_EQ(key_a, key_a2); | |
| 113 glue->GetProtocol(key_a2, &protocol_c); | |
| 114 EXPECT_EQ(protocol_a.get(), protocol_c); | |
| 115 | |
| 116 // Removes the protocols then releases our references. They should be | |
| 117 // destroyed. | |
| 118 InSequence s; | |
| 119 EXPECT_CALL(*protocol_a, OnDestroy()); | |
| 120 EXPECT_CALL(*protocol_b, OnDestroy()); | |
| 121 EXPECT_CALL(*this, CheckPoint(0)); | |
| 122 | |
| 123 glue->RemoveProtocol(protocol_a.get()); | |
| 124 glue->GetProtocol(key_a, &protocol_c); | |
| 125 EXPECT_FALSE(protocol_c); | |
| 126 glue->GetProtocol(key_b, &protocol_d); | |
| 127 EXPECT_EQ(protocol_b.get(), protocol_d); | |
| 128 glue->RemoveProtocol(protocol_b.get()); | |
| 129 glue->GetProtocol(key_b, &protocol_d); | |
| 130 EXPECT_FALSE(protocol_d); | |
| 131 protocol_a.reset(); | |
| 132 protocol_b.reset(); | |
| 133 | |
| 134 // Data sources should be deleted by this point. | |
| 135 CheckPoint(0); | |
| 136 } | |
| 137 | |
| 138 TEST_F(FFmpegGlueTest, OpenClose) { | |
| 139 // Prepare testing data. | |
| 140 FFmpegGlue* glue = FFmpegGlue::GetInstance(); | |
| 141 | |
| 142 // Create our protocol and add them to the glue layer. | |
| 143 scoped_ptr<StrictMock<Destroyable<MockProtocol> > > protocol( | |
| 144 new StrictMock<Destroyable<MockProtocol> >()); | |
| 145 EXPECT_CALL(*protocol, IsStreaming()).WillOnce(Return(true)); | |
| 146 std::string key = glue->AddProtocol(protocol.get()); | |
| 147 | |
| 148 // Prepare FFmpeg URLContext structure. | |
| 149 URLContext context; | |
| 150 memset(&context, 0, sizeof(context)); | |
| 151 | |
| 152 // Test opening a URLContext with a protocol that doesn't exist. | |
| 153 EXPECT_EQ(AVERROR(EIO), protocol_->url_open(&context, "foobar", 0)); | |
| 154 | |
| 155 // Test opening a URLContext with our protocol. | |
| 156 EXPECT_EQ(0, protocol_->url_open(&context, key.c_str(), 0)); | |
| 157 EXPECT_EQ(AVIO_FLAG_READ, context.flags); | |
| 158 EXPECT_EQ(protocol.get(), context.priv_data); | |
| 159 EXPECT_TRUE(context.is_streamed); | |
| 160 | |
| 161 // We're going to remove references one by one until the last reference is | |
| 162 // held by FFmpeg. Once we close the URLContext, the protocol should be | |
| 163 // destroyed. | |
| 164 InSequence s; | |
| 165 EXPECT_CALL(*this, CheckPoint(0)); | |
| 166 EXPECT_CALL(*this, CheckPoint(1)); | |
| 167 EXPECT_CALL(*protocol, OnDestroy()); | |
| 168 EXPECT_CALL(*this, CheckPoint(2)); | |
| 169 | |
| 170 // Remove the protocol from the glue layer, releasing a reference. | |
| 171 glue->RemoveProtocol(protocol.get()); | |
| 172 CheckPoint(0); | |
| 173 | |
| 174 // Remove our own reference -- URLContext should maintain a reference. | |
| 175 CheckPoint(1); | |
| 176 protocol.reset(); | |
| 177 | |
| 178 // Close the URLContext, which should release the final reference. | |
| 179 EXPECT_EQ(0, protocol_->url_close(&context)); | |
| 180 CheckPoint(2); | |
| 181 } | |
| 182 | |
| 183 TEST_F(FFmpegGlueTest, Write) { | 109 TEST_F(FFmpegGlueTest, Write) { |
| 184 scoped_ptr<StrictMock<MockProtocol> > protocol( | 110 ASSERT_FALSE(glue_->format_context()->pb->write_packet); |
| 185 new StrictMock<MockProtocol>()); | 111 ASSERT_FALSE(glue_->format_context()->pb->write_flag); |
| 186 URLContext context; | 112 } |
| 187 OpenContext(protocol.get(), &context); | 113 |
| 188 | 114 // Test both successful and unsuccessful reads pass through correctly. |
| 115 TEST_F(FFmpegGlueTest, Read) { | |
| 189 const int kBufferSize = 16; | 116 const int kBufferSize = 16; |
| 190 uint8 buffer[kBufferSize]; | 117 uint8 buffer[kBufferSize]; |
| 191 | 118 |
| 192 // Writing should always fail and never call the protocol. | |
| 193 EXPECT_EQ(AVERROR(EIO), protocol_->url_write(&context, NULL, 0)); | |
| 194 EXPECT_EQ(AVERROR(EIO), protocol_->url_write(&context, buffer, 0)); | |
| 195 EXPECT_EQ(AVERROR(EIO), protocol_->url_write(&context, buffer, kBufferSize)); | |
| 196 | |
| 197 // Destroy the protocol. | |
| 198 protocol_->url_close(&context); | |
| 199 } | |
| 200 | |
| 201 TEST_F(FFmpegGlueTest, Read) { | |
| 202 scoped_ptr<StrictMock<MockProtocol> > protocol( | |
| 203 new StrictMock<MockProtocol>()); | |
| 204 URLContext context; | |
| 205 OpenContext(protocol.get(), &context); | |
| 206 | |
| 207 const int kBufferSize = 16; | |
| 208 uint8 buffer[kBufferSize]; | |
| 209 | |
| 210 // Reads are for the most part straight-through calls to Read(). | 119 // Reads are for the most part straight-through calls to Read(). |
| 211 InSequence s; | 120 InSequence s; |
| 212 EXPECT_CALL(*protocol, Read(0, buffer)) | 121 EXPECT_CALL(*protocol_, Read(0, buffer)) |
| 213 .WillOnce(Return(0)); | 122 .WillOnce(Return(0)); |
| 214 EXPECT_CALL(*protocol, Read(kBufferSize, buffer)) | 123 EXPECT_CALL(*protocol_, Read(kBufferSize, buffer)) |
| 215 .WillOnce(Return(kBufferSize)); | 124 .WillOnce(Return(kBufferSize)); |
| 216 EXPECT_CALL(*protocol, Read(kBufferSize, buffer)) | 125 EXPECT_CALL(*protocol_, Read(kBufferSize, buffer)) |
| 217 .WillOnce(Return(DataSource::kReadError)); | 126 .WillOnce(Return(DataSource::kReadError)); |
| 218 | 127 |
| 219 EXPECT_EQ(0, protocol_->url_read(&context, buffer, 0)); | 128 EXPECT_EQ(0, ReadPacket(0, buffer)); |
| 220 EXPECT_EQ(kBufferSize, protocol_->url_read(&context, buffer, kBufferSize)); | 129 EXPECT_EQ(kBufferSize, ReadPacket(kBufferSize, buffer)); |
| 221 EXPECT_EQ(AVERROR(EIO), protocol_->url_read(&context, buffer, kBufferSize)); | 130 EXPECT_EQ(AVERROR(EIO), ReadPacket(kBufferSize, buffer)); |
| 222 | 131 } |
| 223 // Destroy the protocol. | 132 |
| 224 protocol_->url_close(&context); | 133 // Test a variety of seek operations. |
| 225 } | |
| 226 | |
| 227 TEST_F(FFmpegGlueTest, Seek) { | 134 TEST_F(FFmpegGlueTest, Seek) { |
| 228 scoped_ptr<StrictMock<MockProtocol> > protocol( | |
| 229 new StrictMock<MockProtocol>()); | |
| 230 URLContext context; | |
| 231 OpenContext(protocol.get(), &context); | |
| 232 | |
| 233 // SEEK_SET should be a straight-through call to SetPosition(), which when | 135 // SEEK_SET should be a straight-through call to SetPosition(), which when |
| 234 // successful will return the result from GetPosition(). | 136 // successful will return the result from GetPosition(). |
| 235 InSequence s; | 137 InSequence s; |
| 236 EXPECT_CALL(*protocol, SetPosition(-16)) | 138 EXPECT_CALL(*protocol_, SetPosition(-16)) |
| 237 .WillOnce(Return(false)); | 139 .WillOnce(Return(false)); |
| 238 | 140 |
| 239 EXPECT_CALL(*protocol, SetPosition(16)) | 141 EXPECT_CALL(*protocol_, SetPosition(16)) |
| 240 .WillOnce(Return(true)); | 142 .WillOnce(Return(true)); |
| 241 EXPECT_CALL(*protocol, GetPosition(_)) | 143 EXPECT_CALL(*protocol_, GetPosition(_)) |
| 242 .WillOnce(DoAll(SetArgumentPointee<0>(8), Return(true))); | 144 .WillOnce(DoAll(SetArgumentPointee<0>(8), Return(true))); |
| 243 | 145 |
| 244 EXPECT_EQ(AVERROR(EIO), protocol_->url_seek(&context, -16, SEEK_SET)); | 146 EXPECT_EQ(AVERROR(EIO), Seek(-16, SEEK_SET)); |
| 245 EXPECT_EQ(8, protocol_->url_seek(&context, 16, SEEK_SET)); | 147 EXPECT_EQ(8, Seek(16, SEEK_SET)); |
| 246 | 148 |
| 247 // SEEK_CUR should call GetPosition() first, and if it succeeds add the offset | 149 // SEEK_CUR should call GetPosition() first, and if it succeeds add the offset |
| 248 // to the result then call SetPosition()+GetPosition(). | 150 // to the result then call SetPosition()+GetPosition(). |
| 249 EXPECT_CALL(*protocol, GetPosition(_)) | 151 EXPECT_CALL(*protocol_, GetPosition(_)) |
| 250 .WillOnce(Return(false)); | 152 .WillOnce(Return(false)); |
| 251 | 153 |
| 252 EXPECT_CALL(*protocol, GetPosition(_)) | 154 EXPECT_CALL(*protocol_, GetPosition(_)) |
| 253 .WillOnce(DoAll(SetArgumentPointee<0>(8), Return(true))); | 155 .WillOnce(DoAll(SetArgumentPointee<0>(8), Return(true))); |
| 254 EXPECT_CALL(*protocol, SetPosition(16)) | 156 EXPECT_CALL(*protocol_, SetPosition(16)) |
| 255 .WillOnce(Return(false)); | 157 .WillOnce(Return(false)); |
| 256 | 158 |
| 257 EXPECT_CALL(*protocol, GetPosition(_)) | 159 EXPECT_CALL(*protocol_, GetPosition(_)) |
| 258 .WillOnce(DoAll(SetArgumentPointee<0>(8), Return(true))); | 160 .WillOnce(DoAll(SetArgumentPointee<0>(8), Return(true))); |
| 259 EXPECT_CALL(*protocol, SetPosition(16)) | 161 EXPECT_CALL(*protocol_, SetPosition(16)) |
| 260 .WillOnce(Return(true)); | 162 .WillOnce(Return(true)); |
| 261 EXPECT_CALL(*protocol, GetPosition(_)) | 163 EXPECT_CALL(*protocol_, GetPosition(_)) |
| 262 .WillOnce(DoAll(SetArgumentPointee<0>(16), Return(true))); | 164 .WillOnce(DoAll(SetArgumentPointee<0>(16), Return(true))); |
| 263 | 165 |
| 264 EXPECT_EQ(AVERROR(EIO), protocol_->url_seek(&context, 8, SEEK_CUR)); | 166 EXPECT_EQ(AVERROR(EIO), Seek(8, SEEK_CUR)); |
| 265 EXPECT_EQ(AVERROR(EIO), protocol_->url_seek(&context, 8, SEEK_CUR)); | 167 EXPECT_EQ(AVERROR(EIO), Seek(8, SEEK_CUR)); |
| 266 EXPECT_EQ(16, protocol_->url_seek(&context, 8, SEEK_CUR)); | 168 EXPECT_EQ(16, Seek(8, SEEK_CUR)); |
| 267 | 169 |
| 268 // SEEK_END should call GetSize() first, and if it succeeds add the offset | 170 // SEEK_END should call GetSize() first, and if it succeeds add the offset |
| 269 // to the result then call SetPosition()+GetPosition(). | 171 // to the result then call SetPosition()+GetPosition(). |
| 270 EXPECT_CALL(*protocol, GetSize(_)) | 172 EXPECT_CALL(*protocol_, GetSize(_)) |
| 271 .WillOnce(Return(false)); | 173 .WillOnce(Return(false)); |
| 272 | 174 |
| 273 EXPECT_CALL(*protocol, GetSize(_)) | 175 EXPECT_CALL(*protocol_, GetSize(_)) |
| 274 .WillOnce(DoAll(SetArgumentPointee<0>(16), Return(true))); | 176 .WillOnce(DoAll(SetArgumentPointee<0>(16), Return(true))); |
| 275 EXPECT_CALL(*protocol, SetPosition(8)) | 177 EXPECT_CALL(*protocol_, SetPosition(8)) |
| 276 .WillOnce(Return(false)); | 178 .WillOnce(Return(false)); |
| 277 | 179 |
| 278 EXPECT_CALL(*protocol, GetSize(_)) | 180 EXPECT_CALL(*protocol_, GetSize(_)) |
| 279 .WillOnce(DoAll(SetArgumentPointee<0>(16), Return(true))); | 181 .WillOnce(DoAll(SetArgumentPointee<0>(16), Return(true))); |
| 280 EXPECT_CALL(*protocol, SetPosition(8)) | 182 EXPECT_CALL(*protocol_, SetPosition(8)) |
| 281 .WillOnce(Return(true)); | 183 .WillOnce(Return(true)); |
| 282 EXPECT_CALL(*protocol, GetPosition(_)) | 184 EXPECT_CALL(*protocol_, GetPosition(_)) |
| 283 .WillOnce(DoAll(SetArgumentPointee<0>(8), Return(true))); | 185 .WillOnce(DoAll(SetArgumentPointee<0>(8), Return(true))); |
| 284 | 186 |
| 285 EXPECT_EQ(AVERROR(EIO), protocol_->url_seek(&context, -8, SEEK_END)); | 187 EXPECT_EQ(AVERROR(EIO), Seek(-8, SEEK_END)); |
| 286 EXPECT_EQ(AVERROR(EIO), protocol_->url_seek(&context, -8, SEEK_END)); | 188 EXPECT_EQ(AVERROR(EIO), Seek(-8, SEEK_END)); |
| 287 EXPECT_EQ(8, protocol_->url_seek(&context, -8, SEEK_END)); | 189 EXPECT_EQ(8, Seek(-8, SEEK_END)); |
| 288 | 190 |
| 289 // AVSEEK_SIZE should be a straight-through call to GetSize(). | 191 // AVSEEK_SIZE should be a straight-through call to GetSize(). |
| 290 EXPECT_CALL(*protocol, GetSize(_)) | 192 EXPECT_CALL(*protocol_, GetSize(_)) |
| 291 .WillOnce(Return(false)); | 193 .WillOnce(Return(false)); |
| 292 | 194 |
| 293 EXPECT_CALL(*protocol, GetSize(_)) | 195 EXPECT_CALL(*protocol_, GetSize(_)) |
| 294 .WillOnce(DoAll(SetArgumentPointee<0>(16), Return(true))); | 196 .WillOnce(DoAll(SetArgumentPointee<0>(16), Return(true))); |
| 295 | 197 |
| 296 EXPECT_EQ(AVERROR(EIO), protocol_->url_seek(&context, 0, AVSEEK_SIZE)); | 198 EXPECT_EQ(AVERROR(EIO), Seek(0, AVSEEK_SIZE)); |
| 297 EXPECT_EQ(16, protocol_->url_seek(&context, 0, AVSEEK_SIZE)); | 199 EXPECT_EQ(16, Seek(0, AVSEEK_SIZE)); |
| 298 | 200 } |
| 299 // Destroy the protocol. | 201 |
| 300 protocol_->url_close(&context); | 202 // Ensure destruction release the appropriate resources when OpenContext() is |
| 301 } | 203 // never called. |
| 302 | 204 TEST_F(FFmpegGlueDestructionTest, WithoutOpen) { |
| 303 TEST_F(FFmpegGlueTest, Destroy) { | 205 Initialize("ten_byte_file"); |
| 304 // Create our protocol and add them to the glue layer. | 206 } |
| 305 scoped_ptr<StrictMock<Destroyable<MockProtocol> > > protocol( | 207 |
| 306 new StrictMock<Destroyable<MockProtocol> >()); | 208 // Ensure destruction releases the appropriate resources when |
| 307 std::string key = FFmpegGlue::GetInstance()->AddProtocol(protocol.get()); | 209 // avformat_open_input() fails. |
| 308 | 210 TEST_F(FFmpegGlueDestructionTest, WithOpenFailure) { |
| 309 // We should expect the protocol to get destroyed when the unit test | 211 Initialize("ten_byte_file"); |
| 310 // exits. | 212 ASSERT_LT(glue_->OpenContext(), 0); |
| 311 InSequence s; | 213 } |
| 312 EXPECT_CALL(*this, CheckPoint(0)); | 214 |
| 313 EXPECT_CALL(*protocol, OnDestroy()); | 215 // Ensure destruction release the appropriate resources when OpenContext() is |
| 314 | 216 // called, but no streams have been opened. |
| 315 // Remove our own reference, we shouldn't be destroyed yet. | 217 TEST_F(FFmpegGlueDestructionTest, WithOpenNoStreams) { |
| 316 CheckPoint(0); | 218 Initialize("no_streams.webm"); |
| 317 protocol.reset(); | 219 ASSERT_EQ(glue_->OpenContext(), 0); |
| 318 | 220 } |
| 319 // ~FFmpegGlue() will be called when this unit test finishes execution. By | 221 |
| 320 // leaving something inside FFmpegGlue's map we get to test our cleanup code. | 222 // Ensure destruction release the appropriate resources when OpenContext() is |
| 223 // called and streams exist. | |
| 224 TEST_F(FFmpegGlueDestructionTest, WithOpenWithStreams) { | |
| 225 Initialize("bear-320x240.webm"); | |
| 226 ASSERT_EQ(glue_->OpenContext(), 0); | |
| 227 } | |
| 228 | |
| 229 // Ensure destruction release the appropriate resources when OpenContext() is | |
| 230 // called and streams have been opened. | |
| 231 TEST_F(FFmpegGlueDestructionTest, WithOpenWithOpenStreams) { | |
| 232 Initialize("bear-320x240.webm"); | |
| 233 ASSERT_EQ(glue_->OpenContext(), 0); | |
| 234 ASSERT_GT(glue_->format_context()->nb_streams, 0u); | |
| 235 | |
| 236 AVCodecContext* context = glue_->format_context()->streams[0]->codec; | |
| 237 ASSERT_EQ(avcodec_open2( | |
| 238 context, avcodec_find_decoder(context->codec_id), NULL), 0); | |
| 321 } | 239 } |
| 322 | 240 |
| 323 } // namespace media | 241 } // namespace media |
| OLD | NEW |