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
23BMediaEncoder::BMediaEncoder()
24	:
25	fEncoder(NULL),
26	fInitStatus(B_NO_INIT)
27{
28	CALLED();
29}
30
31
32BMediaEncoder::BMediaEncoder(const media_format* outputFormat)
33	:
34	fEncoder(NULL),
35	fInitStatus(B_NO_INIT)
36{
37	CALLED();
38	SetTo(outputFormat);
39}
40
41
42BMediaEncoder::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 */
53BMediaEncoder::~BMediaEncoder()
54{
55	CALLED();
56	ReleaseEncoder();
57}
58
59
60status_t
61BMediaEncoder::InitCheck() const
62{
63	return fInitStatus;
64}
65
66
67status_t
68BMediaEncoder::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
91status_t
92BMediaEncoder::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
112status_t
113BMediaEncoder::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
131status_t
132BMediaEncoder::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
144status_t
145BMediaEncoder::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
156status_t
157BMediaEncoder::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
173BMediaEncoder::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
190BMediaEncoder::BMediaEncoder(const BMediaEncoder &);
191BMediaEncoder::BMediaEncoder & operator=(const BMediaEncoder &);
192*/
193
194/* static */ status_t
195BMediaEncoder::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
207void
208BMediaEncoder::Init()
209{
210	UNIMPLEMENTED();
211}
212
213
214void
215BMediaEncoder::ReleaseEncoder()
216{
217	CALLED();
218	if (fEncoder != NULL) {
219		gPluginManager.DestroyEncoder(fEncoder);
220		fEncoder = NULL;
221	}
222	fInitStatus = B_NO_INIT;
223}
224
225
226status_t
227BMediaEncoder::_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
252status_t BMediaEncoder::_Reserved_BMediaEncoder_0(int32 arg, ...) { return B_ERROR; }
253status_t BMediaEncoder::_Reserved_BMediaEncoder_1(int32 arg, ...) { return B_ERROR; }
254status_t BMediaEncoder::_Reserved_BMediaEncoder_2(int32 arg, ...) { return B_ERROR; }
255status_t BMediaEncoder::_Reserved_BMediaEncoder_3(int32 arg, ...) { return B_ERROR; }
256status_t BMediaEncoder::_Reserved_BMediaEncoder_4(int32 arg, ...) { return B_ERROR; }
257status_t BMediaEncoder::_Reserved_BMediaEncoder_5(int32 arg, ...) { return B_ERROR; }
258status_t BMediaEncoder::_Reserved_BMediaEncoder_6(int32 arg, ...) { return B_ERROR; }
259status_t BMediaEncoder::_Reserved_BMediaEncoder_7(int32 arg, ...) { return B_ERROR; }
260status_t BMediaEncoder::_Reserved_BMediaEncoder_8(int32 arg, ...) { return B_ERROR; }
261status_t BMediaEncoder::_Reserved_BMediaEncoder_9(int32 arg, ...) { return B_ERROR; }
262status_t BMediaEncoder::_Reserved_BMediaEncoder_10(int32 arg, ...) { return B_ERROR; }
263status_t BMediaEncoder::_Reserved_BMediaEncoder_11(int32 arg, ...) { return B_ERROR; }
264status_t BMediaEncoder::_Reserved_BMediaEncoder_12(int32 arg, ...) { return B_ERROR; }
265status_t BMediaEncoder::_Reserved_BMediaEncoder_13(int32 arg, ...) { return B_ERROR; }
266status_t BMediaEncoder::_Reserved_BMediaEncoder_14(int32 arg, ...) { return B_ERROR; }
267status_t BMediaEncoder::_Reserved_BMediaEncoder_15(int32 arg, ...) { return B_ERROR; }
268
269/*************************************************************
270 * public BMediaBufferEncoder
271 *************************************************************/
272
273BMediaBufferEncoder::BMediaBufferEncoder()
274	:
275	BMediaEncoder(),
276	fBuffer(NULL)
277{
278	CALLED();
279}
280
281
282BMediaBufferEncoder::BMediaBufferEncoder(const media_format* outputFormat)
283	:
284	BMediaEncoder(outputFormat),
285	fBuffer(NULL)
286{
287	CALLED();
288}
289
290
291BMediaBufferEncoder::BMediaBufferEncoder(const media_codec_info* mci)
292	:
293	BMediaEncoder(mci),
294	fBuffer(NULL)
295{
296	CALLED();
297}
298
299
300status_t
301BMediaBufferEncoder::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
325status_t
326BMediaBufferEncoder::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