1 /****************************************************************************** 2 * 3 * Copyright (C) 2020 The Android Open Source Project 4 * 5 * Licensed under the Apache License, Version 2.0 (the "License"); 6 * you may not use this file except in compliance with the License. 7 * You may obtain a copy of the License at: 8 * 9 * http://www.apache.org/licenses/LICENSE-2.0 10 * 11 * Unless required by applicable law or agreed to in writing, software 12 * distributed under the License is distributed on an "AS IS" BASIS, 13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 * See the License for the specific language governing permissions and 15 * limitations under the License. 16 * 17 ***************************************************************************** 18 * Originally developed and contributed by Ittiam Systems Pvt. Ltd, Bangalore 19 */ 20 21 #ifndef __WRITER_FUZZER_BASE_H__ 22 #define __WRITER_FUZZER_BASE_H__ 23 24 #include <media/stagefright/MediaAdapter.h> 25 #include <media/stagefright/MediaWriter.h> 26 #include <media/stagefright/MetaData.h> 27 #include <media/stagefright/Utils.h> 28 #include <media/stagefright/foundation/ABuffer.h> 29 #include <media/stagefright/foundation/AMessage.h> 30 #include <algorithm> 31 #include <cstring> 32 #include <vector> 33 34 using namespace std; 35 36 constexpr uint32_t kMimeSize = 128; 37 constexpr uint8_t kMaxTrackCount = 3; 38 constexpr uint32_t kMaxCSDStrlen = 16; 39 constexpr uint32_t kCodecConfigFlag = 32; 40 41 namespace android { 42 43 struct ConfigFormat { 44 char* mime; 45 int32_t width; 46 int32_t height; 47 int32_t sampleRate; 48 int32_t channelCount; 49 }; 50 51 struct FrameData { 52 size_t size; 53 uint8_t flags; 54 int64_t timeUs; 55 const uint8_t* buf; 56 }; 57 58 static string supportedMimeTypes[] = {"audio/3gpp", 59 "audio/amr-wb", 60 "audio/vorbis", 61 "audio/opus", 62 "audio/mp4a-latm", 63 "audio/mpeg", 64 "audio/mpeg-L1", 65 "audio/mpeg-L2", 66 "audio/midi", 67 "audio/qcelp", 68 "audio/g711-alaw", 69 "audio/g711-mlaw", 70 "audio/flac", 71 "audio/aac-adts", 72 "audio/gsm", 73 "audio/ac3", 74 "audio/eac3", 75 "audio/eac3-joc", 76 "audio/ac4", 77 "audio/scrambled", 78 "audio/alac", 79 "audio/x-ms-wma", 80 "audio/x-adpcm-ms", 81 "audio/x-adpcm-dvi-ima", 82 "video/avc", 83 "video/hevc", 84 "video/mp4v-es", 85 "video/3gpp", 86 "video/x-vnd.on2.vp8", 87 "video/x-vnd.on2.vp9", 88 "video/av01", 89 "video/mpeg2", 90 "video/dolby-vision", 91 "video/scrambled", 92 "video/divx", 93 "video/divx3", 94 "video/xvid", 95 "video/x-motion-jpeg", 96 "text/3gpp-tt", 97 "application/x-subrip", 98 "text/vtt", 99 "text/cea-608", 100 "text/cea-708", 101 "application/x-id3v4"}; 102 103 enum SampleFlag { 104 DEFAULT_FLAG = 0, 105 SYNC_FLAG = 1, 106 ENCRYPTED_FLAG = 2, 107 }; 108 109 static uint8_t flagTypes[] = {SampleFlag::DEFAULT_FLAG, SampleFlag::SYNC_FLAG, 110 SampleFlag::ENCRYPTED_FLAG}; 111 112 class WriterFuzzerBase { 113 public: 114 WriterFuzzerBase() = default; ~WriterFuzzerBase()115 virtual ~WriterFuzzerBase() { 116 if (mFileMeta) { 117 mFileMeta.clear(); 118 mFileMeta = nullptr; 119 } 120 if (mWriter) { 121 mWriter.clear(); 122 mWriter = nullptr; 123 } 124 for (int32_t idx = 0; idx < kMaxTrackCount; ++idx) { 125 if (mCurrentTrack[idx]) { 126 mCurrentTrack[idx]->stop(); 127 mCurrentTrack[idx].clear(); 128 mCurrentTrack[idx] = nullptr; 129 } 130 } 131 close(mFd); 132 }; 133 134 /** Function to create the media writer component. 135 * To be implemented by the derived class. 136 */ 137 virtual bool createWriter() = 0; 138 139 /** Parent class functions to be reused by derived class. 140 * These are common for all media writer components. 141 */ 142 bool createOutputFile(); 143 144 void addWriterSource(int32_t trackIndex); 145 146 void start(); 147 148 void sendBuffersToWriter(sp<MediaAdapter>& currentTrack, int32_t trackIndex, 149 int32_t startFrameIndex, int32_t endFrameIndex); 150 151 void sendBuffersInterleave(int32_t numTracks, uint8_t numBuffersInterleave); 152 153 void initFileWriterAndProcessData(const uint8_t* data, size_t size); 154 155 protected: 156 class BufferSource { 157 public: BufferSource(const uint8_t * data,size_t size)158 BufferSource(const uint8_t* data, size_t size) : mData(data), mSize(size), mReadIndex(0) {} ~BufferSource()159 ~BufferSource() { 160 mData = nullptr; 161 mSize = 0; 162 mReadIndex = 0; 163 for (int32_t idx = 0; idx < kMaxTrackCount; ++idx) { 164 mFrameList[idx].clear(); 165 } 166 } 167 uint32_t getNumTracks(); 168 bool getTrackInfo(int32_t trackIndex); 169 void getFrameInfo(); 170 ConfigFormat getConfigFormat(int32_t trackIndex); 171 int32_t getNumCsds(int32_t trackIndex); 172 vector<FrameData>& getFrameList(int32_t trackIndex); 173 174 private: isMarker()175 bool isMarker() { return (memcmp(&mData[mReadIndex], kMarker, kMarkerSize) == 0); } 176 isCSDMarker(size_t position)177 bool isCSDMarker(size_t position) { 178 return (memcmp(&mData[position], kCsdMarkerSuffix, kMarkerSuffixSize) == 0); 179 } 180 181 bool searchForMarker(size_t startIndex); 182 183 const uint8_t* mData = nullptr; 184 size_t mSize = 0; 185 size_t mReadIndex = 0; 186 ConfigFormat mParams[kMaxTrackCount] = {}; 187 int32_t mNumCsds[kMaxTrackCount] = {0}; 188 vector<FrameData> mFrameList[kMaxTrackCount]; 189 190 static constexpr int kSupportedMimeTypes = size(supportedMimeTypes); 191 static constexpr uint8_t kMarker[] = "_MARK"; 192 static constexpr uint8_t kCsdMarkerSuffix[] = "_H_"; 193 static constexpr uint8_t kFrameMarkerSuffix[] = "_F_"; 194 // All markers should be 5 bytes long ( sizeof '_MARK' which is 5) 195 static constexpr size_t kMarkerSize = (sizeof(kMarker) - 1); 196 // All marker types should be 3 bytes long ('_H_', '_F_') 197 static constexpr size_t kMarkerSuffixSize = 3; 198 }; 199 200 BufferSource* mBufferSource = nullptr; 201 int32_t mFd = -1; 202 uint32_t mNumTracks = 0; 203 string mOutputFileName = "writer.out"; 204 sp<MediaWriter> mWriter = nullptr; 205 sp<MetaData> mFileMeta = nullptr; 206 sp<MediaAdapter> mCurrentTrack[kMaxTrackCount] = {}; 207 }; 208 209 } // namespace android 210 211 #endif // __WRITER_FUZZER_BASE_H__ 212