| OLD | NEW |
| 1 // Copyright (c) 2009 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2009 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 "media/base/filters.h" | 5 #include "media/base/mock_ffmpeg.h" |
| 6 #include "media/base/mock_media_filters.h" | 6 #include "media/base/mock_filters.h" |
| 7 #include "media/filters/ffmpeg_common.h" | 7 #include "media/filters/ffmpeg_common.h" |
| 8 #include "media/filters/ffmpeg_glue.h" | 8 #include "media/filters/ffmpeg_glue.h" |
| 9 #include "testing/gtest/include/gtest/gtest.h" | 9 #include "testing/gtest/include/gtest/gtest.h" |
| 10 | 10 |
| 11 // FFmpeg mocks to remove dependency on having the DLLs present. | 11 using ::testing::_; |
| 12 extern "C" { | 12 using ::testing::DoAll; |
| 13 static bool g_avcodec_init = false; | 13 using ::testing::InSequence; |
| 14 static URLProtocol* g_protocol = NULL; | 14 using ::testing::Return; |
| 15 static bool g_av_register_all = false; | 15 using ::testing::SetArgumentPointee; |
| 16 using ::testing::StrictMock; |
| 16 | 17 |
| 17 void avcodec_init() { | 18 namespace media { |
| 18 EXPECT_FALSE(g_avcodec_init); | 19 |
| 19 g_avcodec_init = true; | 20 class FFmpegGlueTest : public ::testing::Test { |
| 21 public: |
| 22 FFmpegGlueTest() { |
| 23 MockFFmpeg::set(&mock_ffmpeg_); |
| 24 } |
| 25 |
| 26 virtual ~FFmpegGlueTest() { |
| 27 MockFFmpeg::set(NULL); |
| 28 } |
| 29 |
| 30 // Helper to open a URLContext pointing to the given mocked data source. |
| 31 // Callers are expected to close the context at the end of their test. |
| 32 virtual void OpenContext(MockDataSource* data_source, URLContext* context) { |
| 33 // IsSeekable() is called when opening. |
| 34 EXPECT_CALL(*data_source, IsSeekable()).WillOnce(Return(false)); |
| 35 |
| 36 // Add the data source to the glue layer and open a context. |
| 37 std::string key = FFmpegGlue::get()->AddDataSource(data_source); |
| 38 memset(context, 0, sizeof(*context)); |
| 39 EXPECT_EQ(0, protocol_->url_open(context, key.c_str(), 0)); |
| 40 FFmpegGlue::get()->RemoveDataSource(data_source); |
| 41 } |
| 42 |
| 43 protected: |
| 44 // Fixture members. |
| 45 MockFFmpeg mock_ffmpeg_; |
| 46 static URLProtocol* protocol_; |
| 47 |
| 48 private: |
| 49 DISALLOW_COPY_AND_ASSIGN(FFmpegGlueTest); |
| 50 }; |
| 51 |
| 52 URLProtocol* FFmpegGlueTest::protocol_ = NULL; |
| 53 |
| 54 TEST_F(FFmpegGlueTest, InitializeFFmpeg) { |
| 55 // Singleton should initialize FFmpeg. |
| 56 FFmpegGlue* glue = FFmpegGlue::get(); |
| 57 EXPECT_TRUE(glue); |
| 58 |
| 59 // Assign our static copy of URLProtocol for the rest of the tests. |
| 60 protocol_ = MockFFmpeg::protocol(); |
| 61 |
| 62 // Make sure URLProtocol was filled out correctly. |
| 63 EXPECT_STREQ("http", protocol_->name); |
| 64 EXPECT_TRUE(protocol_->url_close); |
| 65 EXPECT_TRUE(protocol_->url_open); |
| 66 EXPECT_TRUE(protocol_->url_read); |
| 67 EXPECT_TRUE(protocol_->url_seek); |
| 68 EXPECT_TRUE(protocol_->url_write); |
| 20 } | 69 } |
| 21 | 70 |
| 22 int av_register_protocol(URLProtocol* protocol) { | 71 TEST_F(FFmpegGlueTest, AddRemoveGetDataSource) { |
| 23 EXPECT_FALSE(g_protocol); | |
| 24 g_protocol = protocol; | |
| 25 return 0; | |
| 26 } | |
| 27 | |
| 28 void av_register_all() { | |
| 29 EXPECT_FALSE(g_av_register_all); | |
| 30 g_av_register_all = true; | |
| 31 } | |
| 32 } // extern "C" | |
| 33 | |
| 34 TEST(FFmpegGlueTest, InitializeFFmpeg) { | |
| 35 // Singleton should initialize FFmpeg. | |
| 36 media::FFmpegGlue* glue = media::FFmpegGlue::get(); | |
| 37 EXPECT_TRUE(glue); | |
| 38 EXPECT_TRUE(g_avcodec_init); | |
| 39 EXPECT_TRUE(g_protocol); | |
| 40 EXPECT_TRUE(g_av_register_all); | |
| 41 | |
| 42 // Make sure URLProtocol was filled out correctly. | |
| 43 EXPECT_STREQ("http", g_protocol->name); | |
| 44 EXPECT_TRUE(g_protocol->url_close); | |
| 45 EXPECT_TRUE(g_protocol->url_open); | |
| 46 EXPECT_TRUE(g_protocol->url_read); | |
| 47 EXPECT_TRUE(g_protocol->url_seek); | |
| 48 EXPECT_TRUE(g_protocol->url_write); | |
| 49 } | |
| 50 | |
| 51 TEST(FFmpegGlueTest, AddRemoveGetDataSource) { | |
| 52 // Prepare testing data. | 72 // Prepare testing data. |
| 53 media::FFmpegGlue* glue = media::FFmpegGlue::get(); | 73 FFmpegGlue* glue = FFmpegGlue::get(); |
| 54 | 74 |
| 55 // Create our data sources and add them to the glue layer. | 75 // Create our data sources and add them to the glue layer. |
| 56 bool deleted_a = false; | 76 scoped_refptr<StrictMock<Destroyable<MockDataSource> > > data_source_a |
| 57 bool deleted_b = false; | 77 = new StrictMock<Destroyable<MockDataSource> >(); |
| 58 media::old_mocks::MockFilterConfig config_a; | 78 scoped_refptr<StrictMock<Destroyable<MockDataSource> > > data_source_b |
| 59 media::old_mocks::MockFilterConfig config_b; | 79 = new StrictMock<Destroyable<MockDataSource> >(); |
| 60 scoped_refptr<media::old_mocks::MockDataSource> data_source_a | |
| 61 = new media::old_mocks::MockDataSource(&config_a, &deleted_a); | |
| 62 scoped_refptr<media::old_mocks::MockDataSource> data_source_b | |
| 63 = new media::old_mocks::MockDataSource(&config_b, &deleted_b); | |
| 64 | 80 |
| 65 // Make sure the keys are unique. | 81 // Make sure the keys are unique. |
| 66 std::string key_a = glue->AddDataSource(data_source_a); | 82 std::string key_a = glue->AddDataSource(data_source_a); |
| 67 std::string key_b = glue->AddDataSource(data_source_b); | 83 std::string key_b = glue->AddDataSource(data_source_b); |
| 68 EXPECT_EQ(0u, key_a.find("http://")); | 84 EXPECT_EQ(0u, key_a.find("http://")); |
| 69 EXPECT_EQ(0u, key_b.find("http://")); | 85 EXPECT_EQ(0u, key_b.find("http://")); |
| 70 EXPECT_NE(key_a, key_b); | 86 EXPECT_NE(key_a, key_b); |
| 71 | 87 |
| 72 // Our keys should return our data sources. | 88 // Our keys should return our data sources. |
| 73 scoped_refptr<media::DataSource> data_source_c; | 89 scoped_refptr<DataSource> data_source_c; |
| 74 scoped_refptr<media::DataSource> data_source_d; | 90 scoped_refptr<DataSource> data_source_d; |
| 75 glue->GetDataSource(key_a, &data_source_c); | 91 glue->GetDataSource(key_a, &data_source_c); |
| 76 glue->GetDataSource(key_b, &data_source_d); | 92 glue->GetDataSource(key_b, &data_source_d); |
| 77 EXPECT_EQ(data_source_a, data_source_c); | 93 EXPECT_EQ(data_source_a, data_source_c); |
| 78 EXPECT_EQ(data_source_b, data_source_d); | 94 EXPECT_EQ(data_source_b, data_source_d); |
| 79 | 95 |
| 80 // Adding the same DataSource should create the same key and not add an extra | 96 // Adding the same DataSource should create the same key and not add an extra |
| 81 // reference. | 97 // reference. |
| 82 std::string key_a2 = glue->AddDataSource(data_source_a); | 98 std::string key_a2 = glue->AddDataSource(data_source_a); |
| 83 EXPECT_EQ(key_a, key_a2); | 99 EXPECT_EQ(key_a, key_a2); |
| 84 glue->GetDataSource(key_a2, &data_source_c); | 100 glue->GetDataSource(key_a2, &data_source_c); |
| 85 EXPECT_EQ(data_source_a, data_source_c); | 101 EXPECT_EQ(data_source_a, data_source_c); |
| 86 | 102 |
| 87 // Removes the data sources and then releases our references. They should be | 103 // Removes the data sources then releases our references. They should be |
| 88 // deleted. | 104 // destroyed. |
| 105 InSequence s; |
| 106 EXPECT_CALL(*data_source_a, OnDestroy()); |
| 107 EXPECT_CALL(*data_source_b, OnDestroy()); |
| 108 EXPECT_CALL(mock_ffmpeg_, CheckPoint(0)); |
| 109 |
| 89 glue->RemoveDataSource(data_source_a); | 110 glue->RemoveDataSource(data_source_a); |
| 90 glue->GetDataSource(key_a, &data_source_c); | 111 glue->GetDataSource(key_a, &data_source_c); |
| 91 EXPECT_FALSE(data_source_c); | 112 EXPECT_FALSE(data_source_c); |
| 92 glue->GetDataSource(key_b, &data_source_d); | 113 glue->GetDataSource(key_b, &data_source_d); |
| 93 EXPECT_EQ(data_source_b, data_source_d); | 114 EXPECT_EQ(data_source_b, data_source_d); |
| 94 glue->RemoveDataSource(data_source_b); | 115 glue->RemoveDataSource(data_source_b); |
| 95 glue->GetDataSource(key_b, &data_source_d); | 116 glue->GetDataSource(key_b, &data_source_d); |
| 96 EXPECT_FALSE(data_source_d); | 117 EXPECT_FALSE(data_source_d); |
| 97 EXPECT_FALSE(deleted_a); | |
| 98 EXPECT_FALSE(deleted_b); | |
| 99 data_source_a = NULL; | 118 data_source_a = NULL; |
| 100 data_source_b = NULL; | 119 data_source_b = NULL; |
| 101 EXPECT_TRUE(deleted_a); | 120 |
| 102 EXPECT_TRUE(deleted_b); | 121 // Data sources should be deleted by this point. |
| 122 mock_ffmpeg_.CheckPoint(0); |
| 103 } | 123 } |
| 104 | 124 |
| 105 TEST(FFmpegGlueTest, OpenClose) { | 125 TEST_F(FFmpegGlueTest, OpenClose) { |
| 106 // Prepare testing data. | 126 // Prepare testing data. |
| 107 media::FFmpegGlue* glue = media::FFmpegGlue::get(); | 127 FFmpegGlue* glue = FFmpegGlue::get(); |
| 108 | 128 |
| 109 // Create our data source and add them to the glue layer. | 129 // Create our data source and add them to the glue layer. |
| 110 bool deleted = false; | 130 scoped_refptr<StrictMock<Destroyable<MockDataSource> > > data_source |
| 111 media::old_mocks::MockFilterConfig config; | 131 = new StrictMock<Destroyable<MockDataSource> >(); |
| 112 scoped_refptr<media::old_mocks::MockDataSource> data_source | 132 EXPECT_CALL(*data_source, IsSeekable()).WillOnce(Return(false)); |
| 113 = new media::old_mocks::MockDataSource(&config, &deleted); | |
| 114 std::string key = glue->AddDataSource(data_source); | 133 std::string key = glue->AddDataSource(data_source); |
| 115 | 134 |
| 116 // Prepare FFmpeg URLContext structure. | 135 // Prepare FFmpeg URLContext structure. |
| 117 URLContext context; | 136 URLContext context; |
| 118 memset(&context, 0, sizeof(context)); | 137 memset(&context, 0, sizeof(context)); |
| 119 | 138 |
| 120 // Test opening a URLContext with a data source that doesn't exist. | 139 // Test opening a URLContext with a data source that doesn't exist. |
| 121 EXPECT_EQ(AVERROR_IO, g_protocol->url_open(&context, "foobar", 0)); | 140 EXPECT_EQ(AVERROR_IO, protocol_->url_open(&context, "foobar", 0)); |
| 122 | 141 |
| 123 // Test opening a URLContext with our data source. | 142 // Test opening a URLContext with our data source. |
| 124 EXPECT_EQ(0, g_protocol->url_open(&context, key.c_str(), 0)); | 143 EXPECT_EQ(0, protocol_->url_open(&context, key.c_str(), 0)); |
| 125 EXPECT_EQ(URL_RDONLY, context.flags); | 144 EXPECT_EQ(URL_RDONLY, context.flags); |
| 126 EXPECT_EQ(data_source, context.priv_data); | 145 EXPECT_EQ(data_source, context.priv_data); |
| 127 EXPECT_FALSE(context.is_streamed); | 146 EXPECT_TRUE(context.is_streamed); |
| 147 |
| 148 // We're going to remove references one by one until the last reference is |
| 149 // held by FFmpeg. Once we close the URLContext, the data source should be |
| 150 // destroyed. |
| 151 InSequence s; |
| 152 EXPECT_CALL(mock_ffmpeg_, CheckPoint(0)); |
| 153 EXPECT_CALL(mock_ffmpeg_, CheckPoint(1)); |
| 154 EXPECT_CALL(*data_source, OnDestroy()); |
| 155 EXPECT_CALL(mock_ffmpeg_, CheckPoint(2)); |
| 128 | 156 |
| 129 // Remove the data source from the glue layer, releasing a reference. | 157 // Remove the data source from the glue layer, releasing a reference. |
| 130 glue->RemoveDataSource(data_source); | 158 glue->RemoveDataSource(data_source); |
| 131 EXPECT_FALSE(deleted); | 159 mock_ffmpeg_.CheckPoint(0); |
| 132 | 160 |
| 133 // Remove our own reference -- URLContext should maintain a reference. | 161 // Remove our own reference -- URLContext should maintain a reference. |
| 134 data_source = NULL; | 162 data_source = NULL; |
| 135 EXPECT_FALSE(deleted); | 163 mock_ffmpeg_.CheckPoint(1); |
| 136 | 164 |
| 137 // Close the URLContext, which should release the final reference. | 165 // Close the URLContext, which should release the final reference. |
| 138 EXPECT_EQ(0, g_protocol->url_close(&context)); | 166 EXPECT_EQ(0, protocol_->url_close(&context)); |
| 139 EXPECT_TRUE(deleted); | 167 mock_ffmpeg_.CheckPoint(2); |
| 140 } | 168 } |
| 141 | 169 |
| 142 TEST(FFmpegGlueTest, ReadingWriting) { | 170 TEST_F(FFmpegGlueTest, Write) { |
| 143 // Prepare testing data. | 171 scoped_refptr<StrictMock<MockDataSource> > data_source |
| 144 media::FFmpegGlue* glue = media::FFmpegGlue::get(); | 172 = new StrictMock<MockDataSource>(); |
| 145 const size_t kBufferSize = 16; | 173 URLContext context; |
| 146 unsigned char buffer[kBufferSize]; | 174 OpenContext(data_source, &context); |
| 147 | 175 |
| 148 // Configure MockDataSource to be 8 characters long and fill reads with | 176 const int kBufferSize = 16; |
| 149 // periods. Therefore our expected string should be a character of 8 periods. | 177 uint8 buffer[kBufferSize]; |
| 150 const int kExpectedSize = 8; | |
| 151 media::old_mocks::MockFilterConfig config; | |
| 152 config.media_total_bytes = kExpectedSize; | |
| 153 config.data_source_value = '.'; | |
| 154 const char kExpected[] = "........"; | |
| 155 COMPILE_ASSERT(kExpectedSize == (arraysize(kExpected) - 1), string_length); | |
| 156 | 178 |
| 157 // Create our data source and add them to the glue layer. | 179 // Writing should always fail and never call the data source. |
| 158 bool deleted = false; | 180 EXPECT_EQ(AVERROR_IO, protocol_->url_write(&context, NULL, 0)); |
| 159 scoped_refptr<media::old_mocks::MockDataSource> data_source | 181 EXPECT_EQ(AVERROR_IO, protocol_->url_write(&context, buffer, 0)); |
| 160 = new media::old_mocks::MockDataSource(&config, &deleted); | 182 EXPECT_EQ(AVERROR_IO, protocol_->url_write(&context, buffer, kBufferSize)); |
| 161 std::string key = glue->AddDataSource(data_source); | |
| 162 | 183 |
| 163 // Open our data source and then remove it from the glue layer. | 184 // Destroy the data source. |
| 164 URLContext context; | 185 protocol_->url_close(&context); |
| 165 memset(&context, 0, sizeof(context)); | |
| 166 EXPECT_EQ(0, g_protocol->url_open(&context, key.c_str(), 0)); | |
| 167 glue->RemoveDataSource(data_source); | |
| 168 EXPECT_FALSE(deleted); | |
| 169 | |
| 170 // Writing should always fail. | |
| 171 EXPECT_EQ(AVERROR_IO, g_protocol->url_write(&context, NULL, 0)); | |
| 172 EXPECT_EQ(AVERROR_IO, g_protocol->url_write(&context, buffer, 0)); | |
| 173 EXPECT_EQ(AVERROR_IO, g_protocol->url_write(&context, buffer, -1)); | |
| 174 EXPECT_EQ(AVERROR_IO, g_protocol->url_write(&context, buffer, kBufferSize)); | |
| 175 EXPECT_EQ(0, data_source->position()); | |
| 176 | |
| 177 // Reading should return same amount of bytes if <= kExpectedSize. | |
| 178 EXPECT_EQ(0, g_protocol->url_read(&context, buffer, 0)); | |
| 179 EXPECT_EQ(kExpectedSize / 2, | |
| 180 g_protocol->url_read(&context, buffer, kExpectedSize / 2)); | |
| 181 EXPECT_EQ(kExpectedSize, | |
| 182 g_protocol->url_read(&context, buffer, kExpectedSize)); | |
| 183 buffer[kExpectedSize] = '\0'; | |
| 184 EXPECT_STREQ(kExpected, reinterpret_cast<char*>(buffer)); | |
| 185 | |
| 186 // Test reading more than kExpectedSize for simulating EOF. | |
| 187 EXPECT_EQ(kExpectedSize, g_protocol->url_read(&context, buffer, kBufferSize)); | |
| 188 buffer[kExpectedSize] = '\0'; | |
| 189 EXPECT_STREQ(kExpected, reinterpret_cast<char*>(buffer)); | |
| 190 | |
| 191 // Close our data source. | |
| 192 EXPECT_EQ(0, g_protocol->url_close(&context)); | |
| 193 EXPECT_FALSE(deleted); | |
| 194 | |
| 195 // Remove our own reference, which should release the final reference. | |
| 196 data_source = NULL; | |
| 197 EXPECT_TRUE(deleted); | |
| 198 } | 186 } |
| 199 | 187 |
| 200 TEST(FFmpegGlueTest, Seeking) { | 188 TEST_F(FFmpegGlueTest, Read) { |
| 201 // Prepare testing data. | 189 scoped_refptr<StrictMock<MockDataSource> > data_source |
| 202 media::FFmpegGlue* glue = media::FFmpegGlue::get(); | 190 = new StrictMock<MockDataSource>(); |
| 203 const int64 kSize = 32; | 191 URLContext context; |
| 192 OpenContext(data_source, &context); |
| 204 | 193 |
| 205 // Create our data source and add them to the glue layer. | 194 const int kBufferSize = 16; |
| 206 bool deleted = false; | 195 uint8 buffer[kBufferSize]; |
| 207 media::old_mocks::MockFilterConfig config; | |
| 208 config.media_total_bytes = kSize; | |
| 209 scoped_refptr<media::old_mocks::MockDataSource> data_source | |
| 210 = new media::old_mocks::MockDataSource(&config, &deleted); | |
| 211 std::string key = glue->AddDataSource(data_source); | |
| 212 | 196 |
| 213 // Open our data source and then remove it from the glue layer. | 197 // Reads are for the most part straight-through calls to Read(). |
| 214 URLContext context; | 198 InSequence s; |
| 215 memset(&context, 0, sizeof(context)); | 199 EXPECT_CALL(*data_source, Read(buffer, 0)) |
| 216 EXPECT_EQ(0, g_protocol->url_open(&context, key.c_str(), 0)); | 200 .WillOnce(Return(0)); |
| 217 glue->RemoveDataSource(data_source); | 201 EXPECT_CALL(*data_source, Read(buffer, kBufferSize)) |
| 218 EXPECT_FALSE(deleted); | 202 .WillOnce(Return(kBufferSize)); |
| 203 EXPECT_CALL(*data_source, Read(buffer, kBufferSize)) |
| 204 .WillOnce(Return(DataSource::kReadError)); |
| 219 | 205 |
| 220 // Test SEEK_SET operations. | 206 EXPECT_EQ(0, protocol_->url_read(&context, buffer, 0)); |
| 221 config.media_total_bytes = -1; | 207 EXPECT_EQ(kBufferSize, protocol_->url_read(&context, buffer, kBufferSize)); |
| 222 EXPECT_EQ(AVERROR_IO, g_protocol->url_seek(&context, 0, SEEK_SET)); | 208 EXPECT_EQ(AVERROR_IO, protocol_->url_read(&context, buffer, kBufferSize)); |
| 223 | 209 |
| 224 config.media_total_bytes = kSize; | 210 // Destroy the data source. |
| 225 EXPECT_TRUE(data_source->SetPosition(0)); | 211 protocol_->url_close(&context); |
| 226 EXPECT_EQ(0, g_protocol->url_seek(&context, 0, SEEK_SET)); | |
| 227 EXPECT_TRUE(data_source->SetPosition(5)); | |
| 228 EXPECT_EQ(0, g_protocol->url_seek(&context, 0, SEEK_SET)); | |
| 229 EXPECT_EQ(0, data_source->position()); | |
| 230 EXPECT_EQ(AVERROR_IO, g_protocol->url_seek(&context, -5, SEEK_SET)); | |
| 231 EXPECT_EQ(0, data_source->position()); | |
| 232 EXPECT_EQ(kSize, g_protocol->url_seek(&context, kSize, SEEK_SET)); | |
| 233 EXPECT_EQ(kSize, data_source->position()); | |
| 234 EXPECT_EQ(AVERROR_IO, g_protocol->url_seek(&context, kSize+1, SEEK_SET)); | |
| 235 EXPECT_EQ(kSize, data_source->position()); | |
| 236 | |
| 237 // Test SEEK_CUR operations. | |
| 238 config.media_total_bytes = -1; | |
| 239 EXPECT_EQ(AVERROR_IO, g_protocol->url_seek(&context, 0, SEEK_CUR)); | |
| 240 | |
| 241 config.media_total_bytes = kSize; | |
| 242 EXPECT_TRUE(data_source->SetPosition(0)); | |
| 243 EXPECT_EQ(0, g_protocol->url_seek(&context, 0, SEEK_CUR)); | |
| 244 EXPECT_TRUE(data_source->SetPosition(5)); | |
| 245 EXPECT_EQ(5, g_protocol->url_seek(&context, 0, SEEK_CUR)); | |
| 246 EXPECT_EQ(0, g_protocol->url_seek(&context, -5, SEEK_CUR)); | |
| 247 EXPECT_EQ(0, data_source->position()); | |
| 248 EXPECT_EQ(AVERROR_IO, g_protocol->url_seek(&context, -1, SEEK_CUR)); | |
| 249 EXPECT_EQ(kSize, g_protocol->url_seek(&context, kSize, SEEK_CUR)); | |
| 250 EXPECT_EQ(kSize, data_source->position()); | |
| 251 EXPECT_EQ(AVERROR_IO, g_protocol->url_seek(&context, 1, SEEK_CUR)); | |
| 252 EXPECT_EQ(kSize, data_source->position()); | |
| 253 | |
| 254 // Test SEEK_END operations. | |
| 255 config.media_total_bytes = -1; | |
| 256 EXPECT_EQ(AVERROR_IO, g_protocol->url_seek(&context, 0, SEEK_END)); | |
| 257 | |
| 258 config.media_total_bytes = kSize; | |
| 259 EXPECT_TRUE(data_source->SetPosition(0)); | |
| 260 EXPECT_EQ(kSize, g_protocol->url_seek(&context, 0, SEEK_END)); | |
| 261 EXPECT_EQ(kSize, data_source->position()); | |
| 262 EXPECT_EQ(kSize-5, g_protocol->url_seek(&context, -5, SEEK_END)); | |
| 263 EXPECT_EQ(kSize-5, data_source->position()); | |
| 264 EXPECT_EQ(0, g_protocol->url_seek(&context, -kSize, SEEK_END)); | |
| 265 EXPECT_EQ(0, data_source->position()); | |
| 266 EXPECT_EQ(AVERROR_IO, g_protocol->url_seek(&context, 1, SEEK_END)); | |
| 267 EXPECT_EQ(0, data_source->position()); | |
| 268 | |
| 269 // Test AVSEEK_SIZE operation. | |
| 270 config.media_total_bytes = -1; | |
| 271 EXPECT_EQ(AVERROR_IO, g_protocol->url_seek(&context, 0, AVSEEK_SIZE)); | |
| 272 | |
| 273 config.media_total_bytes = kSize; | |
| 274 EXPECT_TRUE(data_source->SetPosition(0)); | |
| 275 EXPECT_EQ(kSize, g_protocol->url_seek(&context, 0, AVSEEK_SIZE)); | |
| 276 | |
| 277 // Close our data source. | |
| 278 EXPECT_EQ(0, g_protocol->url_close(&context)); | |
| 279 EXPECT_FALSE(deleted); | |
| 280 | |
| 281 // Remove our own reference, which should release the final reference. | |
| 282 data_source = NULL; | |
| 283 EXPECT_TRUE(deleted); | |
| 284 } | 212 } |
| 285 | 213 |
| 286 TEST(FFmpegGlueTest, Destructor) { | 214 TEST_F(FFmpegGlueTest, Seek) { |
| 287 // Prepare testing data. | 215 scoped_refptr<StrictMock<MockDataSource> > data_source |
| 288 media::FFmpegGlue* glue = media::FFmpegGlue::get(); | 216 = new StrictMock<MockDataSource>(); |
| 217 URLContext context; |
| 218 OpenContext(data_source, &context); |
| 289 | 219 |
| 290 // We use a static bool since ~FFmpegGlue() will set it to true sometime | 220 // SEEK_SET should be a straight-through call to SetPosition(), which when |
| 291 // after this function exits. | 221 // successful will return the result from GetPosition(). |
| 292 static bool deleted = false; | 222 InSequence s; |
| 223 EXPECT_CALL(*data_source, SetPosition(-16)) |
| 224 .WillOnce(Return(false)); |
| 293 | 225 |
| 226 EXPECT_CALL(*data_source, SetPosition(16)) |
| 227 .WillOnce(Return(true)); |
| 228 EXPECT_CALL(*data_source, GetPosition(_)) |
| 229 .WillOnce(DoAll(SetArgumentPointee<0>(8), Return(true))); |
| 230 |
| 231 EXPECT_EQ(AVERROR_IO, protocol_->url_seek(&context, -16, SEEK_SET)); |
| 232 EXPECT_EQ(8, protocol_->url_seek(&context, 16, SEEK_SET)); |
| 233 |
| 234 // SEEK_CUR should call GetPosition() first, and if it succeeds add the offset |
| 235 // to the result then call SetPosition()+GetPosition(). |
| 236 EXPECT_CALL(*data_source, GetPosition(_)) |
| 237 .WillOnce(Return(false)); |
| 238 |
| 239 EXPECT_CALL(*data_source, GetPosition(_)) |
| 240 .WillOnce(DoAll(SetArgumentPointee<0>(8), Return(true))); |
| 241 EXPECT_CALL(*data_source, SetPosition(16)) |
| 242 .WillOnce(Return(false)); |
| 243 |
| 244 EXPECT_CALL(*data_source, GetPosition(_)) |
| 245 .WillOnce(DoAll(SetArgumentPointee<0>(8), Return(true))); |
| 246 EXPECT_CALL(*data_source, SetPosition(16)) |
| 247 .WillOnce(Return(true)); |
| 248 EXPECT_CALL(*data_source, GetPosition(_)) |
| 249 .WillOnce(DoAll(SetArgumentPointee<0>(16), Return(true))); |
| 250 |
| 251 EXPECT_EQ(AVERROR_IO, protocol_->url_seek(&context, 8, SEEK_CUR)); |
| 252 EXPECT_EQ(AVERROR_IO, protocol_->url_seek(&context, 8, SEEK_CUR)); |
| 253 EXPECT_EQ(16, protocol_->url_seek(&context, 8, SEEK_CUR)); |
| 254 |
| 255 // SEEK_END should call GetSize() first, and if it succeeds add the offset |
| 256 // to the result then call SetPosition()+GetPosition(). |
| 257 EXPECT_CALL(*data_source, GetSize(_)) |
| 258 .WillOnce(Return(false)); |
| 259 |
| 260 EXPECT_CALL(*data_source, GetSize(_)) |
| 261 .WillOnce(DoAll(SetArgumentPointee<0>(16), Return(true))); |
| 262 EXPECT_CALL(*data_source, SetPosition(8)) |
| 263 .WillOnce(Return(false)); |
| 264 |
| 265 EXPECT_CALL(*data_source, GetSize(_)) |
| 266 .WillOnce(DoAll(SetArgumentPointee<0>(16), Return(true))); |
| 267 EXPECT_CALL(*data_source, SetPosition(8)) |
| 268 .WillOnce(Return(true)); |
| 269 EXPECT_CALL(*data_source, GetPosition(_)) |
| 270 .WillOnce(DoAll(SetArgumentPointee<0>(8), Return(true))); |
| 271 |
| 272 EXPECT_EQ(AVERROR_IO, protocol_->url_seek(&context, -8, SEEK_END)); |
| 273 EXPECT_EQ(AVERROR_IO, protocol_->url_seek(&context, -8, SEEK_END)); |
| 274 EXPECT_EQ(8, protocol_->url_seek(&context, -8, SEEK_END)); |
| 275 |
| 276 // AVSEEK_SIZE should be a straight-through call to GetSize(). |
| 277 EXPECT_CALL(*data_source, GetSize(_)) |
| 278 .WillOnce(Return(false)); |
| 279 |
| 280 EXPECT_CALL(*data_source, GetSize(_)) |
| 281 .WillOnce(DoAll(SetArgumentPointee<0>(16), Return(true))); |
| 282 |
| 283 EXPECT_EQ(AVERROR_IO, protocol_->url_seek(&context, 0, AVSEEK_SIZE)); |
| 284 EXPECT_EQ(16, protocol_->url_seek(&context, 0, AVSEEK_SIZE)); |
| 285 |
| 286 // Destroy the data source. |
| 287 protocol_->url_close(&context); |
| 288 } |
| 289 |
| 290 TEST_F(FFmpegGlueTest, Destroy) { |
| 294 // Create our data source and add them to the glue layer. | 291 // Create our data source and add them to the glue layer. |
| 295 media::old_mocks::MockFilterConfig config; | 292 scoped_refptr<StrictMock<Destroyable<MockDataSource> > > data_source |
| 296 scoped_refptr<media::old_mocks::MockDataSource> data_source | 293 = new StrictMock<Destroyable<MockDataSource> >(); |
| 297 = new media::old_mocks::MockDataSource(&config, &deleted); | 294 std::string key = FFmpegGlue::get()->AddDataSource(data_source); |
| 298 std::string key = glue->AddDataSource(data_source); | |
| 299 | 295 |
| 300 // Remove our own reference. | 296 // We should expect the data source to get destroyed when the unit test |
| 297 // exits. |
| 298 InSequence s; |
| 299 EXPECT_CALL(mock_ffmpeg_, CheckPoint(0)); |
| 300 EXPECT_CALL(*data_source, OnDestroy()); |
| 301 |
| 302 // Remove our own reference, we shouldn't be destroyed yet. |
| 301 data_source = NULL; | 303 data_source = NULL; |
| 302 EXPECT_FALSE(deleted); | 304 mock_ffmpeg_.CheckPoint(0); |
| 303 | 305 |
| 304 // ~FFmpegGlue() will be called when this unit test finishes execution. By | 306 // ~FFmpegGlue() will be called when this unit test finishes execution. By |
| 305 // leaving something inside FFmpegGlue's map we get to test our cleanup code. | 307 // leaving something inside FFmpegGlue's map we get to test our cleanup code. |
| 306 // | |
| 307 // MockDataSource will be holding onto a bad MockFilterConfig pointer at this | |
| 308 // point but since no one is calling it everything will be ok. | |
| 309 } | 308 } |
| 309 |
| 310 } // namespace media |
| OLD | NEW |