xref: /haiku/src/kits/media/MediaEncoder.cpp (revision 218a8c03cbadd95d8888b218930f514fa0b4fac4)
12b514992SDario Casalinuovo /*
22b514992SDario Casalinuovo  * Copyright 2015, Dario Casalinuovo
32b514992SDario Casalinuovo  * Copyright 2010, Oleg Krysenkov, beos344@mail.ru.
42b514992SDario Casalinuovo  * Copyright 2012, Fredrik Modéen, [firstname]@[lastname].se.
52b514992SDario Casalinuovo  * Copyright 2004-2007, Marcus Overhagen. All rights reserved.
62b514992SDario Casalinuovo  * Distributed under the terms of the MIT License.
72b514992SDario Casalinuovo  */
82b514992SDario Casalinuovo 
92b514992SDario Casalinuovo 
1052a38012Sejakowatz #include <MediaEncoder.h>
112b514992SDario Casalinuovo 
12*218a8c03SAugustin Cavalier #include <EncoderPlugin.h>
13*218a8c03SAugustin Cavalier #include <PluginManager.h>
142b514992SDario Casalinuovo 
152b514992SDario Casalinuovo #include <new>
162b514992SDario Casalinuovo 
17b84955d4SBarrett17 #include "MediaDebug.h"
1852a38012Sejakowatz 
1952a38012Sejakowatz /*************************************************************
2052a38012Sejakowatz  * public BMediaEncoder
2152a38012Sejakowatz  *************************************************************/
2252a38012Sejakowatz 
BMediaEncoder()2352a38012Sejakowatz BMediaEncoder::BMediaEncoder()
242b514992SDario Casalinuovo 	:
252b514992SDario Casalinuovo 	fEncoder(NULL),
262b514992SDario Casalinuovo 	fInitStatus(B_NO_INIT)
2752a38012Sejakowatz {
282b514992SDario Casalinuovo 	CALLED();
2952a38012Sejakowatz }
3052a38012Sejakowatz 
3152a38012Sejakowatz 
BMediaEncoder(const media_format * outputFormat)32537ea80aSDario Casalinuovo BMediaEncoder::BMediaEncoder(const media_format* outputFormat)
332b514992SDario Casalinuovo 	:
342b514992SDario Casalinuovo 	fEncoder(NULL),
352b514992SDario Casalinuovo 	fInitStatus(B_NO_INIT)
3652a38012Sejakowatz {
372b514992SDario Casalinuovo 	CALLED();
38537ea80aSDario Casalinuovo 	SetTo(outputFormat);
3952a38012Sejakowatz }
4052a38012Sejakowatz 
4152a38012Sejakowatz 
BMediaEncoder(const media_codec_info * mci)4252a38012Sejakowatz BMediaEncoder::BMediaEncoder(const media_codec_info* mci)
432b514992SDario Casalinuovo 	:
442b514992SDario Casalinuovo 	fEncoder(NULL),
452b514992SDario Casalinuovo 	fInitStatus(B_NO_INIT)
4652a38012Sejakowatz {
472b514992SDario Casalinuovo 	CALLED();
482b514992SDario Casalinuovo 	SetTo(mci);
4952a38012Sejakowatz }
5052a38012Sejakowatz 
5152a38012Sejakowatz 
5252a38012Sejakowatz /* virtual */
~BMediaEncoder()5352a38012Sejakowatz BMediaEncoder::~BMediaEncoder()
5452a38012Sejakowatz {
552b514992SDario Casalinuovo 	CALLED();
569bc60a8bSDario Casalinuovo 	ReleaseEncoder();
5752a38012Sejakowatz }
5852a38012Sejakowatz 
5952a38012Sejakowatz 
6052a38012Sejakowatz status_t
InitCheck() const6152a38012Sejakowatz BMediaEncoder::InitCheck() const
6252a38012Sejakowatz {
632b514992SDario Casalinuovo 	return fInitStatus;
6452a38012Sejakowatz }
6552a38012Sejakowatz 
662b514992SDario Casalinuovo 
6752a38012Sejakowatz status_t
SetTo(const media_format * outputFormat)68537ea80aSDario Casalinuovo BMediaEncoder::SetTo(const media_format* outputFormat)
6952a38012Sejakowatz {
702b514992SDario Casalinuovo 	CALLED();
712b514992SDario Casalinuovo 
722b514992SDario Casalinuovo 	status_t err = B_ERROR;
739bc60a8bSDario Casalinuovo 	ReleaseEncoder();
749bc60a8bSDario Casalinuovo 
75537ea80aSDario Casalinuovo 	if (outputFormat == NULL)
769bc60a8bSDario Casalinuovo 		return fInitStatus;
779bc60a8bSDario Casalinuovo 
78537ea80aSDario Casalinuovo 	media_format format = *outputFormat;
79*218a8c03SAugustin Cavalier 	err = gPluginManager.CreateEncoder(&fEncoder, format);
809bc60a8bSDario Casalinuovo 	if (fEncoder != NULL && err == B_OK) {
812b514992SDario Casalinuovo 		err = _AttachToEncoder();
822d508790SDario Casalinuovo 		if (err == B_OK)
832d508790SDario Casalinuovo 			return err;
849bc60a8bSDario Casalinuovo 	}
859bc60a8bSDario Casalinuovo 	ReleaseEncoder();
862b514992SDario Casalinuovo 	fInitStatus = err;
872b514992SDario Casalinuovo 	return err;
882b514992SDario Casalinuovo }
892b514992SDario Casalinuovo 
902b514992SDario Casalinuovo 
9152a38012Sejakowatz status_t
SetTo(const media_codec_info * mci)9252a38012Sejakowatz BMediaEncoder::SetTo(const media_codec_info* mci)
9352a38012Sejakowatz {
942b514992SDario Casalinuovo 	CALLED();
952b514992SDario Casalinuovo 
969bc60a8bSDario Casalinuovo 	ReleaseEncoder();
97*218a8c03SAugustin Cavalier 	status_t err = gPluginManager.CreateEncoder(&fEncoder, mci, 0);
989bc60a8bSDario Casalinuovo 	if (fEncoder != NULL && err == B_OK) {
992b514992SDario Casalinuovo 		err = _AttachToEncoder();
1009bc60a8bSDario Casalinuovo 		if (err == B_OK) {
1012b514992SDario Casalinuovo 			fInitStatus = B_OK;
10252a38012Sejakowatz 			return B_OK;
1039bc60a8bSDario Casalinuovo 		}
1049bc60a8bSDario Casalinuovo 	}
1052b514992SDario Casalinuovo 
1069bc60a8bSDario Casalinuovo 	ReleaseEncoder();
1079bc60a8bSDario Casalinuovo 	fInitStatus = err;
1082b514992SDario Casalinuovo 	return err;
10952a38012Sejakowatz }
11052a38012Sejakowatz 
11152a38012Sejakowatz 
11252a38012Sejakowatz status_t
SetFormat(media_format * inputFormat,media_format * outputFormat,media_file_format * mfi)113537ea80aSDario Casalinuovo BMediaEncoder::SetFormat(media_format* inputFormat,
114537ea80aSDario Casalinuovo 	media_format* outputFormat, media_file_format* mfi)
11552a38012Sejakowatz {
1162b514992SDario Casalinuovo 	CALLED();
1172b514992SDario Casalinuovo 	TRACE("BMediaEncoder::SetFormat. Input = %d, Output = %d\n",
118537ea80aSDario Casalinuovo 		inputFormat->type, outputFormat->type);
1192b514992SDario Casalinuovo 
1202b514992SDario Casalinuovo 	if (!fEncoder)
1212b514992SDario Casalinuovo 		return B_NO_INIT;
1222b514992SDario Casalinuovo 
1232d508790SDario Casalinuovo 	if (outputFormat != NULL)
1242d508790SDario Casalinuovo 		SetTo(outputFormat);
1252d508790SDario Casalinuovo 
1262d508790SDario Casalinuovo 	//TODO: How we support mfi?
127537ea80aSDario Casalinuovo 	return fEncoder->SetUp(inputFormat);
12852a38012Sejakowatz }
12952a38012Sejakowatz 
1302b514992SDario Casalinuovo 
13152a38012Sejakowatz status_t
Encode(const void * buffer,int64 frameCount,media_encode_info * info)13252a38012Sejakowatz BMediaEncoder::Encode(const void* buffer,
133537ea80aSDario Casalinuovo 	int64 frameCount, media_encode_info* info)
13452a38012Sejakowatz {
1352b514992SDario Casalinuovo 	CALLED();
1362b514992SDario Casalinuovo 
1372b514992SDario Casalinuovo 	if (!fEncoder)
1382b514992SDario Casalinuovo 		return B_NO_INIT;
1392b514992SDario Casalinuovo 
140537ea80aSDario Casalinuovo 	return fEncoder->Encode(buffer, frameCount, info);
14152a38012Sejakowatz }
14252a38012Sejakowatz 
14352a38012Sejakowatz 
14452a38012Sejakowatz status_t
GetEncodeParameters(encode_parameters * parameters) const14552a38012Sejakowatz BMediaEncoder::GetEncodeParameters(encode_parameters* parameters) const
14652a38012Sejakowatz {
1472b514992SDario Casalinuovo 	CALLED();
1482b514992SDario Casalinuovo 
1492b514992SDario Casalinuovo 	if (fEncoder == NULL)
1502b514992SDario Casalinuovo 		return B_NO_INIT;
1518cd14ac0SDario Casalinuovo 
1522b514992SDario Casalinuovo 	return fEncoder->GetEncodeParameters(parameters);
15352a38012Sejakowatz }
15452a38012Sejakowatz 
15552a38012Sejakowatz 
15652a38012Sejakowatz status_t
SetEncodeParameters(encode_parameters * parameters)15752a38012Sejakowatz BMediaEncoder::SetEncodeParameters(encode_parameters* parameters)
15852a38012Sejakowatz {
1592b514992SDario Casalinuovo 	CALLED();
1602b514992SDario Casalinuovo 
1612b514992SDario Casalinuovo 	if (fEncoder == NULL)
1622b514992SDario Casalinuovo 		return B_NO_INIT;
1638cd14ac0SDario Casalinuovo 
1642b514992SDario Casalinuovo 	return fEncoder->SetEncodeParameters(parameters);
16552a38012Sejakowatz }
16652a38012Sejakowatz 
16752a38012Sejakowatz 
16852a38012Sejakowatz /*************************************************************
16952a38012Sejakowatz  * protected BMediaEncoder
17052a38012Sejakowatz  *************************************************************/
17152a38012Sejakowatz 
17252a38012Sejakowatz /* virtual */ status_t
AddTrackInfo(uint32 code,const char * data,size_t size)17352a38012Sejakowatz BMediaEncoder::AddTrackInfo(uint32 code, const char* data, size_t size)
17452a38012Sejakowatz {
1752b514992SDario Casalinuovo 	CALLED();
1762b514992SDario Casalinuovo 
1772b514992SDario Casalinuovo 	if (fEncoder == NULL)
1782b514992SDario Casalinuovo 		return B_NO_INIT;
1798cd14ac0SDario Casalinuovo 
1802b514992SDario Casalinuovo 	return fEncoder->AddTrackInfo(code, data, size);
18152a38012Sejakowatz }
18252a38012Sejakowatz 
18352a38012Sejakowatz 
18452a38012Sejakowatz /*************************************************************
18552a38012Sejakowatz  * private BMediaEncoder
18652a38012Sejakowatz  *************************************************************/
18752a38012Sejakowatz 
18852a38012Sejakowatz /*
18952a38012Sejakowatz //	unimplemented
19052a38012Sejakowatz BMediaEncoder::BMediaEncoder(const BMediaEncoder &);
19152a38012Sejakowatz BMediaEncoder::BMediaEncoder & operator=(const BMediaEncoder &);
19252a38012Sejakowatz */
19352a38012Sejakowatz 
19452a38012Sejakowatz /* static */ status_t
write_chunk(void * classptr,const void * chunk_data,size_t chunk_len,media_encode_info * info)1952b514992SDario Casalinuovo BMediaEncoder::write_chunk(void* classptr, const void* chunk_data,
1962b514992SDario Casalinuovo 	size_t chunk_len, media_encode_info* info)
19752a38012Sejakowatz {
198106539c2SDario Casalinuovo 	CALLED();
199106539c2SDario Casalinuovo 
200106539c2SDario Casalinuovo 	BMediaEncoder* encoder = static_cast<BMediaEncoder*>(classptr);
201106539c2SDario Casalinuovo 	if (encoder == NULL)
202106539c2SDario Casalinuovo 		return B_BAD_VALUE;
203106539c2SDario Casalinuovo 	return encoder->WriteChunk(chunk_data, chunk_len, info);
20452a38012Sejakowatz }
20552a38012Sejakowatz 
20652a38012Sejakowatz 
20752a38012Sejakowatz void
Init()20852a38012Sejakowatz BMediaEncoder::Init()
20952a38012Sejakowatz {
21052a38012Sejakowatz 	UNIMPLEMENTED();
21152a38012Sejakowatz }
21252a38012Sejakowatz 
21352a38012Sejakowatz 
21452a38012Sejakowatz void
ReleaseEncoder()21552a38012Sejakowatz BMediaEncoder::ReleaseEncoder()
21652a38012Sejakowatz {
2179bc60a8bSDario Casalinuovo 	CALLED();
2189bc60a8bSDario Casalinuovo 	if (fEncoder != NULL) {
219*218a8c03SAugustin Cavalier 		gPluginManager.DestroyEncoder(fEncoder);
2209bc60a8bSDario Casalinuovo 		fEncoder = NULL;
2219bc60a8bSDario Casalinuovo 	}
2229bc60a8bSDario Casalinuovo 	fInitStatus = B_NO_INIT;
22352a38012Sejakowatz }
22452a38012Sejakowatz 
2252b514992SDario Casalinuovo 
2262b514992SDario Casalinuovo status_t
_AttachToEncoder()2272b514992SDario Casalinuovo BMediaEncoder::_AttachToEncoder()
2282b514992SDario Casalinuovo {
229*218a8c03SAugustin Cavalier 	class MediaEncoderChunkWriter : public ChunkWriter {
2302b514992SDario Casalinuovo 		public:
2312b514992SDario Casalinuovo 			MediaEncoderChunkWriter(BMediaEncoder* encoder)
2322b514992SDario Casalinuovo 			{
2332b514992SDario Casalinuovo 				fEncoder = encoder;
2342b514992SDario Casalinuovo 			}
2352b514992SDario Casalinuovo 			virtual status_t WriteChunk(const void* chunkBuffer,
2362b514992SDario Casalinuovo 				size_t chunkSize, media_encode_info* encodeInfo)
2372b514992SDario Casalinuovo 			{
2382b514992SDario Casalinuovo 				return fEncoder->WriteChunk(chunkBuffer, chunkSize, encodeInfo);
2392b514992SDario Casalinuovo 			}
2402b514992SDario Casalinuovo 		private:
2412b514992SDario Casalinuovo 			BMediaEncoder* fEncoder;
2422b514992SDario Casalinuovo 	} *writer = new(std::nothrow) MediaEncoderChunkWriter(this);
2432b514992SDario Casalinuovo 
2442b514992SDario Casalinuovo 	if (!writer)
2452b514992SDario Casalinuovo 		return B_NO_MEMORY;
2462b514992SDario Casalinuovo 
2472b514992SDario Casalinuovo 	fEncoder->SetChunkWriter(writer);
2482b514992SDario Casalinuovo 	return B_OK;
2492b514992SDario Casalinuovo }
2502b514992SDario Casalinuovo 
2512b514992SDario Casalinuovo 
_Reserved_BMediaEncoder_0(int32 arg,...)25252a38012Sejakowatz status_t BMediaEncoder::_Reserved_BMediaEncoder_0(int32 arg, ...) { return B_ERROR; }
_Reserved_BMediaEncoder_1(int32 arg,...)25352a38012Sejakowatz status_t BMediaEncoder::_Reserved_BMediaEncoder_1(int32 arg, ...) { return B_ERROR; }
_Reserved_BMediaEncoder_2(int32 arg,...)25452a38012Sejakowatz status_t BMediaEncoder::_Reserved_BMediaEncoder_2(int32 arg, ...) { return B_ERROR; }
_Reserved_BMediaEncoder_3(int32 arg,...)25552a38012Sejakowatz status_t BMediaEncoder::_Reserved_BMediaEncoder_3(int32 arg, ...) { return B_ERROR; }
_Reserved_BMediaEncoder_4(int32 arg,...)25652a38012Sejakowatz status_t BMediaEncoder::_Reserved_BMediaEncoder_4(int32 arg, ...) { return B_ERROR; }
_Reserved_BMediaEncoder_5(int32 arg,...)25752a38012Sejakowatz status_t BMediaEncoder::_Reserved_BMediaEncoder_5(int32 arg, ...) { return B_ERROR; }
_Reserved_BMediaEncoder_6(int32 arg,...)25852a38012Sejakowatz status_t BMediaEncoder::_Reserved_BMediaEncoder_6(int32 arg, ...) { return B_ERROR; }
_Reserved_BMediaEncoder_7(int32 arg,...)25952a38012Sejakowatz status_t BMediaEncoder::_Reserved_BMediaEncoder_7(int32 arg, ...) { return B_ERROR; }
_Reserved_BMediaEncoder_8(int32 arg,...)26052a38012Sejakowatz status_t BMediaEncoder::_Reserved_BMediaEncoder_8(int32 arg, ...) { return B_ERROR; }
_Reserved_BMediaEncoder_9(int32 arg,...)26152a38012Sejakowatz status_t BMediaEncoder::_Reserved_BMediaEncoder_9(int32 arg, ...) { return B_ERROR; }
_Reserved_BMediaEncoder_10(int32 arg,...)26252a38012Sejakowatz status_t BMediaEncoder::_Reserved_BMediaEncoder_10(int32 arg, ...) { return B_ERROR; }
_Reserved_BMediaEncoder_11(int32 arg,...)26352a38012Sejakowatz status_t BMediaEncoder::_Reserved_BMediaEncoder_11(int32 arg, ...) { return B_ERROR; }
_Reserved_BMediaEncoder_12(int32 arg,...)26452a38012Sejakowatz status_t BMediaEncoder::_Reserved_BMediaEncoder_12(int32 arg, ...) { return B_ERROR; }
_Reserved_BMediaEncoder_13(int32 arg,...)26552a38012Sejakowatz status_t BMediaEncoder::_Reserved_BMediaEncoder_13(int32 arg, ...) { return B_ERROR; }
_Reserved_BMediaEncoder_14(int32 arg,...)26652a38012Sejakowatz status_t BMediaEncoder::_Reserved_BMediaEncoder_14(int32 arg, ...) { return B_ERROR; }
_Reserved_BMediaEncoder_15(int32 arg,...)26752a38012Sejakowatz status_t BMediaEncoder::_Reserved_BMediaEncoder_15(int32 arg, ...) { return B_ERROR; }
26852a38012Sejakowatz 
26952a38012Sejakowatz /*************************************************************
27052a38012Sejakowatz  * public BMediaBufferEncoder
27152a38012Sejakowatz  *************************************************************/
27252a38012Sejakowatz 
BMediaBufferEncoder()27352a38012Sejakowatz BMediaBufferEncoder::BMediaBufferEncoder()
2742b514992SDario Casalinuovo 	:
2752b514992SDario Casalinuovo 	BMediaEncoder(),
2762b514992SDario Casalinuovo 	fBuffer(NULL)
27752a38012Sejakowatz {
2782b514992SDario Casalinuovo 	CALLED();
27952a38012Sejakowatz }
28052a38012Sejakowatz 
28152a38012Sejakowatz 
BMediaBufferEncoder(const media_format * outputFormat)282537ea80aSDario Casalinuovo BMediaBufferEncoder::BMediaBufferEncoder(const media_format* outputFormat)
2832b514992SDario Casalinuovo 	:
284537ea80aSDario Casalinuovo 	BMediaEncoder(outputFormat),
2852b514992SDario Casalinuovo 	fBuffer(NULL)
28652a38012Sejakowatz {
2872b514992SDario Casalinuovo 	CALLED();
28852a38012Sejakowatz }
28952a38012Sejakowatz 
29052a38012Sejakowatz 
BMediaBufferEncoder(const media_codec_info * mci)29152a38012Sejakowatz BMediaBufferEncoder::BMediaBufferEncoder(const media_codec_info* mci)
2922b514992SDario Casalinuovo 	:
2932b514992SDario Casalinuovo 	BMediaEncoder(mci),
2942b514992SDario Casalinuovo 	fBuffer(NULL)
29552a38012Sejakowatz {
2962b514992SDario Casalinuovo 	CALLED();
29752a38012Sejakowatz }
29852a38012Sejakowatz 
29952a38012Sejakowatz 
30052a38012Sejakowatz status_t
EncodeToBuffer(void * outputBuffer,size_t * outputSize,const void * inputBuffer,int64 frameCount,media_encode_info * info)301537ea80aSDario Casalinuovo BMediaBufferEncoder::EncodeToBuffer(void* outputBuffer,
302537ea80aSDario Casalinuovo 	size_t* outputSize, const void* inputBuffer,
303537ea80aSDario Casalinuovo 	int64 frameCount, media_encode_info* info)
30452a38012Sejakowatz {
3052b514992SDario Casalinuovo 	CALLED();
30652a38012Sejakowatz 
3072b514992SDario Casalinuovo 	status_t error;
308537ea80aSDario Casalinuovo 	fBuffer = outputBuffer;
309537ea80aSDario Casalinuovo 	fBufferSize = *outputSize;
310537ea80aSDario Casalinuovo 	error = Encode(inputBuffer, frameCount, info);
3112b514992SDario Casalinuovo 	if (fBuffer) {
3122b514992SDario Casalinuovo 		fBuffer = NULL;
313537ea80aSDario Casalinuovo 		*outputSize = 0;
3142b514992SDario Casalinuovo 	} else {
315537ea80aSDario Casalinuovo 		*outputSize = fBufferSize;
3162b514992SDario Casalinuovo 	}
3172b514992SDario Casalinuovo 	return error;
31852a38012Sejakowatz }
31952a38012Sejakowatz 
32052a38012Sejakowatz 
32152a38012Sejakowatz /*************************************************************
32252a38012Sejakowatz  * public BMediaBufferEncoder
32352a38012Sejakowatz  *************************************************************/
32452a38012Sejakowatz 
32552a38012Sejakowatz status_t
WriteChunk(const void * chunkData,size_t chunkLen,media_encode_info * info)326537ea80aSDario Casalinuovo BMediaBufferEncoder::WriteChunk(const void* chunkData,
327537ea80aSDario Casalinuovo 	size_t chunkLen, media_encode_info* info)
32852a38012Sejakowatz {
3292b514992SDario Casalinuovo 	CALLED();
33052a38012Sejakowatz 
3312b514992SDario Casalinuovo 	if (fBuffer == NULL)
3322b514992SDario Casalinuovo 		return B_ENTRY_NOT_FOUND;
3332b514992SDario Casalinuovo 
334537ea80aSDario Casalinuovo 	if (chunkLen > (size_t)fBufferSize) {
335537ea80aSDario Casalinuovo 		memcpy(fBuffer, chunkData, fBufferSize);
3362b514992SDario Casalinuovo 		fBuffer = NULL;
3372b514992SDario Casalinuovo 		return B_DEVICE_FULL;
33852a38012Sejakowatz 	}
33952a38012Sejakowatz 
340537ea80aSDario Casalinuovo 	memcpy(fBuffer, chunkData, chunkLen);
341537ea80aSDario Casalinuovo 	fBufferSize = chunkLen;
3422b514992SDario Casalinuovo 	fBuffer = NULL;
3432b514992SDario Casalinuovo 	return B_NO_ERROR;
3442b514992SDario Casalinuovo }
345