1// Copyright 2014 The Chromium Authors. All rights reserved. 2// Use of this source code is governed by a BSD-style license that can be 3// found in the LICENSE file. 4 5#include <sstream> 6#include <string> 7#include <vector> 8 9#include "base/bind.h" 10#include "base/logging.h" 11#include "base/strings/string_util.h" 12#include "base/time/time.h" 13#include "media/base/stream_parser_buffer.h" 14#include "media/base/video_decoder_config.h" 15#include "media/formats/mp2t/es_adapter_video.h" 16#include "testing/gtest/include/gtest/gtest.h" 17 18namespace media { 19namespace mp2t { 20 21namespace { 22 23VideoDecoderConfig CreateFakeVideoConfig() { 24 gfx::Size coded_size(320, 240); 25 gfx::Rect visible_rect(0, 0, 320, 240); 26 gfx::Size natural_size(320, 240); 27 return VideoDecoderConfig( 28 kCodecH264, 29 H264PROFILE_MAIN, 30 VideoFrame::I420, 31 coded_size, 32 visible_rect, 33 natural_size, 34 NULL, 0, false); 35} 36 37StreamParserBuffer::BufferQueue 38GenerateFakeBuffers(const int* frame_pts_ms, 39 const bool* is_key_frame, 40 size_t frame_count) { 41 uint8 dummy_buffer[] = {0, 0, 0, 0}; 42 43 StreamParserBuffer::BufferQueue buffers(frame_count); 44 for (size_t k = 0; k < frame_count; k++) { 45 buffers[k] = StreamParserBuffer::CopyFrom( 46 dummy_buffer, arraysize(dummy_buffer), 47 is_key_frame[k], DemuxerStream::VIDEO, 0); 48 buffers[k]->set_timestamp( 49 base::TimeDelta::FromMilliseconds(frame_pts_ms[k])); 50 } 51 return buffers; 52} 53 54} 55 56class EsAdapterVideoTest : public testing::Test { 57 public: 58 EsAdapterVideoTest(); 59 virtual ~EsAdapterVideoTest() {} 60 61 protected: 62 // Feed the ES adapter with the buffers from |buffer_queue|. 63 // Return the durations computed by the ES adapter as well as 64 // whether each frame emitted by the adapter is a key frame. 65 std::string RunAdapterTest(const StreamParser::BufferQueue& buffer_queue); 66 67 private: 68 void OnNewConfig(const VideoDecoderConfig& video_config); 69 void OnNewBuffer(scoped_refptr<StreamParserBuffer> buffer); 70 71 EsAdapterVideo es_adapter_; 72 73 std::stringstream buffer_descriptors_; 74 75 DISALLOW_COPY_AND_ASSIGN(EsAdapterVideoTest); 76}; 77 78EsAdapterVideoTest::EsAdapterVideoTest() 79 : es_adapter_(base::Bind(&EsAdapterVideoTest::OnNewConfig, 80 base::Unretained(this)), 81 base::Bind(&EsAdapterVideoTest::OnNewBuffer, 82 base::Unretained(this))) { 83} 84 85void EsAdapterVideoTest::OnNewConfig(const VideoDecoderConfig& video_config) { 86} 87 88void EsAdapterVideoTest::OnNewBuffer( 89 scoped_refptr<StreamParserBuffer> buffer) { 90 buffer_descriptors_ << "(" << buffer->duration().InMilliseconds() << "," 91 << (buffer->IsKeyframe() ? "Y" : "N") << ") "; 92} 93 94std::string EsAdapterVideoTest::RunAdapterTest( 95 const StreamParserBuffer::BufferQueue& buffer_queue) { 96 buffer_descriptors_.clear(); 97 98 es_adapter_.OnConfigChanged(CreateFakeVideoConfig()); 99 for (StreamParserBuffer::BufferQueue::const_iterator it = 100 buffer_queue.begin(); it != buffer_queue.end(); ++it) { 101 es_adapter_.OnNewBuffer(*it); 102 } 103 es_adapter_.Flush(); 104 105 std::string s = buffer_descriptors_.str(); 106 base::TrimWhitespaceASCII(s, base::TRIM_ALL, &s); 107 return s; 108} 109 110TEST_F(EsAdapterVideoTest, FrameDurationSimpleGop) { 111 // PTS for a GOP without B frames - strictly increasing. 112 int pts_ms[] = {30, 31, 33, 36, 40, 45, 51, 58}; 113 bool is_key_frame[] = { 114 true, false, false, false, 115 false, false, false, false }; 116 StreamParserBuffer::BufferQueue buffer_queue = 117 GenerateFakeBuffers(pts_ms, is_key_frame, arraysize(pts_ms)); 118 119 EXPECT_EQ("(1,Y) (2,N) (3,N) (4,N) (5,N) (6,N) (7,N) (7,N)", 120 RunAdapterTest(buffer_queue)); 121} 122 123TEST_F(EsAdapterVideoTest, FrameDurationComplexGop) { 124 // PTS for a GOP with B frames. 125 int pts_ms[] = {30, 120, 60, 90, 210, 150, 180, 300, 240, 270}; 126 bool is_key_frame[] = { 127 true, false, false, false, false, 128 false, false, false, false, false }; 129 StreamParserBuffer::BufferQueue buffer_queue = 130 GenerateFakeBuffers(pts_ms, is_key_frame, arraysize(pts_ms)); 131 132 EXPECT_EQ("(30,Y) (30,N) (30,N) (30,N) (30,N) " 133 "(30,N) (30,N) (30,N) (30,N) (30,N)", 134 RunAdapterTest(buffer_queue)); 135} 136 137TEST_F(EsAdapterVideoTest, LeadingNonKeyFrames) { 138 int pts_ms[] = {30, 40, 50, 120, 150, 180}; 139 bool is_key_frame[] = {false, false, false, true, false, false}; 140 StreamParserBuffer::BufferQueue buffer_queue = 141 GenerateFakeBuffers(pts_ms, is_key_frame, arraysize(pts_ms)); 142 143 EXPECT_EQ("(30,Y) (30,Y) (30,Y) (30,Y) (30,N) (30,N)", 144 RunAdapterTest(buffer_queue)); 145} 146 147} // namespace mp2t 148} // namespace media 149