Home | History | Annotate | Download | only in filters
      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
      3 // found in the LICENSE file.
      4 
      5 #include "base/basictypes.h"
      6 #include "base/bind.h"
      7 #include "base/memory/scoped_ptr.h"
      8 #include "base/message_loop/message_loop.h"
      9 #include "media/base/decoder_buffer.h"
     10 #include "media/base/demuxer_stream.h"
     11 #include "media/filters/fake_demuxer_stream.h"
     12 #include "testing/gtest/include/gtest/gtest.h"
     13 
     14 namespace media {
     15 
     16 static const int kNumBuffersInOneConfig = 9;
     17 static const int kNumBuffersToReadFirst = 5;
     18 static const int kNumConfigs = 3;
     19 COMPILE_ASSERT(kNumBuffersToReadFirst < kNumBuffersInOneConfig,
     20                do_not_read_too_many_buffers);
     21 COMPILE_ASSERT(kNumConfigs > 0, need_multiple_configs_to_trigger_config_change);
     22 
     23 class FakeDemuxerStreamTest : public testing::Test {
     24  public:
     25   FakeDemuxerStreamTest()
     26       : status_(DemuxerStream::kAborted),
     27         read_pending_(false) {}
     28   virtual ~FakeDemuxerStreamTest() {}
     29 
     30   void BufferReady(DemuxerStream::Status status,
     31                    const scoped_refptr<DecoderBuffer>& buffer) {
     32     DCHECK(read_pending_);
     33     read_pending_ = false;
     34     status_ = status;
     35     buffer_ = buffer;
     36   }
     37 
     38   enum ReadResult {
     39     OK,
     40     ABORTED,
     41     CONFIG_CHANGED,
     42     EOS,
     43     PENDING
     44   };
     45 
     46   void EnterNormalReadState() {
     47     stream_.reset(
     48         new FakeDemuxerStream(kNumConfigs, kNumBuffersInOneConfig, false));
     49     for (int i = 0; i < kNumBuffersToReadFirst; ++i)
     50       ReadAndExpect(OK);
     51   }
     52 
     53   void EnterBeforeEOSState() {
     54     stream_.reset(new FakeDemuxerStream(1, kNumBuffersInOneConfig, false));
     55     for (int i = 0; i < kNumBuffersInOneConfig; ++i)
     56       ReadAndExpect(OK);
     57   }
     58 
     59   void ExpectReadResult(ReadResult result) {
     60     switch (result) {
     61       case OK:
     62         EXPECT_FALSE(read_pending_);
     63         EXPECT_EQ(DemuxerStream::kOk, status_);
     64         ASSERT_TRUE(buffer_.get());
     65         EXPECT_FALSE(buffer_->end_of_stream());
     66         break;
     67 
     68       case ABORTED:
     69         EXPECT_FALSE(read_pending_);
     70         EXPECT_EQ(DemuxerStream::kAborted, status_);
     71         EXPECT_FALSE(buffer_.get());
     72         break;
     73 
     74       case CONFIG_CHANGED:
     75         EXPECT_FALSE(read_pending_);
     76         EXPECT_EQ(DemuxerStream::kConfigChanged, status_);
     77         EXPECT_FALSE(buffer_.get());
     78         break;
     79 
     80       case EOS:
     81         EXPECT_FALSE(read_pending_);
     82         EXPECT_EQ(DemuxerStream::kOk, status_);
     83         ASSERT_TRUE(buffer_.get());
     84         EXPECT_TRUE(buffer_->end_of_stream());
     85         break;
     86 
     87       case PENDING:
     88         EXPECT_TRUE(read_pending_);
     89         break;
     90     }
     91   }
     92 
     93   void ReadAndExpect(ReadResult result) {
     94     EXPECT_FALSE(read_pending_);
     95     read_pending_ = true;
     96     stream_->Read(base::Bind(&FakeDemuxerStreamTest::BufferReady,
     97                              base::Unretained(this)));
     98     message_loop_.RunUntilIdle();
     99     ExpectReadResult(result);
    100   }
    101 
    102   void ReadUntilPending() {
    103     while (1) {
    104       read_pending_ = true;
    105       stream_->Read(base::Bind(&FakeDemuxerStreamTest::BufferReady,
    106                                base::Unretained(this)));
    107       message_loop_.RunUntilIdle();
    108       if (read_pending_)
    109         break;
    110     }
    111   }
    112 
    113   void SatisfyReadAndExpect(ReadResult result) {
    114     EXPECT_TRUE(read_pending_);
    115     stream_->SatisfyRead();
    116     message_loop_.RunUntilIdle();
    117     ExpectReadResult(result);
    118   }
    119 
    120   void Reset() {
    121     bool had_read_pending = read_pending_;
    122     stream_->Reset();
    123     message_loop_.RunUntilIdle();
    124 
    125     EXPECT_FALSE(read_pending_);
    126     if (had_read_pending)
    127       ExpectReadResult(ABORTED);
    128   }
    129 
    130   void TestRead(int num_configs,
    131                 int num_buffers_in_one_config,
    132                 bool is_encrypted) {
    133     stream_.reset(new FakeDemuxerStream(
    134         num_configs, num_buffers_in_one_config, is_encrypted));
    135 
    136     int num_buffers_received = 0;
    137 
    138     const VideoDecoderConfig& config = stream_->video_decoder_config();
    139     EXPECT_TRUE(config.IsValidConfig());
    140     EXPECT_EQ(is_encrypted, config.is_encrypted());
    141 
    142     for (int i = 0; i < num_configs; ++i) {
    143       for (int j = 0; j < num_buffers_in_one_config; ++j) {
    144         ReadAndExpect(OK);
    145         num_buffers_received++;
    146         EXPECT_EQ(num_buffers_received, stream_->num_buffers_returned());
    147       }
    148 
    149       if (i == num_configs - 1)
    150         ReadAndExpect(EOS);
    151       else
    152         ReadAndExpect(CONFIG_CHANGED);
    153     }
    154 
    155     // Will always get EOS after we hit EOS.
    156     ReadAndExpect(EOS);
    157 
    158     EXPECT_EQ(num_configs * num_buffers_in_one_config, num_buffers_received);
    159   }
    160 
    161   base::MessageLoop message_loop_;
    162   scoped_ptr<FakeDemuxerStream> stream_;
    163 
    164   DemuxerStream::Status status_;
    165   scoped_refptr<DecoderBuffer> buffer_;
    166   bool read_pending_;
    167   int num_buffers_received_;
    168 
    169  private:
    170   DISALLOW_COPY_AND_ASSIGN(FakeDemuxerStreamTest);
    171 };
    172 
    173 TEST_F(FakeDemuxerStreamTest, Read_OneConfig) {
    174   TestRead(1, 5, false);
    175 }
    176 
    177 TEST_F(FakeDemuxerStreamTest, Read_MultipleConfigs) {
    178   TestRead(3, 5, false);
    179 }
    180 
    181 TEST_F(FakeDemuxerStreamTest, Read_OneBufferPerConfig) {
    182   TestRead(3, 1, false);
    183 }
    184 
    185 TEST_F(FakeDemuxerStreamTest, Read_Encrypted) {
    186   TestRead(6, 3, true);
    187 }
    188 
    189 TEST_F(FakeDemuxerStreamTest, HoldRead_Normal) {
    190   EnterNormalReadState();
    191   stream_->HoldNextRead();
    192   ReadAndExpect(PENDING);
    193   SatisfyReadAndExpect(OK);
    194 }
    195 
    196 TEST_F(FakeDemuxerStreamTest, HoldRead_BeforeConfigChanged) {
    197   EnterNormalReadState();
    198   stream_->HoldNextConfigChangeRead();
    199   ReadUntilPending();
    200   SatisfyReadAndExpect(CONFIG_CHANGED);
    201 }
    202 
    203 TEST_F(FakeDemuxerStreamTest, HoldRead_BeforeEOS) {
    204   EnterBeforeEOSState();
    205   stream_->HoldNextRead();
    206   ReadAndExpect(PENDING);
    207   SatisfyReadAndExpect(EOS);
    208 }
    209 
    210 TEST_F(FakeDemuxerStreamTest, Reset_Normal) {
    211   EnterNormalReadState();
    212   Reset();
    213   ReadAndExpect(OK);
    214 }
    215 
    216 TEST_F(FakeDemuxerStreamTest, Reset_AfterHoldRead) {
    217   EnterNormalReadState();
    218   stream_->HoldNextRead();
    219   Reset();
    220   ReadAndExpect(OK);
    221 }
    222 
    223 TEST_F(FakeDemuxerStreamTest, Reset_DuringPendingRead) {
    224   EnterNormalReadState();
    225   stream_->HoldNextRead();
    226   ReadAndExpect(PENDING);
    227   Reset();
    228   ReadAndExpect(OK);
    229 }
    230 
    231 TEST_F(FakeDemuxerStreamTest, Reset_BeforeConfigChanged) {
    232   EnterNormalReadState();
    233   stream_->HoldNextConfigChangeRead();
    234   ReadUntilPending();
    235   Reset();
    236   ReadAndExpect(CONFIG_CHANGED);
    237 }
    238 
    239 TEST_F(FakeDemuxerStreamTest, Reset_BeforeEOS) {
    240   EnterBeforeEOSState();
    241   stream_->HoldNextRead();
    242   ReadAndExpect(PENDING);
    243   Reset();
    244   ReadAndExpect(EOS);
    245 }
    246 
    247 }  // namespace media
    248