OLD | NEW |
---|---|
1 // Copyright (c) 2011 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2011 The Chromium Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include <deque> | 5 #include <deque> |
6 | 6 |
7 #include "media/base/mock_ffmpeg.h" | |
8 #include "media/ffmpeg/ffmpeg_common.h" | 7 #include "media/ffmpeg/ffmpeg_common.h" |
9 #include "media/filters/bitstream_converter.h" | 8 #include "media/filters/bitstream_converter.h" |
10 #include "testing/gtest/include/gtest/gtest.h" | 9 #include "testing/gtest/include/gtest/gtest.h" |
11 | 10 |
12 using ::testing::DoAll; | |
13 using ::testing::Mock; | |
14 using ::testing::Return; | |
15 using ::testing::ReturnNull; | |
16 using ::testing::SetArgumentPointee; | |
17 using ::testing::StrEq; | |
18 using ::testing::StrictMock; | |
19 using ::testing::_; | |
20 | |
21 namespace media { | 11 namespace media { |
22 | 12 |
13 static const char kTestFilterName[] = "test_filter"; | |
14 static uint8_t kFailData[] = { 3, 2, 1 }; | |
15 static uint8_t kNewBufferData[] = { 2, 1 }; | |
16 static uint8_t kInPlaceData[] = { 1 }; | |
17 static const int kFailSize = 3; | |
18 static const int kNewBufferSize = 2; | |
19 static const int kInPlaceSize = 1; | |
20 | |
21 | |
22 // Test filter function that looks for specific input data and changes it's | |
23 // behavior based on what is passed to |buf| & |buf_size|. The three behaviors | |
24 // simulated are the following: | |
25 // - Create a new output buffer. Triggered by |buf| == |kNewBufferData|. | |
26 // - Use the existing output buffer. Triggered by |buf| == |kInPlaceData|. | |
27 // - Signal an error. Triggered by |buf| == |kFailData|. | |
28 static int DoFilter(AVBitStreamFilterContext *bsfc, | |
scherkus (not reviewing)
2011/08/12 21:32:21
pointers w/ types
acolwell GONE FROM CHROMIUM
2011/08/15 17:00:54
Done.
| |
29 AVCodecContext *avctx, | |
30 const char* args, | |
31 uint8_t** poutbuf, | |
32 int* poutbuf_size, | |
33 const uint8_t* buf, | |
34 int buf_size, | |
35 int keyframe) { | |
36 if (buf_size == kNewBufferSize && | |
37 !memcmp(buf, kNewBufferData, kNewBufferSize)) { | |
38 *poutbuf_size = buf_size + 1; | |
39 *poutbuf = static_cast<uint8*>(av_malloc(*poutbuf_size)); | |
40 *poutbuf[0] = 0; | |
41 memcpy((*poutbuf) + 1, buf, buf_size); | |
42 return 0; | |
43 } else if (buf_size == kInPlaceSize && | |
44 !memcmp(buf, kInPlaceData, kInPlaceSize)) { | |
45 return 0; | |
46 } | |
47 | |
48 return -1; | |
49 } | |
50 | |
51 static void DoClose(AVBitStreamFilterContext *bsfc) {} | |
52 | |
53 static AVBitStreamFilter g_stream_filter = { | |
54 kTestFilterName, | |
55 0, // Private Data Size | |
56 DoFilter, | |
57 DoClose, | |
58 0, | |
scherkus (not reviewing)
2011/08/12 21:32:21
want to doc this one as well?
acolwell GONE FROM CHROMIUM
2011/08/15 17:00:54
Done.
| |
59 }; | |
60 | |
23 class BitstreamConverterTest : public testing::Test { | 61 class BitstreamConverterTest : public testing::Test { |
62 public: | |
scherkus (not reviewing)
2011/08/12 21:32:21
remove?
acolwell GONE FROM CHROMIUM
2011/08/15 17:00:54
Done.
| |
63 | |
24 protected: | 64 protected: |
25 BitstreamConverterTest() { | 65 BitstreamConverterTest() { |
26 memset(&test_stream_context_, 0, sizeof(test_stream_context_)); | 66 memset(&test_stream_context_, 0, sizeof(test_stream_context_)); |
27 memset(&test_filter_, 0, sizeof(test_filter_)); | |
28 memset(&test_packet_, 0, sizeof(test_packet_)); | 67 memset(&test_packet_, 0, sizeof(test_packet_)); |
29 test_packet_.data = kData1; | 68 test_packet_.data = kFailData; |
30 test_packet_.size = kTestSize1; | 69 test_packet_.size = kFailSize; |
31 } | 70 } |
32 | 71 |
33 virtual ~BitstreamConverterTest() {} | 72 virtual ~BitstreamConverterTest() {} |
34 | 73 |
74 static void SetUpTestCase() { | |
75 // Register g_stream_filter if it isn't already registered. | |
76 if (!g_stream_filter.next) | |
77 av_register_bitstream_filter(&g_stream_filter); | |
78 } | |
79 | |
35 AVCodecContext test_stream_context_; | 80 AVCodecContext test_stream_context_; |
36 AVBitStreamFilterContext test_filter_; | |
37 AVPacket test_packet_; | 81 AVPacket test_packet_; |
38 | 82 |
39 StrictMock<MockFFmpeg> mock_ffmpeg_; | |
40 | |
41 static const char kTestFilterName[]; | |
42 static uint8_t kData1[]; | |
43 static uint8_t kData2[]; | |
44 static const int kTestSize1; | |
45 static const int kTestSize2; | |
46 | |
47 private: | 83 private: |
48 DISALLOW_COPY_AND_ASSIGN(BitstreamConverterTest); | 84 DISALLOW_COPY_AND_ASSIGN(BitstreamConverterTest); |
49 }; | 85 }; |
50 | 86 |
51 const char BitstreamConverterTest::kTestFilterName[] = "test_filter"; | 87 TEST_F(BitstreamConverterTest, InitializeFailed) { |
52 uint8_t BitstreamConverterTest::kData1[] = { 1 }; | 88 FFmpegBitstreamConverter converter("BAD_FILTER_NAME", &test_stream_context_); |
53 uint8_t BitstreamConverterTest::kData2[] = { 2 }; | |
54 const int BitstreamConverterTest::kTestSize1 = 1; | |
55 const int BitstreamConverterTest::kTestSize2 = 2; | |
56 | 89 |
57 TEST_F(BitstreamConverterTest, Initialize) { | 90 EXPECT_FALSE(converter.Initialize()); |
91 } | |
92 | |
93 TEST_F(BitstreamConverterTest, InitializeSuccess) { | |
58 FFmpegBitstreamConverter converter(kTestFilterName, &test_stream_context_); | 94 FFmpegBitstreamConverter converter(kTestFilterName, &test_stream_context_); |
59 | |
60 // Test Initialize returns false on a bad initialization, and cleanup is not | |
61 // done. | |
62 EXPECT_CALL(mock_ffmpeg_, AVBitstreamFilterInit(StrEq(kTestFilterName))) | |
63 .WillOnce(ReturnNull()); | |
64 EXPECT_FALSE(converter.Initialize()); | |
65 | |
66 EXPECT_TRUE(Mock::VerifyAndClearExpectations(&mock_ffmpeg_)); | |
67 | |
68 // Test Initialize returns true on successful initialization, and cleanup is | |
69 // done. The cleanup will be activated when the converter object goes out of | |
70 // scope. | |
71 EXPECT_CALL(mock_ffmpeg_, AVBitstreamFilterInit(StrEq(kTestFilterName))) | |
72 .WillOnce(Return(&test_filter_)); | |
73 EXPECT_CALL(mock_ffmpeg_, AVBitstreamFilterClose(&test_filter_)); | |
74 EXPECT_TRUE(converter.Initialize()); | 95 EXPECT_TRUE(converter.Initialize()); |
75 } | 96 } |
76 | 97 |
77 TEST_F(BitstreamConverterTest, ConvertPacket_NotInitialized) { | 98 TEST_F(BitstreamConverterTest, ConvertPacket_NotInitialized) { |
78 FFmpegBitstreamConverter converter(kTestFilterName, &test_stream_context_); | 99 FFmpegBitstreamConverter converter(kTestFilterName, &test_stream_context_); |
79 | 100 |
80 EXPECT_FALSE(converter.ConvertPacket(&test_packet_)); | 101 EXPECT_FALSE(converter.ConvertPacket(&test_packet_)); |
81 } | 102 } |
82 | 103 |
83 TEST_F(BitstreamConverterTest, ConvertPacket_FailedFilter) { | 104 TEST_F(BitstreamConverterTest, ConvertPacket_FailedFilter) { |
84 FFmpegBitstreamConverter converter(kTestFilterName, &test_stream_context_); | 105 FFmpegBitstreamConverter converter(kTestFilterName, &test_stream_context_); |
85 | 106 |
86 // Inject mock filter instance. | 107 EXPECT_TRUE(converter.Initialize()); |
87 converter.stream_filter_ = &test_filter_; | |
88 | |
89 // Simulate a successful filter call, that allocates a new data buffer. | |
90 EXPECT_CALL(mock_ffmpeg_, | |
91 AVBitstreamFilterFilter(&test_filter_, &test_stream_context_, | |
92 NULL, _, _, | |
93 test_packet_.data, test_packet_.size, _)) | |
94 .WillOnce(Return(AVERROR(EINVAL))); | |
95 | 108 |
96 EXPECT_FALSE(converter.ConvertPacket(&test_packet_)); | 109 EXPECT_FALSE(converter.ConvertPacket(&test_packet_)); |
97 | |
98 // Uninject mock filter instance to avoid cleanup code on destruction of | |
99 // converter. | |
100 converter.stream_filter_ = NULL; | |
101 } | 110 } |
102 | 111 |
103 TEST_F(BitstreamConverterTest, ConvertPacket_Success) { | 112 TEST_F(BitstreamConverterTest, ConvertPacket_Success) { |
104 FFmpegBitstreamConverter converter(kTestFilterName, &test_stream_context_); | 113 FFmpegBitstreamConverter converter(kTestFilterName, &test_stream_context_); |
105 | 114 |
106 // Inject mock filter instance. | 115 EXPECT_TRUE(converter.Initialize()); |
107 converter.stream_filter_ = &test_filter_; | |
108 | 116 |
109 // Ensure our packet doesn't already have a destructor. | 117 // Ensure our packet doesn't already have a destructor. |
110 ASSERT_TRUE(test_packet_.destruct == NULL); | 118 ASSERT_TRUE(test_packet_.destruct == NULL); |
111 | 119 |
112 // Simulate a successful filter call, that allocates a new data buffer. | 120 test_packet_.data = kNewBufferData; |
113 EXPECT_CALL(mock_ffmpeg_, | 121 test_packet_.size = kNewBufferSize; |
114 AVBitstreamFilterFilter(&test_filter_, &test_stream_context_, | |
115 NULL, _, _, | |
116 test_packet_.data, test_packet_.size, _)) | |
117 .WillOnce(DoAll(SetArgumentPointee<3>(&kData2[0]), | |
118 SetArgumentPointee<4>(kTestSize2), | |
119 Return(0))); | |
120 EXPECT_CALL(mock_ffmpeg_, AVFreePacket(&test_packet_)); | |
121 | 122 |
122 EXPECT_TRUE(converter.ConvertPacket(&test_packet_)); | 123 EXPECT_TRUE(converter.ConvertPacket(&test_packet_)); |
123 EXPECT_EQ(kData2, test_packet_.data); | 124 EXPECT_NE(kNewBufferData, test_packet_.data); |
124 EXPECT_EQ(kTestSize2, test_packet_.size); | 125 EXPECT_EQ(kNewBufferSize + 1, test_packet_.size); |
125 EXPECT_TRUE(test_packet_.destruct != NULL); | 126 EXPECT_TRUE(test_packet_.destruct != NULL); |
126 | |
127 // Uninject mock filter instance to avoid cleanup code on destruction of | |
128 // converter. | |
129 converter.stream_filter_ = NULL; | |
130 } | 127 } |
131 | 128 |
132 TEST_F(BitstreamConverterTest, ConvertPacket_SuccessInPlace) { | 129 TEST_F(BitstreamConverterTest, ConvertPacket_SuccessInPlace) { |
133 FFmpegBitstreamConverter converter(kTestFilterName, &test_stream_context_); | 130 FFmpegBitstreamConverter converter(kTestFilterName, &test_stream_context_); |
134 | 131 |
135 // Inject mock filter instance. | 132 EXPECT_TRUE(converter.Initialize()); |
136 converter.stream_filter_ = &test_filter_; | |
137 | 133 |
138 // Ensure our packet is in a sane start state. | 134 // Ensure our packet is in a sane start state. |
139 ASSERT_TRUE(test_packet_.destruct == NULL); | 135 ASSERT_TRUE(test_packet_.destruct == NULL); |
140 ASSERT_EQ(kData1, test_packet_.data); | 136 test_packet_.data = kInPlaceData; |
141 ASSERT_EQ(kTestSize1, test_packet_.size); | 137 test_packet_.size = kInPlaceSize; |
142 | |
143 // Simulate a successful filter call, that reuses the input buffer. We should | |
144 // not free the packet here or alter the packet's destructor. | |
145 EXPECT_CALL(mock_ffmpeg_, | |
146 AVBitstreamFilterFilter(&test_filter_, &test_stream_context_, | |
147 NULL, _, _, | |
148 test_packet_.data, test_packet_.size, _)) | |
149 .WillOnce(DoAll(SetArgumentPointee<3>(test_packet_.data), | |
150 SetArgumentPointee<4>(test_packet_.size), | |
151 Return(0))); | |
152 | 138 |
153 EXPECT_TRUE(converter.ConvertPacket(&test_packet_)); | 139 EXPECT_TRUE(converter.ConvertPacket(&test_packet_)); |
154 EXPECT_EQ(kData1, test_packet_.data); | 140 EXPECT_EQ(kInPlaceData, test_packet_.data); |
155 EXPECT_EQ(kTestSize1, test_packet_.size); | 141 EXPECT_EQ(kInPlaceSize, test_packet_.size); |
156 EXPECT_TRUE(test_packet_.destruct == NULL); | 142 EXPECT_TRUE(test_packet_.destruct == NULL); |
157 | |
158 // Uninject mock filter instance to avoid cleanup code on destruction of | |
159 // converter. | |
160 converter.stream_filter_ = NULL; | |
161 } | 143 } |
162 | 144 |
163 } // namespace media | 145 } // namespace media |
OLD | NEW |