15821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Copyright (c) 2012 The Chromium Authors. All rights reserved.
25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be
35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// found in the LICENSE file.
45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
55821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// ffmpeg_unittests verify that the parts of the FFmpeg API that Chromium uses
65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// function as advertised for each media format that Chromium supports.  This
75821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// mostly includes stuff like reporting proper timestamps, seeking to
85821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// keyframes, and supporting certain features like reordered_opaque.
95821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//
105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <limits>
125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <queue>
135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/base_paths.h"
152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "base/files/file_path.h"
161320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci#include "base/files/file_util.h"
172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "base/files/memory_mapped_file.h"
185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/memory/scoped_ptr.h"
195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/path_service.h"
20868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include "base/strings/string_util.h"
215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/test/perf_test_suite.h"
22d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)#include "base/test/perf_time_logger.h"
235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "media/base/media.h"
245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "media/ffmpeg/ffmpeg_common.h"
255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "media/filters/ffmpeg_glue.h"
265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "media/filters/in_memory_url_protocol.h"
275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "testing/gtest/include/gtest/gtest.h"
285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)int main(int argc, char** argv) {
305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return base::PerfTestSuite(argc, argv).Run();
315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace media {
345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Mirror setting in ffmpeg_video_decoder.
365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static const int kDecodeThreads = 2;
375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class AVPacketQueue {
395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) public:
405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  AVPacketQueue() {
415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ~AVPacketQueue() {
445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    flush();
455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bool empty() {
485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return packets_.empty();
495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  AVPacket* peek() {
525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return packets_.front();
535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void pop() {
565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    AVPacket* packet = packets_.front();
575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    packets_.pop();
585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    av_free_packet(packet);
595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    delete packet;
605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void push(AVPacket* packet) {
635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    av_dup_packet(packet);
645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    packets_.push(packet);
655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void flush() {
685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    while (!empty()) {
695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      pop();
705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) private:
745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::queue<AVPacket*> packets_;
755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DISALLOW_COPY_AND_ASSIGN(AVPacketQueue);
775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// TODO(dalecurtis): We should really just use PipelineIntegrationTests instead
805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// of a one-off step decoder so we're exercising the real pipeline.
815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class FFmpegTest : public testing::TestWithParam<const char*> {
825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) protected:
835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  FFmpegTest()
845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      : av_format_context_(NULL),
855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        audio_stream_index_(-1),
865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        video_stream_index_(-1),
875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        decoded_audio_time_(AV_NOPTS_VALUE),
885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        decoded_audio_duration_(AV_NOPTS_VALUE),
895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        decoded_video_time_(AV_NOPTS_VALUE),
905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        decoded_video_duration_(AV_NOPTS_VALUE),
915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        duration_(AV_NOPTS_VALUE) {
925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    InitializeFFmpeg();
935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
945d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    audio_buffer_.reset(av_frame_alloc());
955d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    video_buffer_.reset(av_frame_alloc());
965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual ~FFmpegTest() {
995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void OpenAndReadFile(const std::string& name) {
1025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    OpenFile(name);
1035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    OpenCodecs();
1045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ReadRemainingFile();
1055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void OpenFile(const std::string& name) {
1082a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    base::FilePath path;
1095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    PathService::Get(base::DIR_SOURCE_ROOT, &path);
1105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    path = path.AppendASCII("media")
1115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        .AppendASCII("test")
1125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        .AppendASCII("data")
1135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        .AppendASCII("content")
1145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        .AppendASCII(name.c_str());
1157dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    EXPECT_TRUE(base::PathExists(path));
1165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    CHECK(file_data_.Initialize(path));
1185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    protocol_.reset(new InMemoryUrlProtocol(
1195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        file_data_.data(), file_data_.length(), false));
1205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    glue_.reset(new FFmpegGlue(protocol_.get()));
1215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ASSERT_TRUE(glue_->OpenContext()) << "Could not open " << path.value();
1235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    av_format_context_ = glue_->format_context();
1245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ASSERT_LE(0, avformat_find_stream_info(av_format_context_, NULL))
1255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        << "Could not find stream information for " << path.value();
1265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Determine duration by picking max stream duration.
1285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    for (unsigned int i = 0; i < av_format_context_->nb_streams; ++i) {
1295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      AVStream* av_stream = av_format_context_->streams[i];
1305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      int64 duration = ConvertFromTimeBase(
1315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          av_stream->time_base, av_stream->duration).InMicroseconds();
1325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      duration_ = std::max(duration_, duration);
1335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
1345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Final check to see if the container itself specifies a duration.
1365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    AVRational av_time_base = {1, AV_TIME_BASE};
1375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    int64 duration =
1385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        ConvertFromTimeBase(av_time_base,
1395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                            av_format_context_->duration).InMicroseconds();
1405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    duration_ = std::max(duration_, duration);
1415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void OpenCodecs() {
1445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    for (unsigned int i = 0; i < av_format_context_->nb_streams; ++i) {
1455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      AVStream* av_stream = av_format_context_->streams[i];
1465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      AVCodecContext* av_codec_context = av_stream->codec;
1475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      AVCodec* av_codec = avcodec_find_decoder(av_codec_context->codec_id);
1485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      EXPECT_TRUE(av_codec)
1505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          << "Could not find AVCodec with CodecID "
1515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          << av_codec_context->codec_id;
1525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      av_codec_context->error_concealment = FF_EC_GUESS_MVS | FF_EC_DEBLOCK;
1545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      av_codec_context->thread_count = kDecodeThreads;
1555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      EXPECT_EQ(0, avcodec_open2(av_codec_context, av_codec, NULL))
1575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          << "Could not open AVCodecContext with CodecID "
1585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          << av_codec_context->codec_id;
1595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if (av_codec->type == AVMEDIA_TYPE_AUDIO) {
1615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        EXPECT_EQ(-1, audio_stream_index_) << "Found multiple audio streams.";
1625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        audio_stream_index_ = static_cast<int>(i);
1635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      } else if (av_codec->type == AVMEDIA_TYPE_VIDEO) {
1645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        EXPECT_EQ(-1, video_stream_index_) << "Found multiple video streams.";
1655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        video_stream_index_ = static_cast<int>(i);
1665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      } else {
1675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        ADD_FAILURE() << "Found unknown stream type.";
1685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
1695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
1705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void Flush() {
1735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (has_audio()) {
1745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      audio_packets_.flush();
1755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      avcodec_flush_buffers(av_audio_context());
1765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
1775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (has_video()) {
1785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      video_packets_.flush();
1795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      avcodec_flush_buffers(av_video_context());
1805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
1815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void ReadUntil(int64 time) {
1845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    while (true) {
1855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      scoped_ptr<AVPacket> packet(new AVPacket());
1865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if (av_read_frame(av_format_context_, packet.get()) < 0) {
1875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        break;
1885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
1895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      int stream_index = static_cast<int>(packet->stream_index);
1915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      int64 packet_time = AV_NOPTS_VALUE;
1925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if (stream_index == audio_stream_index_) {
1935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        packet_time =
1945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            ConvertFromTimeBase(av_audio_stream()->time_base, packet->pts)
1955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                .InMicroseconds();
1965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        audio_packets_.push(packet.release());
1975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      } else if (stream_index == video_stream_index_) {
1985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        packet_time =
1995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            ConvertFromTimeBase(av_video_stream()->time_base, packet->pts)
2005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                .InMicroseconds();
2015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        video_packets_.push(packet.release());
2025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      } else {
2035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        ADD_FAILURE() << "Found packet that belongs to unknown stream.";
2045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
2055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if (packet_time > time) {
2075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        break;
2085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
2095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
2105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void ReadRemainingFile() {
2135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ReadUntil(std::numeric_limits<int64>::max());
2145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bool StepDecodeAudio() {
2175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    EXPECT_TRUE(has_audio());
2185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (!has_audio() || audio_packets_.empty()) {
2195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return false;
2205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
2215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Decode until output is produced, end of stream, or error.
2235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    while (true) {
2245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      int result = 0;
2255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      int got_audio = 0;
2265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      bool end_of_stream = false;
2275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      AVPacket packet;
2295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if (audio_packets_.empty()) {
2305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        av_init_packet(&packet);
2315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        end_of_stream = true;
2325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      } else {
2335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        memcpy(&packet, audio_packets_.peek(), sizeof(packet));
2345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
2355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
236cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      av_frame_unref(audio_buffer_.get());
2375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      result = avcodec_decode_audio4(av_audio_context(), audio_buffer_.get(),
2385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                     &got_audio, &packet);
2395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if (!audio_packets_.empty()) {
2405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        audio_packets_.pop();
2415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
2425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      EXPECT_GE(result, 0) << "Audio decode error.";
2445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if (result < 0 || (got_audio == 0 && end_of_stream)) {
2455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        return false;
2465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
2475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if (result > 0) {
2495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        double microseconds = 1.0L * audio_buffer_->nb_samples /
2505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            av_audio_context()->sample_rate *
2515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            base::Time::kMicrosecondsPerSecond;
2525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        decoded_audio_duration_ = static_cast<int64>(microseconds);
2535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        if (packet.pts == static_cast<int64>(AV_NOPTS_VALUE)) {
2555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          EXPECT_NE(decoded_audio_time_, static_cast<int64>(AV_NOPTS_VALUE))
2565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)              << "We never received an initial timestamped audio packet! "
2575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)              << "Looks like there's a seeking/parsing bug in FFmpeg.";
2585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          decoded_audio_time_ += decoded_audio_duration_;
2595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        } else {
2605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          decoded_audio_time_ =
2615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)              ConvertFromTimeBase(av_audio_stream()->time_base, packet.pts)
2625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                  .InMicroseconds();
2635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        }
2645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        return true;
2655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
2665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
2675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return true;
2685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bool StepDecodeVideo() {
2715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    EXPECT_TRUE(has_video());
2725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (!has_video() || video_packets_.empty()) {
2735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return false;
2745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
2755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Decode until output is produced, end of stream, or error.
2775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    while (true) {
2785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      int result = 0;
2795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      int got_picture = 0;
2805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      bool end_of_stream = false;
2815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      AVPacket packet;
2835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if (video_packets_.empty()) {
2845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        av_init_packet(&packet);
2855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        end_of_stream = true;
2865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      } else {
2875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        memcpy(&packet, video_packets_.peek(), sizeof(packet));
2885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
2895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
290cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      av_frame_unref(video_buffer_.get());
2915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      av_video_context()->reordered_opaque = packet.pts;
2925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      result = avcodec_decode_video2(av_video_context(), video_buffer_.get(),
2935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                     &got_picture, &packet);
2945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if (!video_packets_.empty()) {
2955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        video_packets_.pop();
2965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
2975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      EXPECT_GE(result, 0) << "Video decode error.";
2995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if (result < 0 || (got_picture == 0 && end_of_stream)) {
3005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        return false;
3015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
3025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if (got_picture) {
3045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        AVRational doubled_time_base;
3055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        doubled_time_base.den = av_video_stream()->r_frame_rate.num;
3065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        doubled_time_base.num = av_video_stream()->r_frame_rate.den;
3075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        doubled_time_base.den *= 2;
3085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        decoded_video_time_ =
3105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            ConvertFromTimeBase(av_video_stream()->time_base,
3115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                             video_buffer_->reordered_opaque)
3125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                .InMicroseconds();
3135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        decoded_video_duration_ =
3145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            ConvertFromTimeBase(doubled_time_base,
3155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                             2 + video_buffer_->repeat_pict)
3165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                .InMicroseconds();
3175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        return true;
3185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
3195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
3205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
3215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void DecodeRemainingAudio() {
3235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    while (StepDecodeAudio()) {}
3245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
3255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void DecodeRemainingVideo() {
3275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    while (StepDecodeVideo()) {}
3285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
3295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void SeekTo(double position) {
3315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    int64 seek_time =
3325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        static_cast<int64>(position * base::Time::kMicrosecondsPerSecond);
3335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    int flags = AVSEEK_FLAG_BACKWARD;
3345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Passing -1 as our stream index lets FFmpeg pick a default stream.
3365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // FFmpeg will attempt to use the lowest-index video stream, if present,
3375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // followed by the lowest-index audio stream.
3385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    EXPECT_GE(0, av_seek_frame(av_format_context_, -1, seek_time, flags))
3395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        << "Failed to seek to position " << position;
3405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    Flush();
3415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
3425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bool has_audio() { return audio_stream_index_ >= 0; }
3445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bool has_video() { return video_stream_index_ >= 0; }
3455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int64 decoded_audio_time() { return decoded_audio_time_; }
3465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int64 decoded_audio_duration() { return decoded_audio_duration_; }
3475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int64 decoded_video_time() { return decoded_video_time_; }
3485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int64 decoded_video_duration() { return decoded_video_duration_; }
3495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int64 duration() { return duration_; }
3505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  AVStream* av_audio_stream() {
3525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return av_format_context_->streams[audio_stream_index_];
3535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
3545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  AVStream* av_video_stream() {
3555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return av_format_context_->streams[video_stream_index_];
3565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
3575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  AVCodecContext* av_audio_context() {
3585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return av_audio_stream()->codec;
3595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
3605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  AVCodecContext* av_video_context() {
3615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return av_video_stream()->codec;
3625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
3635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) private:
3655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void InitializeFFmpeg() {
3665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    static bool initialized = false;
3675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (initialized) {
3685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return;
3695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
3705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3712a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    base::FilePath path;
3725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    PathService::Get(base::DIR_MODULE, &path);
3735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    EXPECT_TRUE(InitializeMediaLibrary(path))
3745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        << "Could not initialize media library.";
3755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    initialized = true;
3775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
3785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  AVFormatContext* av_format_context_;
3805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int audio_stream_index_;
3815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int video_stream_index_;
3825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  AVPacketQueue audio_packets_;
3835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  AVPacketQueue video_packets_;
3845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
385a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  scoped_ptr<AVFrame, media::ScopedPtrAVFreeFrame> audio_buffer_;
386a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  scoped_ptr<AVFrame, media::ScopedPtrAVFreeFrame> video_buffer_;
3875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int64 decoded_audio_time_;
3895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int64 decoded_audio_duration_;
3905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int64 decoded_video_time_;
3915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int64 decoded_video_duration_;
3925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int64 duration_;
3935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3942a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  base::MemoryMappedFile file_data_;
3955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  scoped_ptr<InMemoryUrlProtocol> protocol_;
3965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  scoped_ptr<FFmpegGlue> glue_;
3975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DISALLOW_COPY_AND_ASSIGN(FFmpegTest);
3995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
4005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#define FFMPEG_TEST_CASE(name, extension) \
4025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    INSTANTIATE_TEST_CASE_P(name##_##extension, FFmpegTest, \
4035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                            testing::Values(#name "." #extension));
4045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Covers all our basic formats.
4065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)FFMPEG_TEST_CASE(sync0, mp4);
4075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)FFMPEG_TEST_CASE(sync0, ogv);
4085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)FFMPEG_TEST_CASE(sync0, webm);
4095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)FFMPEG_TEST_CASE(sync1, m4a);
4105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)FFMPEG_TEST_CASE(sync1, mp3);
4115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)FFMPEG_TEST_CASE(sync1, mp4);
4125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)FFMPEG_TEST_CASE(sync1, ogg);
4135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)FFMPEG_TEST_CASE(sync1, ogv);
4145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)FFMPEG_TEST_CASE(sync1, webm);
4155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)FFMPEG_TEST_CASE(sync2, m4a);
4165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)FFMPEG_TEST_CASE(sync2, mp3);
4175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)FFMPEG_TEST_CASE(sync2, mp4);
4185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)FFMPEG_TEST_CASE(sync2, ogg);
4195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)FFMPEG_TEST_CASE(sync2, ogv);
4205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)FFMPEG_TEST_CASE(sync2, webm);
4215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Covers our LayoutTest file.
4235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)FFMPEG_TEST_CASE(counting, ogv);
4245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)TEST_P(FFmpegTest, Perf) {
4265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  {
427d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)    base::PerfTimeLogger timer("Opening file");
4285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    OpenFile(GetParam());
4295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
4305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  {
431d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)    base::PerfTimeLogger timer("Opening codecs");
4325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    OpenCodecs();
4335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
4345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  {
435d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)    base::PerfTimeLogger timer("Reading file");
4365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ReadRemainingFile();
4375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
4385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (has_audio()) {
439d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)    base::PerfTimeLogger timer("Decoding audio");
4405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    DecodeRemainingAudio();
4415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
4425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (has_video()) {
443d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)    base::PerfTimeLogger timer("Decoding video");
4445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    DecodeRemainingVideo();
4455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
4465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  {
447d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)    base::PerfTimeLogger timer("Seeking to zero");
4485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    SeekTo(0);
4495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
4505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
4515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)TEST_P(FFmpegTest, Loop_Audio) {
4535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  OpenAndReadFile(GetParam());
4545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!has_audio()) {
4555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
4565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
4575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const int kSteps = 4;
4595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::vector<int64> expected_timestamps_;
4605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (int i = 0; i < kSteps; ++i) {
4615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    EXPECT_TRUE(StepDecodeAudio());
4625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    expected_timestamps_.push_back(decoded_audio_time());
4635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
4645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  SeekTo(0);
4665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ReadRemainingFile();
4675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (int i = 0; i < kSteps; ++i) {
4695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    EXPECT_TRUE(StepDecodeAudio());
4705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    EXPECT_EQ(expected_timestamps_[i], decoded_audio_time())
4715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        << "Frame " << i << " had a mismatched timestamp.";
4725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
4735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
4745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)TEST_P(FFmpegTest, Loop_Video) {
4765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  OpenAndReadFile(GetParam());
4775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!has_video()) {
4785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
4795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
4805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const int kSteps = 4;
4825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::vector<int64> expected_timestamps_;
4835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (int i = 0; i < kSteps; ++i) {
4845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    EXPECT_TRUE(StepDecodeVideo());
4855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    expected_timestamps_.push_back(decoded_video_time());
4865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
4875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  SeekTo(0);
4895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ReadRemainingFile();
4905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (int i = 0; i < kSteps; ++i) {
4925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    EXPECT_TRUE(StepDecodeVideo());
4935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    EXPECT_EQ(expected_timestamps_[i], decoded_video_time())
4945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        << "Frame " << i << " had a mismatched timestamp.";
4955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
4965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
4975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)TEST_P(FFmpegTest, Seek_Audio) {
4995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  OpenAndReadFile(GetParam());
5005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!has_audio() && duration() >= 0.5) {
5015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
5025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
5035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  SeekTo(duration() - 0.5);
5055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ReadRemainingFile();
5065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_TRUE(StepDecodeAudio());
5085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_NE(static_cast<int64>(AV_NOPTS_VALUE), decoded_audio_time());
5095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
5105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)TEST_P(FFmpegTest, Seek_Video) {
5125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  OpenAndReadFile(GetParam());
5135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!has_video() && duration() >= 0.5) {
5145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
5155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
5165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  SeekTo(duration() - 0.5);
5185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ReadRemainingFile();
5195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_TRUE(StepDecodeVideo());
5215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_NE(static_cast<int64>(AV_NOPTS_VALUE), decoded_video_time());
5225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
5235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)TEST_P(FFmpegTest, Decode_Audio) {
5255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  OpenAndReadFile(GetParam());
5265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!has_audio()) {
5275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
5285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
5295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int64 last_audio_time = AV_NOPTS_VALUE;
5315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  while (StepDecodeAudio()) {
5325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ASSERT_GT(decoded_audio_time(), last_audio_time);
5335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    last_audio_time = decoded_audio_time();
5345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
5355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
5365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)TEST_P(FFmpegTest, Decode_Video) {
5385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  OpenAndReadFile(GetParam());
5395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!has_video()) {
5405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
5415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
5425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int64 last_video_time = AV_NOPTS_VALUE;
5445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  while (StepDecodeVideo()) {
5455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ASSERT_GT(decoded_video_time(), last_video_time);
5465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    last_video_time = decoded_video_time();
5475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
5485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
5495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)TEST_P(FFmpegTest, Duration) {
5515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  OpenAndReadFile(GetParam());
5525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (has_audio()) {
5545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    DecodeRemainingAudio();
5555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
5565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (has_video()) {
5585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    DecodeRemainingVideo();
5595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
5605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  double expected = static_cast<double>(duration());
5625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  double actual = static_cast<double>(
5635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      std::max(decoded_audio_time() + decoded_audio_duration(),
5645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)               decoded_video_time() + decoded_video_duration()));
5655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_NEAR(expected, actual, 500000)
5665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      << "Duration is off by more than 0.5 seconds.";
5675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
5685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)TEST_F(FFmpegTest, VideoPlayedCollapse) {
5705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  OpenFile("test.ogv");
5715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  OpenCodecs();
5725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  SeekTo(0.5);
5745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ReadRemainingFile();
5755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_TRUE(StepDecodeVideo());
5765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  VLOG(1) << decoded_video_time();
5775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  SeekTo(2.83);
5795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ReadRemainingFile();
5805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_TRUE(StepDecodeVideo());
5815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  VLOG(1) << decoded_video_time();
5825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  SeekTo(0.4);
5845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ReadRemainingFile();
5855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_TRUE(StepDecodeVideo());
5865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  VLOG(1) << decoded_video_time();
5875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
5885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}  // namespace media
590