1 /* 2 * Copyright 2015, Dario Casalinuovo 3 * Copyright 2010, Oleg Krysenkov, beos344@mail.ru. 4 * Copyright 2012, Fredrik Modéen, [firstname]@[lastname].se. 5 * Copyright 2004-2007, Marcus Overhagen. All rights reserved. 6 * Distributed under the terms of the MIT License. 7 */ 8 9 10 #include <MediaEncoder.h> 11 12 #include <CodecRoster.h> 13 #include <Encoder.h> 14 15 #include <new> 16 17 #include "MediaDebug.h" 18 19 using namespace BCodecKit; 20 21 22 /************************************************************* 23 * public BMediaEncoder 24 *************************************************************/ 25 26 BMediaEncoder::BMediaEncoder() 27 : 28 fEncoder(NULL), 29 fInitStatus(B_NO_INIT) 30 { 31 CALLED(); 32 } 33 34 35 BMediaEncoder::BMediaEncoder(const media_format* outputFormat) 36 : 37 fEncoder(NULL), 38 fInitStatus(B_NO_INIT) 39 { 40 CALLED(); 41 SetTo(outputFormat); 42 } 43 44 45 BMediaEncoder::BMediaEncoder(const media_codec_info* mci) 46 : 47 fEncoder(NULL), 48 fInitStatus(B_NO_INIT) 49 { 50 CALLED(); 51 SetTo(mci); 52 } 53 54 55 /* virtual */ 56 BMediaEncoder::~BMediaEncoder() 57 { 58 CALLED(); 59 ReleaseEncoder(); 60 } 61 62 63 status_t 64 BMediaEncoder::InitCheck() const 65 { 66 return fInitStatus; 67 } 68 69 70 status_t 71 BMediaEncoder::SetTo(const media_format* outputFormat) 72 { 73 CALLED(); 74 75 status_t err = B_ERROR; 76 ReleaseEncoder(); 77 78 if (outputFormat == NULL) 79 return fInitStatus; 80 81 media_format format = *outputFormat; 82 err = BCodecRoster::InstantiateEncoder(&fEncoder, format); 83 if (fEncoder != NULL && err == B_OK) { 84 err = _AttachToEncoder(); 85 if (err == B_OK) 86 return err; 87 } 88 ReleaseEncoder(); 89 fInitStatus = err; 90 return err; 91 } 92 93 94 status_t 95 BMediaEncoder::SetTo(const media_codec_info* mci) 96 { 97 CALLED(); 98 99 ReleaseEncoder(); 100 status_t err = BCodecRoster::InstantiateEncoder(&fEncoder, mci, 0); 101 if (fEncoder != NULL && err == B_OK) { 102 err = _AttachToEncoder(); 103 if (err == B_OK) { 104 fInitStatus = B_OK; 105 return B_OK; 106 } 107 } 108 109 ReleaseEncoder(); 110 fInitStatus = err; 111 return err; 112 } 113 114 115 status_t 116 BMediaEncoder::SetFormat(media_format* inputFormat, 117 media_format* outputFormat, media_file_format* mfi) 118 { 119 CALLED(); 120 TRACE("BMediaEncoder::SetFormat. Input = %d, Output = %d\n", 121 inputFormat->type, outputFormat->type); 122 123 if (!fEncoder) 124 return B_NO_INIT; 125 126 if (outputFormat != NULL) 127 SetTo(outputFormat); 128 129 //TODO: How we support mfi? 130 return fEncoder->SetUp(inputFormat); 131 } 132 133 134 status_t 135 BMediaEncoder::Encode(const void* buffer, 136 int64 frameCount, media_encode_info* info) 137 { 138 CALLED(); 139 140 if (!fEncoder) 141 return B_NO_INIT; 142 143 return fEncoder->Encode(buffer, frameCount, info); 144 } 145 146 147 status_t 148 BMediaEncoder::GetEncodeParameters(encode_parameters* parameters) const 149 { 150 CALLED(); 151 152 if (fEncoder == NULL) 153 return B_NO_INIT; 154 155 return fEncoder->GetEncodeParameters(parameters); 156 } 157 158 159 status_t 160 BMediaEncoder::SetEncodeParameters(encode_parameters* parameters) 161 { 162 CALLED(); 163 164 if (fEncoder == NULL) 165 return B_NO_INIT; 166 167 return fEncoder->SetEncodeParameters(parameters); 168 } 169 170 171 /************************************************************* 172 * protected BMediaEncoder 173 *************************************************************/ 174 175 /* virtual */ status_t 176 BMediaEncoder::AddTrackInfo(uint32 code, const char* data, size_t size) 177 { 178 CALLED(); 179 180 if (fEncoder == NULL) 181 return B_NO_INIT; 182 183 return fEncoder->AddTrackInfo(code, data, size); 184 } 185 186 187 /************************************************************* 188 * private BMediaEncoder 189 *************************************************************/ 190 191 /* 192 // unimplemented 193 BMediaEncoder::BMediaEncoder(const BMediaEncoder &); 194 BMediaEncoder::BMediaEncoder & operator=(const BMediaEncoder &); 195 */ 196 197 /* static */ status_t 198 BMediaEncoder::write_chunk(void* classptr, const void* chunk_data, 199 size_t chunk_len, media_encode_info* info) 200 { 201 CALLED(); 202 203 BMediaEncoder* encoder = static_cast<BMediaEncoder*>(classptr); 204 if (encoder == NULL) 205 return B_BAD_VALUE; 206 return encoder->WriteChunk(chunk_data, chunk_len, info); 207 } 208 209 210 void 211 BMediaEncoder::Init() 212 { 213 UNIMPLEMENTED(); 214 } 215 216 217 void 218 BMediaEncoder::ReleaseEncoder() 219 { 220 CALLED(); 221 if (fEncoder != NULL) { 222 BCodecRoster::ReleaseEncoder(fEncoder); 223 fEncoder = NULL; 224 } 225 fInitStatus = B_NO_INIT; 226 } 227 228 229 status_t 230 BMediaEncoder::_AttachToEncoder() 231 { 232 class MediaEncoderChunkWriter : public BChunkWriter { 233 public: 234 MediaEncoderChunkWriter(BMediaEncoder* encoder) 235 { 236 fEncoder = encoder; 237 } 238 virtual status_t WriteChunk(const void* chunkBuffer, 239 size_t chunkSize, media_encode_info* encodeInfo) 240 { 241 return fEncoder->WriteChunk(chunkBuffer, chunkSize, encodeInfo); 242 } 243 private: 244 BMediaEncoder* fEncoder; 245 } *writer = new(std::nothrow) MediaEncoderChunkWriter(this); 246 247 if (!writer) 248 return B_NO_MEMORY; 249 250 fEncoder->SetChunkWriter(writer); 251 return B_OK; 252 } 253 254 255 status_t BMediaEncoder::_Reserved_BMediaEncoder_0(int32 arg, ...) { return B_ERROR; } 256 status_t BMediaEncoder::_Reserved_BMediaEncoder_1(int32 arg, ...) { return B_ERROR; } 257 status_t BMediaEncoder::_Reserved_BMediaEncoder_2(int32 arg, ...) { return B_ERROR; } 258 status_t BMediaEncoder::_Reserved_BMediaEncoder_3(int32 arg, ...) { return B_ERROR; } 259 status_t BMediaEncoder::_Reserved_BMediaEncoder_4(int32 arg, ...) { return B_ERROR; } 260 status_t BMediaEncoder::_Reserved_BMediaEncoder_5(int32 arg, ...) { return B_ERROR; } 261 status_t BMediaEncoder::_Reserved_BMediaEncoder_6(int32 arg, ...) { return B_ERROR; } 262 status_t BMediaEncoder::_Reserved_BMediaEncoder_7(int32 arg, ...) { return B_ERROR; } 263 status_t BMediaEncoder::_Reserved_BMediaEncoder_8(int32 arg, ...) { return B_ERROR; } 264 status_t BMediaEncoder::_Reserved_BMediaEncoder_9(int32 arg, ...) { return B_ERROR; } 265 status_t BMediaEncoder::_Reserved_BMediaEncoder_10(int32 arg, ...) { return B_ERROR; } 266 status_t BMediaEncoder::_Reserved_BMediaEncoder_11(int32 arg, ...) { return B_ERROR; } 267 status_t BMediaEncoder::_Reserved_BMediaEncoder_12(int32 arg, ...) { return B_ERROR; } 268 status_t BMediaEncoder::_Reserved_BMediaEncoder_13(int32 arg, ...) { return B_ERROR; } 269 status_t BMediaEncoder::_Reserved_BMediaEncoder_14(int32 arg, ...) { return B_ERROR; } 270 status_t BMediaEncoder::_Reserved_BMediaEncoder_15(int32 arg, ...) { return B_ERROR; } 271 272 /************************************************************* 273 * public BMediaBufferEncoder 274 *************************************************************/ 275 276 BMediaBufferEncoder::BMediaBufferEncoder() 277 : 278 BMediaEncoder(), 279 fBuffer(NULL) 280 { 281 CALLED(); 282 } 283 284 285 BMediaBufferEncoder::BMediaBufferEncoder(const media_format* outputFormat) 286 : 287 BMediaEncoder(outputFormat), 288 fBuffer(NULL) 289 { 290 CALLED(); 291 } 292 293 294 BMediaBufferEncoder::BMediaBufferEncoder(const media_codec_info* mci) 295 : 296 BMediaEncoder(mci), 297 fBuffer(NULL) 298 { 299 CALLED(); 300 } 301 302 303 status_t 304 BMediaBufferEncoder::EncodeToBuffer(void* outputBuffer, 305 size_t* outputSize, const void* inputBuffer, 306 int64 frameCount, media_encode_info* info) 307 { 308 CALLED(); 309 310 status_t error; 311 fBuffer = outputBuffer; 312 fBufferSize = *outputSize; 313 error = Encode(inputBuffer, frameCount, info); 314 if (fBuffer) { 315 fBuffer = NULL; 316 *outputSize = 0; 317 } else { 318 *outputSize = fBufferSize; 319 } 320 return error; 321 } 322 323 324 /************************************************************* 325 * public BMediaBufferEncoder 326 *************************************************************/ 327 328 status_t 329 BMediaBufferEncoder::WriteChunk(const void* chunkData, 330 size_t chunkLen, media_encode_info* info) 331 { 332 CALLED(); 333 334 if (fBuffer == NULL) 335 return B_ENTRY_NOT_FOUND; 336 337 if (chunkLen > (size_t)fBufferSize) { 338 memcpy(fBuffer, chunkData, fBufferSize); 339 fBuffer = NULL; 340 return B_DEVICE_FULL; 341 } 342 343 memcpy(fBuffer, chunkData, chunkLen); 344 fBufferSize = chunkLen; 345 fBuffer = NULL; 346 return B_NO_ERROR; 347 } 348