1 /*********************************************************************** 2 * AUTHOR: Andrew Bachmann, Marcus Overhagen 3 * FILE: MediaDecoder.cpp 4 * DESCR: 5 ***********************************************************************/ 6 #include <MediaDecoder.h> 7 #include <DecoderPlugin.h> 8 #include "PluginManager.h" 9 #include "DataExchange.h" 10 #include "debug.h" 11 12 extern PluginManager _plugin_manager; 13 14 /************************************************************* 15 * public BMediaDecoder 16 *************************************************************/ 17 18 BMediaDecoder::BMediaDecoder() 19 : fDecoder(NULL), 20 fDecoderID(0), 21 fDecoderPlugin(NULL), 22 fDecoderPluginID(0), 23 fInitStatus(B_NO_INIT), 24 fNeedsInit(false), 25 fInitFormat(NULL), 26 fInitInfo(NULL), 27 fInitInfoSize(0) 28 { 29 } 30 31 32 BMediaDecoder::BMediaDecoder(const media_format *in_format, 33 const void *info, 34 size_t info_size) 35 : fDecoder(NULL), 36 fDecoderID(0), 37 fDecoderPlugin(NULL), 38 fDecoderPluginID(0), 39 fInitStatus(B_NO_INIT), 40 fNeedsInit(true), 41 fInitFormat(new media_format(*in_format)), 42 fInitInfo(NULL), 43 fInitInfoSize(0) 44 { 45 if (info_size) { 46 fInitInfoSize = info_size; 47 fInitInfo = new char[info_size]; 48 memcpy(fInitInfo, info, info_size); 49 } 50 } 51 52 53 BMediaDecoder::BMediaDecoder(const media_codec_info *mci) 54 : fDecoder(NULL), 55 fDecoderID(0), 56 fDecoderPlugin(NULL), 57 fDecoderPluginID(0), 58 fInitStatus(B_NO_INIT), 59 fNeedsInit(false), 60 fInitFormat(NULL), 61 fInitInfo(NULL), 62 fInitInfoSize(0) 63 { 64 SetTo(mci); 65 } 66 67 68 /* virtual */ 69 BMediaDecoder::~BMediaDecoder() 70 { 71 delete fDecoder; 72 delete fInitFormat; 73 delete fInitInfo; 74 } 75 76 77 status_t 78 BMediaDecoder::InitCheck() const 79 { 80 if (fNeedsInit) { 81 // casting away const: yes this solution does suck 82 // it is necessary while decoders need to call GetNextChunk in Setup 83 const_cast<BMediaDecoder*>(this)->SetTo(fInitFormat, fInitInfo, fInitInfoSize); 84 } 85 return fInitStatus; 86 } 87 88 89 static DecoderPlugin * 90 GetDecoderPlugin(const media_format * format) 91 { 92 server_get_decoder_for_format_request request; 93 server_get_decoder_for_format_reply reply; 94 request.format = *format; 95 status_t result = QueryServer(SERVER_GET_DECODER_FOR_FORMAT, &request, sizeof(request), &reply, sizeof(reply)); 96 if (result != B_OK) { 97 printf("BMediaDecoder::SetTo: can't get decoder for format\n"); 98 return NULL; 99 } 100 MediaPlugin * media_plugin = _plugin_manager.GetPlugin(reply.ref); 101 if (!media_plugin) { 102 printf("BMediaDecoder::SetTo: GetPlugin failed\n"); 103 return NULL; 104 } 105 DecoderPlugin * plugin = dynamic_cast<DecoderPlugin *>(media_plugin); 106 if (!plugin) { 107 printf("BMediaDecoder::SetTo: dynamic_cast failed\n"); 108 return NULL; 109 } 110 return plugin; 111 } 112 113 // ask the server for a good decoder for the arguments 114 // GETS THE CODEC for in_format->type + in_format->u.x.encoding 115 status_t 116 BMediaDecoder::SetTo(const media_format *in_format, 117 const void *info, 118 size_t info_size) 119 { 120 fNeedsInit = false; 121 fInitStatus = B_NO_INIT; 122 delete fDecoder; 123 DecoderPlugin * plugin = GetDecoderPlugin(in_format); 124 if (plugin == NULL) { 125 return fInitStatus = B_ERROR; 126 } 127 Decoder * decoder = plugin->NewDecoder(0); 128 if (decoder == NULL) { 129 return fInitStatus = B_ERROR; 130 } 131 fDecoder = decoder; 132 // fDecoderID = mci->sub_id; 133 if ((fInitStatus = AttachToDecoder()) != B_OK) { 134 return fInitStatus; 135 } 136 fInitStatus = SetInputFormat(in_format,info,info_size); 137 return fInitStatus; 138 } 139 140 // ask the server for the id'th plugin 141 static DecoderPlugin * 142 GetDecoderPlugin(int32 id) 143 { 144 if (id == 0) { 145 return NULL; 146 } 147 UNIMPLEMENTED(); 148 return NULL; 149 } 150 151 // ask the server for a good decoder for the arguments 152 // GETS THE CODEC for mci->id, mci->sub_id 153 // fails if the mci->id = 0 154 status_t 155 BMediaDecoder::SetTo(const media_codec_info *mci) 156 { 157 fInitStatus = B_NO_INIT; 158 delete fDecoder; 159 DecoderPlugin * plugin = GetDecoderPlugin(mci->id); 160 if (plugin == NULL) { 161 return fInitStatus = B_ERROR; 162 } 163 Decoder * decoder = plugin->NewDecoder(0); 164 if (decoder == NULL) { 165 return fInitStatus = B_ERROR; 166 } 167 fDecoder = decoder; 168 fDecoderID = mci->sub_id; 169 if ((fInitStatus = AttachToDecoder()) != B_OK) { 170 return fInitStatus; 171 } 172 return fInitStatus; 173 } 174 175 176 /** SetInputFormat() sets the input data format to in_format. 177 * Unlike SetTo(), the SetInputFormat() function does not 178 * select a codec, so the currently-selected codec will 179 * continue to be used. You should only use SetInputFormat() 180 * to refine the format settings if it will not require the 181 * use of a different decoder. 182 */ 183 184 status_t 185 BMediaDecoder::SetInputFormat(const media_format *in_format, 186 const void *in_info, 187 size_t in_size) 188 { 189 if (InitCheck() != B_OK) { 190 return fInitStatus; 191 } 192 printf("DISCARDING FORMAT %s\n",__PRETTY_FUNCTION__); 193 media_format format = *in_format; 194 return fDecoder->Setup(&format,in_info,in_size); 195 } 196 197 198 /** SetOutputFormat() sets the format the decoder should output. 199 * On return, the output_format is changed to match the actual 200 * format that will be output; this can be different if you 201 * specified any wildcards. 202 */ 203 204 status_t 205 BMediaDecoder::SetOutputFormat(media_format *output_format) 206 { 207 if (InitCheck() != B_OK) { 208 return fInitStatus; 209 } 210 return fDecoder->NegotiateOutputFormat(output_format); 211 } 212 213 214 /** Decodes a chunk of media data into the output buffer specified 215 * by out_buffer. On return, out_frameCount is set to indicate how 216 * many frames of data were decoded, and out_mh is the header for 217 * the decoded buffer. The media_decode_info structure info is used 218 * on input to specify decoding parameters. 219 * 220 * The amount of data decoded is part of the format determined by 221 * SetTo() or SetInputFormat(). For audio, it's the buffer_size. 222 * For video, it's one frame, which is height*row_bytes. The data 223 * to be decoded will be fetched from the source by the decoder 224 * add-on calling the derived class' GetNextChunk() function. 225 */ 226 227 status_t 228 BMediaDecoder::Decode(void *out_buffer, 229 int64 *out_frameCount, 230 media_header *out_mh, 231 media_decode_info *info) 232 { 233 if (InitCheck() != B_OK) { 234 return fInitStatus; 235 } 236 return fDecoder->Decode(out_buffer,out_frameCount,out_mh,info); 237 } 238 239 240 status_t 241 BMediaDecoder::GetDecoderInfo(media_codec_info *out_info) const 242 { 243 if (InitCheck() != B_OK) { 244 return fInitStatus; 245 } 246 fDecoder->GetCodecInfo(out_info); 247 out_info->id = fDecoderPluginID; 248 out_info->sub_id = fDecoderID; 249 return B_OK; 250 } 251 252 253 /************************************************************* 254 * protected BMediaDecoder 255 *************************************************************/ 256 257 258 /************************************************************* 259 * private BMediaDecoder 260 *************************************************************/ 261 262 /* 263 // unimplemented 264 BMediaDecoder::BMediaDecoder(const BMediaDecoder &); 265 BMediaDecoder::BMediaDecoder & operator=(const BMediaDecoder &); 266 */ 267 268 status_t 269 BMediaDecoder::AttachToDecoder() 270 { 271 class MediaDecoderChunkProvider : public ChunkProvider { 272 private: 273 BMediaDecoder * fDecoder; 274 public: 275 MediaDecoderChunkProvider(BMediaDecoder * decoder) { 276 fDecoder = decoder; 277 } 278 virtual status_t GetNextChunk(void **chunkBuffer, int32 *chunkSize, 279 media_header *mediaHeader) { 280 const void ** buffer = const_cast<const void**>(chunkBuffer); 281 size_t * size = reinterpret_cast<size_t*>(chunkSize); 282 return fDecoder->GetNextChunk(buffer,size,mediaHeader); 283 } 284 } * provider = new MediaDecoderChunkProvider(this); 285 if (provider == NULL) { 286 return B_NO_MEMORY; 287 } 288 fDecoder->Setup(provider); 289 return B_OK; 290 } 291 292 293 status_t BMediaDecoder::_Reserved_BMediaDecoder_0(int32 arg, ...) { return B_ERROR; } 294 status_t BMediaDecoder::_Reserved_BMediaDecoder_1(int32 arg, ...) { return B_ERROR; } 295 status_t BMediaDecoder::_Reserved_BMediaDecoder_2(int32 arg, ...) { return B_ERROR; } 296 status_t BMediaDecoder::_Reserved_BMediaDecoder_3(int32 arg, ...) { return B_ERROR; } 297 status_t BMediaDecoder::_Reserved_BMediaDecoder_4(int32 arg, ...) { return B_ERROR; } 298 status_t BMediaDecoder::_Reserved_BMediaDecoder_5(int32 arg, ...) { return B_ERROR; } 299 status_t BMediaDecoder::_Reserved_BMediaDecoder_6(int32 arg, ...) { return B_ERROR; } 300 status_t BMediaDecoder::_Reserved_BMediaDecoder_7(int32 arg, ...) { return B_ERROR; } 301 status_t BMediaDecoder::_Reserved_BMediaDecoder_8(int32 arg, ...) { return B_ERROR; } 302 status_t BMediaDecoder::_Reserved_BMediaDecoder_9(int32 arg, ...) { return B_ERROR; } 303 status_t BMediaDecoder::_Reserved_BMediaDecoder_10(int32 arg, ...) { return B_ERROR; } 304 status_t BMediaDecoder::_Reserved_BMediaDecoder_11(int32 arg, ...) { return B_ERROR; } 305 status_t BMediaDecoder::_Reserved_BMediaDecoder_12(int32 arg, ...) { return B_ERROR; } 306 status_t BMediaDecoder::_Reserved_BMediaDecoder_13(int32 arg, ...) { return B_ERROR; } 307 status_t BMediaDecoder::_Reserved_BMediaDecoder_14(int32 arg, ...) { return B_ERROR; } 308 status_t BMediaDecoder::_Reserved_BMediaDecoder_15(int32 arg, ...) { return B_ERROR; } 309 310 /************************************************************* 311 * public BMediaBufferDecoder 312 *************************************************************/ 313 314 BMediaBufferDecoder::BMediaBufferDecoder() 315 : BMediaDecoder() 316 { 317 buffer_size = 0; 318 } 319 320 321 BMediaBufferDecoder::BMediaBufferDecoder(const media_format *in_format, 322 const void *info, 323 size_t info_size) 324 : BMediaDecoder(in_format,info,info_size) 325 { 326 buffer_size = 0; 327 } 328 329 330 BMediaBufferDecoder::BMediaBufferDecoder(const media_codec_info *mci) 331 : BMediaDecoder(mci) 332 { 333 buffer_size = 0; 334 } 335 336 337 status_t 338 BMediaBufferDecoder::DecodeBuffer(const void *input_buffer, 339 size_t input_size, 340 void *out_buffer, 341 int64 *out_frameCount, 342 media_header *out_mh, 343 media_decode_info *info) 344 { 345 buffer = input_buffer; 346 buffer_size = input_size; 347 return Decode(out_buffer,out_frameCount,out_mh,info); 348 } 349 350 351 /************************************************************* 352 * protected BMediaBufferDecoder 353 *************************************************************/ 354 355 /* virtual */ 356 status_t 357 BMediaBufferDecoder::GetNextChunk(const void **chunkData, size_t *chunkLen, 358 media_header *mh) 359 { 360 if (!buffer_size) { 361 return B_LAST_BUFFER_ERROR; 362 } 363 *chunkData = buffer; 364 *chunkLen = buffer_size; 365 buffer_size = 0; 366 return B_OK; 367 } 368