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