1 /*
2  * Copyright (C) 2020 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 #ifndef IMEDIASOURCEFUZZIMPL_H
18 #define IMEDIASOURCEFUZZIMPL_H
19 
20 #include <media/stagefright/MediaSource.h>
21 
22 #define MAX_FRAMES 5
23 
24 namespace android {
25 
26 class IMediaSourceFuzzImpl : public IMediaSource {
27  public:
IMediaSourceFuzzImpl(FuzzedDataProvider * _fdp,size_t _max_buffer_size)28    IMediaSourceFuzzImpl(FuzzedDataProvider* _fdp, size_t _max_buffer_size)
29        : frames_read(0), fdp(_fdp), min_buffer_size(32 * 32), max_buffer_size(_max_buffer_size) {}
start(MetaData *)30    status_t start(MetaData*) override { return 0; }
stop()31    status_t stop() override { return 0; }
getFormat()32    sp<MetaData> getFormat() override { return nullptr; }
33    status_t read(MediaBufferBase**, const MediaSource::ReadOptions*) override;
34    status_t readMultiple(Vector<MediaBufferBase*>*, uint32_t,
35                          const MediaSource::ReadOptions*) override;
supportReadMultiple()36    bool supportReadMultiple() override { return true; }
supportNonblockingRead()37    bool supportNonblockingRead() override { return true; }
pause()38    status_t pause() override { return 0; }
39 
40  protected:
onAsBinder()41     IBinder* onAsBinder() { return nullptr; }
42 
43  private:
44    uint8_t frames_read;
45    FuzzedDataProvider* fdp;
46    const size_t min_buffer_size;
47    const size_t max_buffer_size;
48    std::vector<uint8_t> buf;
49 };
50 
51 // This class is simply to expose the destructor
52 class MediaBufferFuzzImpl : public MediaBuffer {
53  public:
MediaBufferFuzzImpl(void * data,size_t size)54     MediaBufferFuzzImpl(void *data, size_t size) : MediaBuffer(data, size) {}
~MediaBufferFuzzImpl()55     ~MediaBufferFuzzImpl() {}
56 };
57 
read(MediaBufferBase ** buffer,const MediaSource::ReadOptions *)58 status_t IMediaSourceFuzzImpl::read(MediaBufferBase** buffer, const MediaSource::ReadOptions*) {
59     Vector<MediaBufferBase*> buffers;
60     status_t ret = readMultiple(&buffers, 1, nullptr);
61     *buffer = buffers.empty() ? nullptr : buffers[0];
62 
63     return ret;
64 }
65 
readMultiple(Vector<MediaBufferBase * > * buffers,uint32_t,const MediaSource::ReadOptions *)66 status_t IMediaSourceFuzzImpl::readMultiple(Vector<MediaBufferBase*>* buffers, uint32_t,
67                                             const MediaSource::ReadOptions*) {
68     if (++frames_read == MAX_FRAMES) {
69         auto size = fdp->ConsumeIntegralInRange<size_t>(min_buffer_size, max_buffer_size);
70         buf = fdp->ConsumeBytes<uint8_t>(size);
71         if (buf.size() < size) {
72             buf.resize(size, 0);
73         }
74 
75         MediaBufferBase* mbb = new MediaBufferFuzzImpl(buf.data(), buf.size());
76         mbb->meta_data().setInt64(kKeyTime, fdp->ConsumeIntegral<uint64_t>());
77         buffers->push_back(mbb);
78 
79         return ERROR_END_OF_STREAM;
80     }
81 
82     auto size = fdp->ConsumeIntegralInRange<size_t>(min_buffer_size, max_buffer_size);
83     buf = fdp->ConsumeBytes<uint8_t>(size);
84     if (buf.size() < size) {
85         buf.resize(size, 0);
86     }
87 
88     MediaBufferBase* mbb = new MediaBufferFuzzImpl(buf.data(), buf.size());
89     mbb->meta_data().setInt64(kKeyTime, fdp->ConsumeIntegral<uint64_t>());
90     buffers->push_back(mbb);
91 
92     return OK;
93 }
94 
95 } // namespace android
96 
97 #endif // IMEDIASOURCEFUZZIMPL_H
98 
99