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