1 /*********************************************************************** 2 * AUTHOR: Andrew Bachmann, Marcus Overhagen 3 * FILE: MediaDecoder.cpp 4 * DESCR: 5 ***********************************************************************/ 6 #include <MediaDecoder.h> 7 #include <DecoderPlugin.h> 8 #include <new> 9 #include "PluginManager.h" 10 #include "debug.h" 11 12 /************************************************************* 13 * public BMediaDecoder 14 *************************************************************/ 15 16 BMediaDecoder::BMediaDecoder() 17 : fDecoder(NULL), 18 fInitStatus(B_NO_INIT) 19 { 20 } 21 22 23 BMediaDecoder::BMediaDecoder(const media_format *in_format, 24 const void *info, 25 size_t info_size) 26 : fDecoder(NULL), 27 fInitStatus(B_NO_INIT) 28 { 29 SetTo(in_format, info, info_size); 30 } 31 32 33 BMediaDecoder::BMediaDecoder(const media_codec_info *mci) 34 : fDecoder(NULL), 35 fInitStatus(B_NO_INIT) 36 { 37 SetTo(mci); 38 } 39 40 41 /* virtual */ 42 BMediaDecoder::~BMediaDecoder() 43 { 44 gPluginManager.DestroyDecoder(fDecoder); 45 } 46 47 48 status_t 49 BMediaDecoder::InitCheck() const 50 { 51 return fInitStatus; 52 } 53 54 55 status_t 56 BMediaDecoder::SetTo(const media_format *in_format, 57 const void *info, 58 size_t info_size) 59 { 60 gPluginManager.DestroyDecoder(fDecoder); 61 fDecoder = NULL; 62 63 status_t err = gPluginManager.CreateDecoder(&fDecoder, *in_format); 64 if (err < B_OK) 65 goto fail; 66 67 err = AttachToDecoder(); 68 if (err < B_OK) 69 goto fail; 70 71 err = SetInputFormat(in_format, info, info_size); 72 if (err < B_OK) 73 goto fail; 74 75 fInitStatus = B_OK; 76 return B_OK; 77 78 fail: 79 gPluginManager.DestroyDecoder(fDecoder); 80 fDecoder = NULL; 81 fInitStatus = B_NO_INIT; 82 return err; 83 } 84 85 86 status_t 87 BMediaDecoder::SetTo(const media_codec_info *mci) 88 { 89 gPluginManager.DestroyDecoder(fDecoder); 90 fDecoder = NULL; 91 92 status_t err = gPluginManager.CreateDecoder(&fDecoder, *mci); 93 if (err < B_OK) 94 goto fail; 95 96 err = AttachToDecoder(); 97 if (err < B_OK) 98 goto fail; 99 100 fInitStatus = B_OK; 101 return B_OK; 102 103 fail: 104 gPluginManager.DestroyDecoder(fDecoder); 105 fDecoder = NULL; 106 fInitStatus = B_NO_INIT; 107 return err; 108 } 109 110 111 /** SetInputFormat() sets the input data format to in_format. 112 * Unlike SetTo(), the SetInputFormat() function does not 113 * select a codec, so the currently-selected codec will 114 * continue to be used. You should only use SetInputFormat() 115 * to refine the format settings if it will not require the 116 * use of a different decoder. 117 */ 118 119 status_t 120 BMediaDecoder::SetInputFormat(const media_format *in_format, 121 const void *in_info, 122 size_t in_size) 123 { 124 if (!fDecoder) 125 return B_NO_INIT; 126 127 media_format format = *in_format; 128 return fDecoder->Setup(&format, in_info, in_size); 129 } 130 131 132 /** SetOutputFormat() sets the format the decoder should output. 133 * On return, the output_format is changed to match the actual 134 * format that will be output; this can be different if you 135 * specified any wildcards. 136 */ 137 138 status_t 139 BMediaDecoder::SetOutputFormat(media_format *output_format) 140 { 141 if (!fDecoder) 142 return B_NO_INIT; 143 144 return fDecoder->NegotiateOutputFormat(output_format); 145 } 146 147 148 /** Decodes a chunk of media data into the output buffer specified 149 * by out_buffer. On return, out_frameCount is set to indicate how 150 * many frames of data were decoded, and out_mh is the header for 151 * the decoded buffer. The media_decode_info structure info is used 152 * on input to specify decoding parameters. 153 * 154 * The amount of data decoded is part of the format determined by 155 * SetTo() or SetInputFormat(). For audio, it's the buffer_size. 156 * For video, it's one frame, which is height*row_bytes. The data 157 * to be decoded will be fetched from the source by the decoder 158 * add-on calling the derived class' GetNextChunk() function. 159 */ 160 161 status_t 162 BMediaDecoder::Decode(void *out_buffer, 163 int64 *out_frameCount, 164 media_header *out_mh, 165 media_decode_info *info) 166 { 167 if (!fDecoder) 168 return B_NO_INIT; 169 170 return fDecoder->Decode(out_buffer, out_frameCount, out_mh, info); 171 } 172 173 174 status_t 175 BMediaDecoder::GetDecoderInfo(media_codec_info *out_info) const 176 { 177 if (!fDecoder) 178 return B_NO_INIT; 179 180 return gPluginManager.GetDecoderInfo(fDecoder, out_info); 181 } 182 183 184 /************************************************************* 185 * protected BMediaDecoder 186 *************************************************************/ 187 188 189 /************************************************************* 190 * private BMediaDecoder 191 *************************************************************/ 192 193 /* 194 // unimplemented 195 BMediaDecoder::BMediaDecoder(const BMediaDecoder &); 196 BMediaDecoder::BMediaDecoder & operator=(const BMediaDecoder &); 197 */ 198 199 status_t 200 BMediaDecoder::AttachToDecoder() 201 { 202 class MediaDecoderChunkProvider : public ChunkProvider { 203 private: 204 BMediaDecoder * fDecoder; 205 public: 206 MediaDecoderChunkProvider(BMediaDecoder * decoder) { 207 fDecoder = decoder; 208 } 209 virtual status_t GetNextChunk(const void **chunkBuffer, size_t *chunkSize, 210 media_header *mediaHeader) { 211 return fDecoder->GetNextChunk(chunkBuffer, chunkSize, mediaHeader); 212 } 213 } * provider = new(std::nothrow) MediaDecoderChunkProvider(this); 214 215 if (!provider) 216 return B_NO_MEMORY; 217 218 fDecoder->SetChunkProvider(provider); 219 return B_OK; 220 } 221 222 223 status_t BMediaDecoder::_Reserved_BMediaDecoder_0(int32 arg, ...) { return B_ERROR; } 224 status_t BMediaDecoder::_Reserved_BMediaDecoder_1(int32 arg, ...) { return B_ERROR; } 225 status_t BMediaDecoder::_Reserved_BMediaDecoder_2(int32 arg, ...) { return B_ERROR; } 226 status_t BMediaDecoder::_Reserved_BMediaDecoder_3(int32 arg, ...) { return B_ERROR; } 227 status_t BMediaDecoder::_Reserved_BMediaDecoder_4(int32 arg, ...) { return B_ERROR; } 228 status_t BMediaDecoder::_Reserved_BMediaDecoder_5(int32 arg, ...) { return B_ERROR; } 229 status_t BMediaDecoder::_Reserved_BMediaDecoder_6(int32 arg, ...) { return B_ERROR; } 230 status_t BMediaDecoder::_Reserved_BMediaDecoder_7(int32 arg, ...) { return B_ERROR; } 231 status_t BMediaDecoder::_Reserved_BMediaDecoder_8(int32 arg, ...) { return B_ERROR; } 232 status_t BMediaDecoder::_Reserved_BMediaDecoder_9(int32 arg, ...) { return B_ERROR; } 233 status_t BMediaDecoder::_Reserved_BMediaDecoder_10(int32 arg, ...) { return B_ERROR; } 234 status_t BMediaDecoder::_Reserved_BMediaDecoder_11(int32 arg, ...) { return B_ERROR; } 235 status_t BMediaDecoder::_Reserved_BMediaDecoder_12(int32 arg, ...) { return B_ERROR; } 236 status_t BMediaDecoder::_Reserved_BMediaDecoder_13(int32 arg, ...) { return B_ERROR; } 237 status_t BMediaDecoder::_Reserved_BMediaDecoder_14(int32 arg, ...) { return B_ERROR; } 238 status_t BMediaDecoder::_Reserved_BMediaDecoder_15(int32 arg, ...) { return B_ERROR; } 239 240 /************************************************************* 241 * public BMediaBufferDecoder 242 *************************************************************/ 243 244 BMediaBufferDecoder::BMediaBufferDecoder() 245 : BMediaDecoder() 246 , fBufferSize(0) 247 { 248 } 249 250 251 BMediaBufferDecoder::BMediaBufferDecoder(const media_format *in_format, 252 const void *info, 253 size_t info_size) 254 : BMediaDecoder(in_format, info, info_size) 255 , fBufferSize(0) 256 { 257 } 258 259 260 BMediaBufferDecoder::BMediaBufferDecoder(const media_codec_info *mci) 261 : BMediaDecoder(mci) 262 , fBufferSize(0) 263 { 264 } 265 266 267 status_t 268 BMediaBufferDecoder::DecodeBuffer(const void *input_buffer, 269 size_t input_size, 270 void *out_buffer, 271 int64 *out_frameCount, 272 media_header *out_mh, 273 media_decode_info *info) 274 { 275 fBuffer = input_buffer; 276 fBufferSize = input_size; 277 return Decode(out_buffer, out_frameCount, out_mh,info); 278 } 279 280 281 /************************************************************* 282 * protected BMediaBufferDecoder 283 *************************************************************/ 284 285 /* virtual */ 286 status_t 287 BMediaBufferDecoder::GetNextChunk(const void **chunkData, 288 size_t *chunkLen, 289 media_header *mh) 290 { 291 if (!fBufferSize) 292 return B_LAST_BUFFER_ERROR; 293 294 *chunkData = fBuffer; 295 *chunkLen = fBufferSize; 296 fBufferSize = 0; 297 return B_OK; 298 } 299