#include "base/bind.h"
#include "base/message_loop/message_loop.h"
+#include "base/run_loop.h"
#include "base/strings/stringprintf.h"
#include "media/base/audio_buffer.h"
#include "media/base/decoder_buffer.h"
namespace media {
-ACTION_P(InvokeReadPacket, test) {
- test->ReadPacket(arg0);
-}
-
class FFmpegAudioDecoderTest : public testing::Test {
public:
FFmpegAudioDecoderTest()
- : decoder_(new FFmpegAudioDecoder(message_loop_.message_loop_proxy())),
- demuxer_(new StrictMock<MockDemuxerStream>(DemuxerStream::AUDIO)) {
+ : decoder_(new FFmpegAudioDecoder(message_loop_.message_loop_proxy(),
+ LogCB())),
+ pending_decode_(false),
+ pending_reset_(false),
+ last_decode_status_(AudioDecoder::kOk) {
FFmpegGlue::InitializeFFmpeg();
vorbis_extradata_ = ReadTestDataFile("vorbis-extradata");
// Push in an EOS buffer.
encoded_audio_.push_back(DecoderBuffer::CreateEOSBuffer());
+
+ Initialize();
}
- virtual ~FFmpegAudioDecoderTest() {}
+ virtual ~FFmpegAudioDecoderTest() {
+ EXPECT_FALSE(pending_decode_);
+ EXPECT_FALSE(pending_reset_);
+ }
void Initialize() {
AudioDecoderConfig config(kCodecVorbis,
vorbis_extradata_->data(),
vorbis_extradata_->data_size(),
false); // Not encrypted.
- demuxer_->set_audio_decoder_config(config);
- decoder_->Initialize(demuxer_.get(),
+ decoder_->Initialize(config,
NewExpectedStatusCB(PIPELINE_OK),
- base::Bind(&MockStatisticsCB::OnStatistics,
- base::Unretained(&statistics_cb_)));
-
- message_loop_.RunUntilIdle();
+ base::Bind(&FFmpegAudioDecoderTest::OnDecoderOutput,
+ base::Unretained(this)));
+ base::RunLoop().RunUntilIdle();
}
- void ReadPacket(const DemuxerStream::ReadCB& read_cb) {
- CHECK(!encoded_audio_.empty()) << "ReadPacket() called too many times";
+ void SatisfyPendingDecode() {
+ base::RunLoop().RunUntilIdle();
+ }
+ void Decode() {
+ pending_decode_ = true;
scoped_refptr<DecoderBuffer> buffer(encoded_audio_.front());
- DemuxerStream::Status status =
- buffer.get() ? DemuxerStream::kOk : DemuxerStream::kAborted;
encoded_audio_.pop_front();
- read_cb.Run(status, buffer);
+ decoder_->Decode(buffer,
+ base::Bind(&FFmpegAudioDecoderTest::DecodeFinished,
+ base::Unretained(this)));
+ base::RunLoop().RunUntilIdle();
+ EXPECT_FALSE(pending_decode_);
+ EXPECT_EQ(AudioDecoder::kOk, last_decode_status_);
}
- void Read() {
- decoder_->Read(base::Bind(
- &FFmpegAudioDecoderTest::DecodeFinished, base::Unretained(this)));
- message_loop_.RunUntilIdle();
+ void Reset() {
+ pending_reset_ = true;
+ decoder_->Reset(base::Bind(
+ &FFmpegAudioDecoderTest::ResetFinished, base::Unretained(this)));
+ base::RunLoop().RunUntilIdle();
}
- void DecodeFinished(AudioDecoder::Status status,
- const scoped_refptr<AudioBuffer>& buffer) {
+ void Stop() {
+ decoder_->Stop();
+ base::RunLoop().RunUntilIdle();
+ }
+
+ void OnDecoderOutput(const scoped_refptr<AudioBuffer>& buffer) {
+ EXPECT_FALSE(buffer->end_of_stream());
decoded_audio_.push_back(buffer);
}
+ void DecodeFinished(AudioDecoder::Status status) {
+ EXPECT_TRUE(pending_decode_);
+ pending_decode_ = false;
+
+ last_decode_status_ = status;
+ }
+
+ void ResetFinished() {
+ EXPECT_TRUE(pending_reset_);
+ // Reset should always finish after Decode.
+ EXPECT_FALSE(pending_decode_);
+
+ pending_reset_ = false;
+ }
+
void ExpectDecodedAudio(size_t i, int64 timestamp, int64 duration) {
EXPECT_LT(i, decoded_audio_.size());
EXPECT_EQ(timestamp, decoded_audio_[i]->timestamp().InMicroseconds());
EXPECT_EQ(duration, decoded_audio_[i]->duration().InMicroseconds());
- EXPECT_FALSE(decoded_audio_[i]->end_of_stream());
- }
-
- void ExpectEndOfStream(size_t i) {
- EXPECT_LT(i, decoded_audio_.size());
- EXPECT_TRUE(decoded_audio_[i]->end_of_stream());
}
base::MessageLoop message_loop_;
scoped_ptr<FFmpegAudioDecoder> decoder_;
- scoped_ptr<StrictMock<MockDemuxerStream> > demuxer_;
- MockStatisticsCB statistics_cb_;
+ bool pending_decode_;
+ bool pending_reset_;
scoped_refptr<DecoderBuffer> vorbis_extradata_;
std::deque<scoped_refptr<DecoderBuffer> > encoded_audio_;
std::deque<scoped_refptr<AudioBuffer> > decoded_audio_;
+ AudioDecoder::Status last_decode_status_;
};
TEST_F(FFmpegAudioDecoderTest, Initialize) {
- Initialize();
-
- const AudioDecoderConfig& config = demuxer_->audio_decoder_config();
- EXPECT_EQ(config.bits_per_channel(), decoder_->bits_per_channel());
- EXPECT_EQ(config.channel_layout(), decoder_->channel_layout());
- EXPECT_EQ(config.samples_per_second(), decoder_->samples_per_second());
+ AudioDecoderConfig config(kCodecVorbis,
+ kSampleFormatPlanarF32,
+ CHANNEL_LAYOUT_STEREO,
+ 44100,
+ vorbis_extradata_->data(),
+ vorbis_extradata_->data_size(),
+ false); // Not encrypted.
+ Stop();
}
TEST_F(FFmpegAudioDecoderTest, ProduceAudioSamples) {
- Initialize();
-
// Vorbis requires N+1 packets to produce audio data for N packets.
//
// This will should result in the demuxer receiving three reads for two
// requests to produce audio samples.
- EXPECT_CALL(*demuxer_, Read(_))
- .Times(5)
- .WillRepeatedly(InvokeReadPacket(this));
- EXPECT_CALL(statistics_cb_, OnStatistics(_))
- .Times(4);
-
- Read();
- Read();
- Read();
+ Decode();
+ Decode();
+ Decode();
+ Decode();
ASSERT_EQ(3u, decoded_audio_.size());
ExpectDecodedAudio(0, 0, 2902);
ExpectDecodedAudio(1, 2902, 13061);
- ExpectDecodedAudio(2, 15963, 23220);
+ ExpectDecodedAudio(2, 15963, 23219);
- // Call one more time to trigger EOS.
- Read();
- ASSERT_EQ(4u, decoded_audio_.size());
- ExpectEndOfStream(3);
+ // Call one more time with EOS.
+ Decode();
+ ASSERT_EQ(3u, decoded_audio_.size());
+ Stop();
}
-TEST_F(FFmpegAudioDecoderTest, ReadAbort) {
- Initialize();
-
- encoded_audio_.clear();
- encoded_audio_.push_back(NULL);
+TEST_F(FFmpegAudioDecoderTest, PendingDecode_Stop) {
+ Decode();
+ Stop();
+ SatisfyPendingDecode();
+}
- EXPECT_CALL(*demuxer_, Read(_))
- .WillOnce(InvokeReadPacket(this));
- Read();
+TEST_F(FFmpegAudioDecoderTest, PendingDecode_Reset) {
+ Decode();
+ Reset();
+ SatisfyPendingDecode();
+ Stop();
+}
- EXPECT_EQ(decoded_audio_.size(), 1u);
- EXPECT_TRUE(decoded_audio_[0].get() == NULL);
+TEST_F(FFmpegAudioDecoderTest, PendingDecode_ResetStop) {
+ Decode();
+ Reset();
+ Stop();
+ SatisfyPendingDecode();
}
} // namespace media