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 "MediaDebug.h" 11 12/************************************************************* 13 * public BMediaDecoder 14 *************************************************************/ 15 16BMediaDecoder::BMediaDecoder() 17 : fDecoder(NULL), 18 fInitStatus(B_NO_INIT) 19{ 20} 21 22 23BMediaDecoder::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 33BMediaDecoder::BMediaDecoder(const media_codec_info *mci) 34 : fDecoder(NULL), 35 fInitStatus(B_NO_INIT) 36{ 37 SetTo(mci); 38} 39 40 41/* virtual */ 42BMediaDecoder::~BMediaDecoder() 43{ 44 gPluginManager.DestroyDecoder(fDecoder); 45} 46 47 48status_t 49BMediaDecoder::InitCheck() const 50{ 51 return fInitStatus; 52} 53 54 55status_t 56BMediaDecoder::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 78fail: 79 gPluginManager.DestroyDecoder(fDecoder); 80 fDecoder = NULL; 81 fInitStatus = B_NO_INIT; 82 return err; 83} 84 85 86status_t 87BMediaDecoder::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 103fail: 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 119status_t 120BMediaDecoder::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 138status_t 139BMediaDecoder::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 161status_t 162BMediaDecoder::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 174status_t 175BMediaDecoder::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 195BMediaDecoder::BMediaDecoder(const BMediaDecoder &); 196BMediaDecoder::BMediaDecoder & operator=(const BMediaDecoder &); 197*/ 198 199status_t 200BMediaDecoder::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 223status_t BMediaDecoder::_Reserved_BMediaDecoder_0(int32 arg, ...) { return B_ERROR; } 224status_t BMediaDecoder::_Reserved_BMediaDecoder_1(int32 arg, ...) { return B_ERROR; } 225status_t BMediaDecoder::_Reserved_BMediaDecoder_2(int32 arg, ...) { return B_ERROR; } 226status_t BMediaDecoder::_Reserved_BMediaDecoder_3(int32 arg, ...) { return B_ERROR; } 227status_t BMediaDecoder::_Reserved_BMediaDecoder_4(int32 arg, ...) { return B_ERROR; } 228status_t BMediaDecoder::_Reserved_BMediaDecoder_5(int32 arg, ...) { return B_ERROR; } 229status_t BMediaDecoder::_Reserved_BMediaDecoder_6(int32 arg, ...) { return B_ERROR; } 230status_t BMediaDecoder::_Reserved_BMediaDecoder_7(int32 arg, ...) { return B_ERROR; } 231status_t BMediaDecoder::_Reserved_BMediaDecoder_8(int32 arg, ...) { return B_ERROR; } 232status_t BMediaDecoder::_Reserved_BMediaDecoder_9(int32 arg, ...) { return B_ERROR; } 233status_t BMediaDecoder::_Reserved_BMediaDecoder_10(int32 arg, ...) { return B_ERROR; } 234status_t BMediaDecoder::_Reserved_BMediaDecoder_11(int32 arg, ...) { return B_ERROR; } 235status_t BMediaDecoder::_Reserved_BMediaDecoder_12(int32 arg, ...) { return B_ERROR; } 236status_t BMediaDecoder::_Reserved_BMediaDecoder_13(int32 arg, ...) { return B_ERROR; } 237status_t BMediaDecoder::_Reserved_BMediaDecoder_14(int32 arg, ...) { return B_ERROR; } 238status_t BMediaDecoder::_Reserved_BMediaDecoder_15(int32 arg, ...) { return B_ERROR; } 239 240/************************************************************* 241 * public BMediaBufferDecoder 242 *************************************************************/ 243 244BMediaBufferDecoder::BMediaBufferDecoder() 245 : BMediaDecoder() 246 , fBufferSize(0) 247{ 248} 249 250 251BMediaBufferDecoder::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 260BMediaBufferDecoder::BMediaBufferDecoder(const media_codec_info *mci) 261 : BMediaDecoder(mci) 262 , fBufferSize(0) 263{ 264} 265 266 267status_t 268BMediaBufferDecoder::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 */ 286status_t 287BMediaBufferDecoder::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