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