OLD | NEW |
1 // Copyright (c) 2010 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 "media/base/mock_ffmpeg.h" | 5 #include "media/base/mock_ffmpeg.h" |
6 | 6 |
7 #include "base/logging.h" | 7 #include "base/logging.h" |
8 #include "media/ffmpeg/ffmpeg_common.h" | 8 #include "media/ffmpeg/ffmpeg_common.h" |
9 | 9 |
10 using ::testing::_; | 10 using ::testing::_; |
11 using ::testing::AtMost; | 11 using ::testing::AtMost; |
12 using ::testing::DoAll; | 12 using ::testing::DoAll; |
13 using ::testing::Return; | 13 using ::testing::Return; |
14 using ::testing::SaveArg; | 14 using ::testing::SaveArg; |
15 | 15 |
16 namespace media { | 16 namespace media { |
17 | 17 |
18 MockFFmpeg* MockFFmpeg::instance_ = NULL; | 18 MockFFmpeg* MockFFmpeg::instance_ = NULL; |
19 URLProtocol* MockFFmpeg::protocol_ = NULL; | 19 URLProtocol* MockFFmpeg::protocol_ = NULL; |
20 | 20 |
21 MockFFmpeg::MockFFmpeg() | 21 MockFFmpeg::MockFFmpeg() |
22 : outstanding_packets_(0) { | 22 : outstanding_packets_(0) { |
| 23 CHECK(instance_ == NULL) << "Only a single MockFFmpeg instance can exist"; |
| 24 instance_ = this; |
| 25 |
23 // If we haven't assigned our static copy of URLProtocol, set up expectations | 26 // If we haven't assigned our static copy of URLProtocol, set up expectations |
24 // to catch the URLProtocol registered when the singleton instance of | 27 // to catch the URLProtocol registered when the singleton instance of |
25 // FFmpegGlue is created. | 28 // FFmpegGlue is created. |
26 // | 29 // |
27 // TODO(scherkus): this feels gross and I need to think of a way to better | 30 // TODO(scherkus): this feels gross and I need to think of a way to better |
28 // inject/mock singletons. | 31 // inject/mock singletons. |
29 if (!protocol_) { | 32 if (!protocol_) { |
30 EXPECT_CALL(*this, AVLogSetLevel(AV_LOG_QUIET)) | 33 EXPECT_CALL(*this, AVLogSetLevel(AV_LOG_QUIET)) |
31 .Times(AtMost(1)) | 34 .Times(AtMost(1)) |
32 .WillOnce(Return()); | 35 .WillOnce(Return()); |
33 EXPECT_CALL(*this, AVCodecInit()) | 36 EXPECT_CALL(*this, AVCodecInit()) |
34 .Times(AtMost(1)) | 37 .Times(AtMost(1)) |
35 .WillOnce(Return()); | 38 .WillOnce(Return()); |
36 EXPECT_CALL(*this, AVRegisterProtocol2(_,_)) | 39 EXPECT_CALL(*this, AVRegisterProtocol2(_,_)) |
37 .Times(AtMost(1)) | 40 .Times(AtMost(1)) |
38 .WillOnce(DoAll(SaveArg<0>(&protocol_), Return(0))); | 41 .WillOnce(DoAll(SaveArg<0>(&protocol_), Return(0))); |
39 EXPECT_CALL(*this, AVRegisterAll()) | 42 EXPECT_CALL(*this, AVRegisterAll()) |
40 .Times(AtMost(1)) | 43 .Times(AtMost(1)) |
41 .WillOnce(Return()); | 44 .WillOnce(Return()); |
42 } | 45 } |
43 // av_lockmgr_register() is also called from ~FFmpegLock(), so we expect | |
44 // it to be called at the end. | |
45 EXPECT_CALL(*this, AVRegisterLockManager(_)) | |
46 .Times(AtMost(2)) | |
47 .WillRepeatedly(Return(0)); | |
48 } | 46 } |
49 | 47 |
50 MockFFmpeg::~MockFFmpeg() { | 48 MockFFmpeg::~MockFFmpeg() { |
51 CHECK(!outstanding_packets_) | 49 CHECK(!outstanding_packets_) |
52 << "MockFFmpeg destroyed with outstanding packets"; | 50 << "MockFFmpeg destroyed with outstanding packets"; |
| 51 CHECK(instance_); |
| 52 instance_ = NULL; |
53 } | 53 } |
54 | 54 |
55 void MockFFmpeg::inc_outstanding_packets() { | 55 void MockFFmpeg::inc_outstanding_packets() { |
56 ++outstanding_packets_; | 56 ++outstanding_packets_; |
57 } | 57 } |
58 | 58 |
59 void MockFFmpeg::dec_outstanding_packets() { | 59 void MockFFmpeg::dec_outstanding_packets() { |
60 CHECK(outstanding_packets_ > 0); | 60 CHECK(outstanding_packets_ > 0); |
61 --outstanding_packets_; | 61 --outstanding_packets_; |
62 } | 62 } |
63 | 63 |
64 // static | 64 // static |
65 void MockFFmpeg::set(MockFFmpeg* instance) { | |
66 instance_ = instance; | |
67 } | |
68 | |
69 // static | |
70 MockFFmpeg* MockFFmpeg::get() { | 65 MockFFmpeg* MockFFmpeg::get() { |
71 return instance_; | 66 return instance_; |
72 } | 67 } |
73 | 68 |
74 // static | 69 // static |
75 URLProtocol* MockFFmpeg::protocol() { | 70 URLProtocol* MockFFmpeg::protocol() { |
76 return protocol_; | 71 return protocol_; |
77 } | 72 } |
78 | 73 |
79 // static | 74 // static |
80 void MockFFmpeg::DestructPacket(AVPacket* packet) { | 75 void MockFFmpeg::DestructPacket(AVPacket* packet) { |
81 delete [] packet->data; | 76 delete [] packet->data; |
82 packet->data = NULL; | 77 packet->data = NULL; |
83 packet->size = 0; | 78 packet->size = 0; |
84 } | 79 } |
85 | 80 |
86 // FFmpeg stubs that delegate to the FFmpegMock instance. | 81 // FFmpeg stubs that delegate to the FFmpegMock instance. |
87 extern "C" { | 82 extern "C" { |
88 void avcodec_init() { | 83 void avcodec_init() { |
89 media::MockFFmpeg::get()->AVCodecInit(); | 84 MockFFmpeg::get()->AVCodecInit(); |
90 } | 85 } |
91 | 86 |
92 int av_register_protocol2(URLProtocol* protocol, int size) { | 87 int av_register_protocol2(URLProtocol* protocol, int size) { |
93 return media::MockFFmpeg::get()->AVRegisterProtocol2(protocol, size); | 88 return MockFFmpeg::get()->AVRegisterProtocol2(protocol, size); |
94 } | 89 } |
95 | 90 |
96 void av_register_all() { | 91 void av_register_all() { |
97 media::MockFFmpeg::get()->AVRegisterAll(); | 92 MockFFmpeg::get()->AVRegisterAll(); |
98 } | 93 } |
99 | 94 |
100 int av_lockmgr_register(int (*cb)(void**, enum AVLockOp)) { | 95 int av_lockmgr_register(int (*cb)(void**, enum AVLockOp)) { |
101 media::MockFFmpeg* mock = media::MockFFmpeg::get(); | |
102 // Here |mock| may be NULL when this function is called from ~FFmpegGlue(). | 96 // Here |mock| may be NULL when this function is called from ~FFmpegGlue(). |
103 if (mock != NULL) { | 97 if (MockFFmpeg::get()) { |
104 return mock->AVRegisterLockManager(cb); | 98 return MockFFmpeg::get()->AVRegisterLockManager(cb); |
105 } else { | |
106 return 0; | |
107 } | 99 } |
| 100 return 0; |
108 } | 101 } |
109 | 102 |
110 AVCodec* avcodec_find_decoder(enum CodecID id) { | 103 AVCodec* avcodec_find_decoder(enum CodecID id) { |
111 return media::MockFFmpeg::get()->AVCodecFindDecoder(id); | 104 return MockFFmpeg::get()->AVCodecFindDecoder(id); |
112 } | 105 } |
113 | 106 |
114 int avcodec_open(AVCodecContext* avctx, AVCodec* codec) { | 107 int avcodec_open(AVCodecContext* avctx, AVCodec* codec) { |
115 return media::MockFFmpeg::get()->AVCodecOpen(avctx, codec); | 108 return MockFFmpeg::get()->AVCodecOpen(avctx, codec); |
116 } | 109 } |
117 | 110 |
118 int avcodec_close(AVCodecContext* avctx) { | 111 int avcodec_close(AVCodecContext* avctx) { |
119 return media::MockFFmpeg::get()->AVCodecClose(avctx); | 112 return MockFFmpeg::get()->AVCodecClose(avctx); |
120 } | 113 } |
121 | 114 |
122 int avcodec_thread_init(AVCodecContext* avctx, int threads) { | 115 int avcodec_thread_init(AVCodecContext* avctx, int threads) { |
123 return media::MockFFmpeg::get()->AVCodecThreadInit(avctx, threads); | 116 return MockFFmpeg::get()->AVCodecThreadInit(avctx, threads); |
124 } | 117 } |
125 | 118 |
126 void avcodec_flush_buffers(AVCodecContext* avctx) { | 119 void avcodec_flush_buffers(AVCodecContext* avctx) { |
127 return media::MockFFmpeg::get()->AVCodecFlushBuffers(avctx); | 120 return MockFFmpeg::get()->AVCodecFlushBuffers(avctx); |
128 } | 121 } |
129 | 122 |
130 AVFrame* avcodec_alloc_frame() { | 123 AVFrame* avcodec_alloc_frame() { |
131 return media::MockFFmpeg::get()->AVCodecAllocFrame(); | 124 return MockFFmpeg::get()->AVCodecAllocFrame(); |
132 } | 125 } |
133 | 126 |
134 int avcodec_decode_video2(AVCodecContext* avctx, AVFrame* picture, | 127 int avcodec_decode_video2(AVCodecContext* avctx, AVFrame* picture, |
135 int* got_picture_ptr, AVPacket* avpkt) { | 128 int* got_picture_ptr, AVPacket* avpkt) { |
136 return media::MockFFmpeg::get()-> | 129 return MockFFmpeg::get()-> |
137 AVCodecDecodeVideo2(avctx, picture, got_picture_ptr, avpkt); | 130 AVCodecDecodeVideo2(avctx, picture, got_picture_ptr, avpkt); |
138 } | 131 } |
139 | 132 |
140 AVBitStreamFilterContext* av_bitstream_filter_init(const char* name) { | 133 AVBitStreamFilterContext* av_bitstream_filter_init(const char* name) { |
141 return media::MockFFmpeg::get()->AVBitstreamFilterInit(name); | 134 return MockFFmpeg::get()->AVBitstreamFilterInit(name); |
142 } | 135 } |
143 | 136 |
144 int av_bitstream_filter_filter(AVBitStreamFilterContext* bsfc, | 137 int av_bitstream_filter_filter(AVBitStreamFilterContext* bsfc, |
145 AVCodecContext* avctx, | 138 AVCodecContext* avctx, |
146 const char* args, | 139 const char* args, |
147 uint8_t** poutbuf, | 140 uint8_t** poutbuf, |
148 int* poutbuf_size, | 141 int* poutbuf_size, |
149 const uint8_t* buf, | 142 const uint8_t* buf, |
150 int buf_size, | 143 int buf_size, |
151 int keyframe) { | 144 int keyframe) { |
152 return media::MockFFmpeg::get()-> | 145 return MockFFmpeg::get()-> |
153 AVBitstreamFilterFilter(bsfc, avctx, args, poutbuf, poutbuf_size, buf, | 146 AVBitstreamFilterFilter(bsfc, avctx, args, poutbuf, poutbuf_size, buf, |
154 buf_size, keyframe); | 147 buf_size, keyframe); |
155 } | 148 } |
156 | 149 |
157 void av_bitstream_filter_close(AVBitStreamFilterContext* bsf) { | 150 void av_bitstream_filter_close(AVBitStreamFilterContext* bsf) { |
158 return media::MockFFmpeg::get()->AVBitstreamFilterClose(bsf); | 151 return MockFFmpeg::get()->AVBitstreamFilterClose(bsf); |
159 } | 152 } |
160 | 153 |
161 int av_open_input_file(AVFormatContext** format, const char* filename, | 154 int av_open_input_file(AVFormatContext** format, const char* filename, |
162 AVInputFormat* input_format, int buffer_size, | 155 AVInputFormat* input_format, int buffer_size, |
163 AVFormatParameters* parameters) { | 156 AVFormatParameters* parameters) { |
164 return media::MockFFmpeg::get()->AVOpenInputFile(format, filename, | 157 return MockFFmpeg::get()->AVOpenInputFile(format, filename, |
165 input_format, buffer_size, | 158 input_format, buffer_size, |
166 parameters); | 159 parameters); |
167 } | 160 } |
168 | 161 |
169 void av_close_input_file(AVFormatContext* format) { | 162 void av_close_input_file(AVFormatContext* format) { |
170 media::MockFFmpeg::get()->AVCloseInputFile(format); | 163 MockFFmpeg::get()->AVCloseInputFile(format); |
171 } | 164 } |
172 | 165 |
173 int av_find_stream_info(AVFormatContext* format) { | 166 int av_find_stream_info(AVFormatContext* format) { |
174 return media::MockFFmpeg::get()->AVFindStreamInfo(format); | 167 return MockFFmpeg::get()->AVFindStreamInfo(format); |
175 } | 168 } |
176 | 169 |
177 int64 av_rescale_q(int64 a, AVRational bq, AVRational cq) { | 170 int64 av_rescale_q(int64 a, AVRational bq, AVRational cq) { |
178 // Because this is a math function there's little point in mocking it, so we | 171 // Because this is a math function there's little point in mocking it, so we |
179 // implement a cheap version that's capable of overflowing. | 172 // implement a cheap version that's capable of overflowing. |
180 int64 num = bq.num * cq.den; | 173 int64 num = bq.num * cq.den; |
181 int64 den = cq.num * bq.den; | 174 int64 den = cq.num * bq.den; |
182 return a * num / den; | 175 return a * num / den; |
183 } | 176 } |
184 | 177 |
185 int av_read_frame(AVFormatContext* format, AVPacket* packet) { | 178 int av_read_frame(AVFormatContext* format, AVPacket* packet) { |
186 return media::MockFFmpeg::get()->AVReadFrame(format, packet); | 179 return MockFFmpeg::get()->AVReadFrame(format, packet); |
187 } | 180 } |
188 | 181 |
189 int av_seek_frame(AVFormatContext *format, int stream_index, int64_t timestamp, | 182 int av_seek_frame(AVFormatContext *format, int stream_index, int64_t timestamp, |
190 int flags) { | 183 int flags) { |
191 return media::MockFFmpeg::get()->AVSeekFrame(format, stream_index, timestamp, | 184 return MockFFmpeg::get()->AVSeekFrame(format, stream_index, timestamp, |
192 flags); | 185 flags); |
193 } | 186 } |
194 | 187 |
195 void av_init_packet(AVPacket* pkt) { | 188 void av_init_packet(AVPacket* pkt) { |
196 return media::MockFFmpeg::get()->AVInitPacket(pkt); | 189 return MockFFmpeg::get()->AVInitPacket(pkt); |
197 } | 190 } |
198 | 191 |
199 int av_new_packet(AVPacket* packet, int size) { | 192 int av_new_packet(AVPacket* packet, int size) { |
200 return media::MockFFmpeg::get()->AVNewPacket(packet, size); | 193 return MockFFmpeg::get()->AVNewPacket(packet, size); |
201 } | 194 } |
202 | 195 |
203 void av_free_packet(AVPacket* packet) { | 196 void av_free_packet(AVPacket* packet) { |
204 media::MockFFmpeg::get()->AVFreePacket(packet); | 197 MockFFmpeg::get()->AVFreePacket(packet); |
205 } | 198 } |
206 | 199 |
207 void av_free(void* ptr) { | 200 void av_free(void* ptr) { |
208 // Freeing NULL pointers are valid, but they aren't interesting from a mock | 201 // Freeing NULL pointers are valid, but they aren't interesting from a mock |
209 // perspective. | 202 // perspective. |
210 if (ptr) { | 203 if (ptr) { |
211 media::MockFFmpeg::get()->AVFree(ptr); | 204 MockFFmpeg::get()->AVFree(ptr); |
212 } | 205 } |
213 } | 206 } |
214 | 207 |
215 int av_dup_packet(AVPacket* packet) { | 208 int av_dup_packet(AVPacket* packet) { |
216 return media::MockFFmpeg::get()->AVDupPacket(packet); | 209 return MockFFmpeg::get()->AVDupPacket(packet); |
217 } | 210 } |
218 | 211 |
219 void av_log_set_level(int level) { | 212 void av_log_set_level(int level) { |
220 media::MockFFmpeg::get()->AVLogSetLevel(level); | 213 MockFFmpeg::get()->AVLogSetLevel(level); |
221 } | 214 } |
222 | 215 |
223 void av_destruct_packet(AVPacket *pkt) { | 216 void av_destruct_packet(AVPacket *pkt) { |
224 media::MockFFmpeg::get()->AVDestructPacket(pkt); | 217 MockFFmpeg::get()->AVDestructPacket(pkt); |
225 } | 218 } |
226 | 219 |
227 } // extern "C" | 220 } // extern "C" |
228 | 221 |
229 } // namespace media | 222 } // namespace media |
OLD | NEW |