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