| 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 |