| 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 static MockFFmpeg* g_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(g_instance == NULL) << "Only a single MockFFmpeg instance can exist"; |
| 24 g_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(g_instance); |
| 52 g_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 | |
| 75 URLProtocol* MockFFmpeg::protocol() { | 65 URLProtocol* MockFFmpeg::protocol() { |
| 76 return protocol_; | 66 return protocol_; |
| 77 } | 67 } |
| 78 | 68 |
| 79 // static | 69 // static |
| 80 void MockFFmpeg::DestructPacket(AVPacket* packet) { | 70 void MockFFmpeg::DestructPacket(AVPacket* packet) { |
| 81 delete [] packet->data; | 71 delete [] packet->data; |
| 82 packet->data = NULL; | 72 packet->data = NULL; |
| 83 packet->size = 0; | 73 packet->size = 0; |
| 84 } | 74 } |
| 85 | 75 |
| 86 // FFmpeg stubs that delegate to the FFmpegMock instance. | 76 // FFmpeg stubs that delegate to the FFmpegMock instance. |
| 87 extern "C" { | 77 extern "C" { |
| 88 void avcodec_init() { | 78 void avcodec_init() { |
| 89 media::MockFFmpeg::get()->AVCodecInit(); | 79 g_instance->AVCodecInit(); |
| 90 } | 80 } |
| 91 | 81 |
| 92 int av_register_protocol2(URLProtocol* protocol, int size) { | 82 int av_register_protocol2(URLProtocol* protocol, int size) { |
| 93 return media::MockFFmpeg::get()->AVRegisterProtocol2(protocol, size); | 83 return g_instance->AVRegisterProtocol2(protocol, size); |
| 94 } | 84 } |
| 95 | 85 |
| 96 void av_register_all() { | 86 void av_register_all() { |
| 97 media::MockFFmpeg::get()->AVRegisterAll(); | 87 g_instance->AVRegisterAll(); |
| 98 } | 88 } |
| 99 | 89 |
| 100 int av_lockmgr_register(int (*cb)(void**, enum AVLockOp)) { | 90 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(). | 91 // Here |mock| may be NULL when this function is called from ~FFmpegGlue(). |
| 103 if (mock != NULL) { | 92 if (g_instance) { |
| 104 return mock->AVRegisterLockManager(cb); | 93 return g_instance->AVRegisterLockManager(cb); |
| 105 } else { | |
| 106 return 0; | |
| 107 } | 94 } |
| 95 return 0; |
| 108 } | 96 } |
| 109 | 97 |
| 110 AVCodec* avcodec_find_decoder(enum CodecID id) { | 98 AVCodec* avcodec_find_decoder(enum CodecID id) { |
| 111 return media::MockFFmpeg::get()->AVCodecFindDecoder(id); | 99 return g_instance->AVCodecFindDecoder(id); |
| 112 } | 100 } |
| 113 | 101 |
| 114 int avcodec_open(AVCodecContext* avctx, AVCodec* codec) { | 102 int avcodec_open(AVCodecContext* avctx, AVCodec* codec) { |
| 115 return media::MockFFmpeg::get()->AVCodecOpen(avctx, codec); | 103 return g_instance->AVCodecOpen(avctx, codec); |
| 116 } | 104 } |
| 117 | 105 |
| 118 int avcodec_close(AVCodecContext* avctx) { | 106 int avcodec_close(AVCodecContext* avctx) { |
| 119 return media::MockFFmpeg::get()->AVCodecClose(avctx); | 107 return g_instance->AVCodecClose(avctx); |
| 120 } | 108 } |
| 121 | 109 |
| 122 int avcodec_thread_init(AVCodecContext* avctx, int threads) { | 110 int avcodec_thread_init(AVCodecContext* avctx, int threads) { |
| 123 return media::MockFFmpeg::get()->AVCodecThreadInit(avctx, threads); | 111 return g_instance->AVCodecThreadInit(avctx, threads); |
| 124 } | 112 } |
| 125 | 113 |
| 126 void avcodec_flush_buffers(AVCodecContext* avctx) { | 114 void avcodec_flush_buffers(AVCodecContext* avctx) { |
| 127 return media::MockFFmpeg::get()->AVCodecFlushBuffers(avctx); | 115 return g_instance->AVCodecFlushBuffers(avctx); |
| 128 } | 116 } |
| 129 | 117 |
| 130 AVFrame* avcodec_alloc_frame() { | 118 AVFrame* avcodec_alloc_frame() { |
| 131 return media::MockFFmpeg::get()->AVCodecAllocFrame(); | 119 return g_instance->AVCodecAllocFrame(); |
| 132 } | 120 } |
| 133 | 121 |
| 134 int avcodec_decode_video2(AVCodecContext* avctx, AVFrame* picture, | 122 int avcodec_decode_video2(AVCodecContext* avctx, AVFrame* picture, |
| 135 int* got_picture_ptr, AVPacket* avpkt) { | 123 int* got_picture_ptr, AVPacket* avpkt) { |
| 136 return media::MockFFmpeg::get()-> | 124 return g_instance-> |
| 137 AVCodecDecodeVideo2(avctx, picture, got_picture_ptr, avpkt); | 125 AVCodecDecodeVideo2(avctx, picture, got_picture_ptr, avpkt); |
| 138 } | 126 } |
| 139 | 127 |
| 140 AVBitStreamFilterContext* av_bitstream_filter_init(const char* name) { | 128 AVBitStreamFilterContext* av_bitstream_filter_init(const char* name) { |
| 141 return media::MockFFmpeg::get()->AVBitstreamFilterInit(name); | 129 return g_instance->AVBitstreamFilterInit(name); |
| 142 } | 130 } |
| 143 | 131 |
| 144 int av_bitstream_filter_filter(AVBitStreamFilterContext* bsfc, | 132 int av_bitstream_filter_filter(AVBitStreamFilterContext* bsfc, |
| 145 AVCodecContext* avctx, | 133 AVCodecContext* avctx, |
| 146 const char* args, | 134 const char* args, |
| 147 uint8_t** poutbuf, | 135 uint8_t** poutbuf, |
| 148 int* poutbuf_size, | 136 int* poutbuf_size, |
| 149 const uint8_t* buf, | 137 const uint8_t* buf, |
| 150 int buf_size, | 138 int buf_size, |
| 151 int keyframe) { | 139 int keyframe) { |
| 152 return media::MockFFmpeg::get()-> | 140 return g_instance-> |
| 153 AVBitstreamFilterFilter(bsfc, avctx, args, poutbuf, poutbuf_size, buf, | 141 AVBitstreamFilterFilter(bsfc, avctx, args, poutbuf, poutbuf_size, buf, |
| 154 buf_size, keyframe); | 142 buf_size, keyframe); |
| 155 } | 143 } |
| 156 | 144 |
| 157 void av_bitstream_filter_close(AVBitStreamFilterContext* bsf) { | 145 void av_bitstream_filter_close(AVBitStreamFilterContext* bsf) { |
| 158 return media::MockFFmpeg::get()->AVBitstreamFilterClose(bsf); | 146 return g_instance->AVBitstreamFilterClose(bsf); |
| 159 } | 147 } |
| 160 | 148 |
| 161 int av_open_input_file(AVFormatContext** format, const char* filename, | 149 int av_open_input_file(AVFormatContext** format, const char* filename, |
| 162 AVInputFormat* input_format, int buffer_size, | 150 AVInputFormat* input_format, int buffer_size, |
| 163 AVFormatParameters* parameters) { | 151 AVFormatParameters* parameters) { |
| 164 return media::MockFFmpeg::get()->AVOpenInputFile(format, filename, | 152 return g_instance->AVOpenInputFile(format, filename, |
| 165 input_format, buffer_size, | 153 input_format, buffer_size, |
| 166 parameters); | 154 parameters); |
| 167 } | 155 } |
| 168 | 156 |
| 169 void av_close_input_file(AVFormatContext* format) { | 157 void av_close_input_file(AVFormatContext* format) { |
| 170 media::MockFFmpeg::get()->AVCloseInputFile(format); | 158 g_instance->AVCloseInputFile(format); |
| 171 } | 159 } |
| 172 | 160 |
| 173 int av_find_stream_info(AVFormatContext* format) { | 161 int av_find_stream_info(AVFormatContext* format) { |
| 174 return media::MockFFmpeg::get()->AVFindStreamInfo(format); | 162 return g_instance->AVFindStreamInfo(format); |
| 175 } | 163 } |
| 176 | 164 |
| 177 int64 av_rescale_q(int64 a, AVRational bq, AVRational cq) { | 165 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 | 166 // 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. | 167 // implement a cheap version that's capable of overflowing. |
| 180 int64 num = bq.num * cq.den; | 168 int64 num = bq.num * cq.den; |
| 181 int64 den = cq.num * bq.den; | 169 int64 den = cq.num * bq.den; |
| 182 return a * num / den; | 170 return a * num / den; |
| 183 } | 171 } |
| 184 | 172 |
| 185 int av_read_frame(AVFormatContext* format, AVPacket* packet) { | 173 int av_read_frame(AVFormatContext* format, AVPacket* packet) { |
| 186 return media::MockFFmpeg::get()->AVReadFrame(format, packet); | 174 return g_instance->AVReadFrame(format, packet); |
| 187 } | 175 } |
| 188 | 176 |
| 189 int av_seek_frame(AVFormatContext *format, int stream_index, int64_t timestamp, | 177 int av_seek_frame(AVFormatContext *format, int stream_index, int64_t timestamp, |
| 190 int flags) { | 178 int flags) { |
| 191 return media::MockFFmpeg::get()->AVSeekFrame(format, stream_index, timestamp, | 179 return g_instance->AVSeekFrame(format, stream_index, timestamp, |
| 192 flags); | 180 flags); |
| 193 } | 181 } |
| 194 | 182 |
| 195 void av_init_packet(AVPacket* pkt) { | 183 void av_init_packet(AVPacket* pkt) { |
| 196 return media::MockFFmpeg::get()->AVInitPacket(pkt); | 184 return g_instance->AVInitPacket(pkt); |
| 197 } | 185 } |
| 198 | 186 |
| 199 int av_new_packet(AVPacket* packet, int size) { | 187 int av_new_packet(AVPacket* packet, int size) { |
| 200 return media::MockFFmpeg::get()->AVNewPacket(packet, size); | 188 return g_instance->AVNewPacket(packet, size); |
| 201 } | 189 } |
| 202 | 190 |
| 203 void av_free_packet(AVPacket* packet) { | 191 void av_free_packet(AVPacket* packet) { |
| 204 media::MockFFmpeg::get()->AVFreePacket(packet); | 192 g_instance->AVFreePacket(packet); |
| 205 } | 193 } |
| 206 | 194 |
| 207 void av_free(void* ptr) { | 195 void av_free(void* ptr) { |
| 208 // Freeing NULL pointers are valid, but they aren't interesting from a mock | 196 // Freeing NULL pointers are valid, but they aren't interesting from a mock |
| 209 // perspective. | 197 // perspective. |
| 210 if (ptr) { | 198 if (ptr) { |
| 211 media::MockFFmpeg::get()->AVFree(ptr); | 199 g_instance->AVFree(ptr); |
| 212 } | 200 } |
| 213 } | 201 } |
| 214 | 202 |
| 215 int av_dup_packet(AVPacket* packet) { | 203 int av_dup_packet(AVPacket* packet) { |
| 216 return media::MockFFmpeg::get()->AVDupPacket(packet); | 204 return g_instance->AVDupPacket(packet); |
| 217 } | 205 } |
| 218 | 206 |
| 219 void av_log_set_level(int level) { | 207 void av_log_set_level(int level) { |
| 220 media::MockFFmpeg::get()->AVLogSetLevel(level); | 208 g_instance->AVLogSetLevel(level); |
| 221 } | 209 } |
| 222 | 210 |
| 223 void av_destruct_packet(AVPacket *pkt) { | 211 void av_destruct_packet(AVPacket *pkt) { |
| 224 media::MockFFmpeg::get()->AVDestructPacket(pkt); | 212 g_instance->AVDestructPacket(pkt); |
| 225 } | 213 } |
| 226 | 214 |
| 227 } // extern "C" | 215 } // extern "C" |
| 228 | 216 |
| 229 } // namespace media | 217 } // namespace media |
| OLD | NEW |