xref: /haiku/src/add-ons/media/plugins/ffmpeg/AVCodecEncoder.cpp (revision b08627f310bb2e80bca50176e7a758182384735a)
1 /*
2  * Copyright 2009-2010, Stephan Amßus <superstippi@gmx.de>
3  * All rights reserved. Distributed under the terms of the MIT license.
4  */
5 
6 
7 #include "AVCodecEncoder.h"
8 
9 #include <new>
10 
11 #include <stdio.h>
12 #include <string.h>
13 
14 #include <Application.h>
15 #include <Roster.h>
16 
17 extern "C" {
18 	#include "rational.h"
19 }
20 
21 #include "EncoderTable.h"
22 #include "gfx_util.h"
23 
24 
25 #undef TRACE
26 //#define TRACE_AV_CODEC_ENCODER
27 #ifdef TRACE_AV_CODEC_ENCODER
28 #	define TRACE	printf
29 #	define TRACE_IO(a...)
30 #else
31 #	define TRACE(a...)
32 #	define TRACE_IO(a...)
33 #endif
34 
35 
36 static const size_t kDefaultChunkBufferSize = 2 * 1024 * 1024;
37 
38 #if LIBAVCODEC_VERSION_INT < ((54 << 16) | (50 << 8))
39 #define AV_PIX_FMT_NONE PIX_FMT_NONE
40 #define AV_CODEC_ID_NONE CODEC_ID_NONE
41 #define AV_CODEC_ID_MPEG1VIDEO CODEC_ID_MPEG1VIDEO
42 #define AV_CODEC_ID_MPEG2VIDEO CODEC_ID_MPEG2VIDEO
43 #endif
44 #if LIBAVCODEC_VERSION_INT < ((55 << 16) | (45 << 8))
45 #define av_frame_alloc avcodec_alloc_frame
46 #define av_frame_unref avcodec_get_frame_defaults
47 #define av_frame_free avcodec_free_frame
48 #endif
49 
50 
51 AVCodecEncoder::AVCodecEncoder(uint32 codecID, int bitRateScale)
52 	:
53 	Encoder(),
54 	fBitRateScale(bitRateScale),
55 	fCodecID((CodecID)codecID),
56 	fCodec(NULL),
57 	fOwnContext(avcodec_alloc_context3(NULL)),
58 	fContext(fOwnContext),
59 	fCodecInitStatus(CODEC_INIT_NEEDED),
60 	fFrame(av_frame_alloc()),
61 	fSwsContext(NULL),
62 	fFramesWritten(0)
63 {
64 	TRACE("AVCodecEncoder::AVCodecEncoder()\n");
65 	_Init();
66 }
67 
68 
69 void
70 AVCodecEncoder::_Init()
71 {
72 	fChunkBuffer = new(std::nothrow) uint8[kDefaultChunkBufferSize];
73 	if (fCodecID > 0) {
74 		fCodec = avcodec_find_encoder(fCodecID);
75 		TRACE("  found AVCodec for %u: %p\n", fCodecID, fCodec);
76 	}
77 
78 	memset(&fInputFormat, 0, sizeof(media_format));
79 
80 	fAudioFifo = av_fifo_alloc(0);
81 
82 	fDstFrame.data[0] = NULL;
83 	fDstFrame.data[1] = NULL;
84 	fDstFrame.data[2] = NULL;
85 	fDstFrame.data[3] = NULL;
86 
87 	fDstFrame.linesize[0] = 0;
88 	fDstFrame.linesize[1] = 0;
89 	fDstFrame.linesize[2] = 0;
90 	fDstFrame.linesize[3] = 0;
91 
92 	// Initial parameters, so we know if the user changed them
93 	fEncodeParameters.avg_field_size = 0;
94 	fEncodeParameters.max_field_size = 0;
95 	fEncodeParameters.quality = 1.0f;
96 }
97 
98 
99 AVCodecEncoder::~AVCodecEncoder()
100 {
101 	TRACE("AVCodecEncoder::~AVCodecEncoder()\n");
102 
103 	_CloseCodecIfNeeded();
104 
105 	if (fSwsContext != NULL)
106 		sws_freeContext(fSwsContext);
107 
108 	av_fifo_free(fAudioFifo);
109 
110 	avpicture_free(&fDstFrame);
111 	// NOTE: Do not use avpicture_free() on fSrcFrame!! We fill the picture
112 	// data on the fly with the media buffer data passed to Encode().
113 
114 	if (fFrame != NULL) {
115 		fFrame->data[0] = NULL;
116 		fFrame->data[1] = NULL;
117 		fFrame->data[2] = NULL;
118 		fFrame->data[3] = NULL;
119 
120 		fFrame->linesize[0] = 0;
121 		fFrame->linesize[1] = 0;
122 		fFrame->linesize[2] = 0;
123 		fFrame->linesize[3] = 0;
124 		av_free(fFrame);
125 	}
126 
127 	av_free(fOwnContext);
128 
129 	delete[] fChunkBuffer;
130 }
131 
132 
133 status_t
134 AVCodecEncoder::AcceptedFormat(const media_format* proposedInputFormat,
135 	media_format* _acceptedInputFormat)
136 {
137 	TRACE("AVCodecEncoder::AcceptedFormat(%p, %p)\n", proposedInputFormat,
138 		_acceptedInputFormat);
139 
140 	if (proposedInputFormat == NULL)
141 		return B_BAD_VALUE;
142 
143 	if (_acceptedInputFormat != NULL) {
144 		memcpy(_acceptedInputFormat, proposedInputFormat,
145 			sizeof(media_format));
146 	}
147 
148 	return B_OK;
149 }
150 
151 
152 status_t
153 AVCodecEncoder::SetUp(const media_format* inputFormat)
154 {
155 	TRACE("AVCodecEncoder::SetUp()\n");
156 
157 	if (fContext == NULL)
158 		return B_NO_INIT;
159 
160 	if (inputFormat == NULL)
161 		return B_BAD_VALUE;
162 
163 	// Codec IDs for raw-formats may need to be figured out here.
164 	if (fCodec == NULL && fCodecID == AV_CODEC_ID_NONE) {
165 		fCodecID = raw_audio_codec_id_for(*inputFormat);
166 		if (fCodecID != AV_CODEC_ID_NONE)
167 			fCodec = avcodec_find_encoder(fCodecID);
168 	}
169 	if (fCodec == NULL) {
170 		TRACE("  encoder not found!\n");
171 		return B_NO_INIT;
172 	}
173 
174 	_CloseCodecIfNeeded();
175 
176 	fInputFormat = *inputFormat;
177 	fFramesWritten = 0;
178 
179 	const uchar* userData = inputFormat->user_data;
180 	if (*(uint32*)userData == 'ffmp') {
181 		userData += sizeof(uint32);
182 		// The Writer plugin used is the FFmpeg plugin. It stores the
183 		// AVCodecContext pointer in the user data section. Use this
184 		// context instead of our own. It requires the Writer living in
185 		// the same team, of course.
186 		app_info appInfo;
187 		if (be_app->GetAppInfo(&appInfo) == B_OK
188 			&& *(team_id*)userData == appInfo.team) {
189 			userData += sizeof(team_id);
190 			// Use the AVCodecContext from the Writer. This works better
191 			// than using our own context with some encoders.
192 			fContext = *(AVCodecContext**)userData;
193 		}
194 	}
195 
196 	return _Setup();
197 }
198 
199 
200 status_t
201 AVCodecEncoder::GetEncodeParameters(encode_parameters* parameters) const
202 {
203 	TRACE("AVCodecEncoder::GetEncodeParameters(%p)\n", parameters);
204 
205 // TODO: Implement maintaining an automatically calculated bit_rate versus
206 // a user specified (via SetEncodeParameters()) bit_rate. At this point, the
207 // fContext->bit_rate may not yet have been specified (_Setup() was never
208 // called yet). So it cannot work like the code below, but in any case, it's
209 // showing how to convert between the values (albeit untested).
210 //	int avgBytesPerSecond = fContext->bit_rate / 8;
211 //	int maxBytesPerSecond = (fContext->bit_rate
212 //		+ fContext->bit_rate_tolerance) / 8;
213 //
214 //	if (fInputFormat.type == B_MEDIA_RAW_AUDIO) {
215 //		fEncodeParameters.avg_field_size = (int32)(avgBytesPerSecond
216 //			/ fInputFormat.u.raw_audio.frame_rate);
217 //		fEncodeParameters.max_field_size = (int32)(maxBytesPerSecond
218 //			/ fInputFormat.u.raw_audio.frame_rate);
219 //	} else if (fInputFormat.type == B_MEDIA_RAW_VIDEO) {
220 //		fEncodeParameters.avg_field_size = (int32)(avgBytesPerSecond
221 //			/ fInputFormat.u.raw_video.field_rate);
222 //		fEncodeParameters.max_field_size = (int32)(maxBytesPerSecond
223 //			/ fInputFormat.u.raw_video.field_rate);
224 //	}
225 
226 	parameters->quality = fEncodeParameters.quality;
227 
228 	return B_OK;
229 }
230 
231 
232 status_t
233 AVCodecEncoder::SetEncodeParameters(encode_parameters* parameters)
234 {
235 	TRACE("AVCodecEncoder::SetEncodeParameters(%p)\n", parameters);
236 
237 	if (fFramesWritten > 0)
238 		return B_NOT_SUPPORTED;
239 
240 	fEncodeParameters.quality = parameters->quality;
241 	TRACE("  quality: %.5f\n", parameters->quality);
242 	if (fEncodeParameters.quality == 0.0f) {
243 		TRACE("  using default quality (1.0)\n");
244 		fEncodeParameters.quality = 1.0f;
245 	}
246 
247 // TODO: Auto-bit_rate versus user supplied. See above.
248 //	int avgBytesPerSecond = 0;
249 //	int maxBytesPerSecond = 0;
250 //
251 //	if (fInputFormat.type == B_MEDIA_RAW_AUDIO) {
252 //		avgBytesPerSecond = (int)(parameters->avg_field_size
253 //			* fInputFormat.u.raw_audio.frame_rate);
254 //		maxBytesPerSecond = (int)(parameters->max_field_size
255 //			* fInputFormat.u.raw_audio.frame_rate);
256 //	} else if (fInputFormat.type == B_MEDIA_RAW_VIDEO) {
257 //		avgBytesPerSecond = (int)(parameters->avg_field_size
258 //			* fInputFormat.u.raw_video.field_rate);
259 //		maxBytesPerSecond = (int)(parameters->max_field_size
260 //			* fInputFormat.u.raw_video.field_rate);
261 //	}
262 //
263 //	if (maxBytesPerSecond < avgBytesPerSecond)
264 //		maxBytesPerSecond = avgBytesPerSecond;
265 //
266 //	// Reset these, so we can tell the difference between uninitialized
267 //	// and initialized...
268 //	if (avgBytesPerSecond > 0) {
269 //		fContext->bit_rate = avgBytesPerSecond * 8;
270 //		fContext->bit_rate_tolerance = (maxBytesPerSecond
271 //			- avgBytesPerSecond) * 8;
272 //		fBitRateControlledByUser = true;
273 //	}
274 
275 	return _Setup();
276 }
277 
278 
279 status_t
280 AVCodecEncoder::Encode(const void* buffer, int64 frameCount,
281 	media_encode_info* info)
282 {
283 	TRACE("AVCodecEncoder::Encode(%p, %lld, %p)\n", buffer, frameCount, info);
284 
285 	if (!_OpenCodecIfNeeded())
286 		return B_NO_INIT;
287 
288 	if (fInputFormat.type == B_MEDIA_RAW_AUDIO)
289 		return _EncodeAudio(buffer, frameCount, info);
290 	else if (fInputFormat.type == B_MEDIA_RAW_VIDEO)
291 		return _EncodeVideo(buffer, frameCount, info);
292 	else
293 		return B_NO_INIT;
294 }
295 
296 
297 // #pragma mark -
298 
299 
300 status_t
301 AVCodecEncoder::_Setup()
302 {
303 	TRACE("AVCodecEncoder::_Setup\n");
304 
305 	int rawBitRate;
306 
307 	if (fInputFormat.type == B_MEDIA_RAW_VIDEO) {
308 		TRACE("  B_MEDIA_RAW_VIDEO\n");
309 		// frame rate
310 		fContext->time_base.den = (int)fInputFormat.u.raw_video.field_rate;
311 		fContext->time_base.num = 1;
312 		// video size
313 		fContext->width = fInputFormat.u.raw_video.display.line_width;
314 		fContext->height = fInputFormat.u.raw_video.display.line_count;
315 		fContext->gop_size = 12;
316 
317 		// TODO: Fix pixel format or setup conversion method...
318 		if (fCodec->pix_fmts != NULL) {
319 			for (int i = 0; fCodec->pix_fmts[i] != AV_PIX_FMT_NONE; i++) {
320 				// Use the last supported pixel format, which we hope is the
321 				// one with the best quality.
322 				fContext->pix_fmt = fCodec->pix_fmts[i];
323 			}
324 		}
325 
326 		// TODO: Setup rate control:
327 //		fContext->rate_emu = 0;
328 //		fContext->rc_eq = NULL;
329 //		fContext->rc_max_rate = 0;
330 //		fContext->rc_min_rate = 0;
331 		// TODO: Try to calculate a good bit rate...
332 		rawBitRate = (int)(fContext->width * fContext->height * 2
333 			* fInputFormat.u.raw_video.field_rate) * 8;
334 
335 		// Pixel aspect ratio
336 		fContext->sample_aspect_ratio.num
337 			= fInputFormat.u.raw_video.pixel_width_aspect;
338 		fContext->sample_aspect_ratio.den
339 			= fInputFormat.u.raw_video.pixel_height_aspect;
340 		if (fContext->sample_aspect_ratio.num == 0
341 			|| fContext->sample_aspect_ratio.den == 0) {
342 			av_reduce(&fContext->sample_aspect_ratio.num,
343 				&fContext->sample_aspect_ratio.den, fContext->width,
344 				fContext->height, 255);
345 		}
346 
347 		// TODO: This should already happen in AcceptFormat()
348 		if (fInputFormat.u.raw_video.display.bytes_per_row == 0) {
349 			fInputFormat.u.raw_video.display.bytes_per_row
350 				= fContext->width * 4;
351 		}
352 
353 		fFrame->pts = 0;
354 
355 		// Allocate space for colorspace converted AVPicture
356 		// TODO: Check allocations...
357 		avpicture_alloc(&fDstFrame, fContext->pix_fmt, fContext->width,
358 			fContext->height);
359 
360 		// Make the frame point to the data in the converted AVPicture
361 		fFrame->data[0] = fDstFrame.data[0];
362 		fFrame->data[1] = fDstFrame.data[1];
363 		fFrame->data[2] = fDstFrame.data[2];
364 		fFrame->data[3] = fDstFrame.data[3];
365 
366 		fFrame->linesize[0] = fDstFrame.linesize[0];
367 		fFrame->linesize[1] = fDstFrame.linesize[1];
368 		fFrame->linesize[2] = fDstFrame.linesize[2];
369 		fFrame->linesize[3] = fDstFrame.linesize[3];
370 
371 		fSwsContext = sws_getContext(fContext->width, fContext->height,
372 			colorspace_to_pixfmt(fInputFormat.u.raw_video.display.format),
373 			fContext->width, fContext->height,
374 			fContext->pix_fmt, SWS_FAST_BILINEAR, NULL, NULL, NULL);
375 
376 	} else if (fInputFormat.type == B_MEDIA_RAW_AUDIO) {
377 		TRACE("  B_MEDIA_RAW_AUDIO\n");
378 		// frame rate
379 		fContext->sample_rate = (int)fInputFormat.u.raw_audio.frame_rate;
380 		// channels
381 		fContext->channels = fInputFormat.u.raw_audio.channel_count;
382 		// raw bitrate
383 		rawBitRate = fContext->sample_rate * fContext->channels
384 			* (fInputFormat.u.raw_audio.format
385 				& media_raw_audio_format::B_AUDIO_SIZE_MASK) * 8;
386 		// sample format
387 		switch (fInputFormat.u.raw_audio.format) {
388 			case media_raw_audio_format::B_AUDIO_FLOAT:
389 				fContext->sample_fmt = AV_SAMPLE_FMT_FLT;
390 				break;
391 			case media_raw_audio_format::B_AUDIO_DOUBLE:
392 				fContext->sample_fmt = AV_SAMPLE_FMT_DBL;
393 				break;
394 			case media_raw_audio_format::B_AUDIO_INT:
395 				fContext->sample_fmt = AV_SAMPLE_FMT_S32;
396 				break;
397 			case media_raw_audio_format::B_AUDIO_SHORT:
398 				fContext->sample_fmt = AV_SAMPLE_FMT_S16;
399 				break;
400 			case media_raw_audio_format::B_AUDIO_UCHAR:
401 				fContext->sample_fmt = AV_SAMPLE_FMT_U8;
402 				break;
403 
404 			case media_raw_audio_format::B_AUDIO_CHAR:
405 			default:
406 				return B_MEDIA_BAD_FORMAT;
407 				break;
408 		}
409 		if (fInputFormat.u.raw_audio.channel_mask == 0) {
410 			// guess the channel mask...
411 			switch (fInputFormat.u.raw_audio.channel_count) {
412 				default:
413 				case 2:
414 					fContext->channel_layout = AV_CH_LAYOUT_STEREO;
415 					break;
416 				case 1:
417 					fContext->channel_layout = AV_CH_LAYOUT_MONO;
418 					break;
419 				case 3:
420 					fContext->channel_layout = AV_CH_LAYOUT_SURROUND;
421 					break;
422 				case 4:
423 					fContext->channel_layout = AV_CH_LAYOUT_QUAD;
424 					break;
425 				case 5:
426 					fContext->channel_layout = AV_CH_LAYOUT_5POINT0;
427 					break;
428 				case 6:
429 					fContext->channel_layout = AV_CH_LAYOUT_5POINT1;
430 					break;
431 				case 8:
432 					fContext->channel_layout = AV_CH_LAYOUT_7POINT1;
433 					break;
434 				case 10:
435 					fContext->channel_layout = AV_CH_LAYOUT_7POINT1_WIDE;
436 					break;
437 			}
438 		} else {
439 			// The bits match 1:1 for media_multi_channels and FFmpeg defines.
440 			fContext->channel_layout = fInputFormat.u.raw_audio.channel_mask;
441 		}
442 	} else {
443 		TRACE("  UNSUPPORTED MEDIA TYPE!\n");
444 		return B_NOT_SUPPORTED;
445 	}
446 
447 	// TODO: Support letting the user overwrite this via
448 	// SetEncodeParameters(). See comments there...
449 	int wantedBitRate = (int)(rawBitRate / fBitRateScale
450 		* fEncodeParameters.quality);
451 	if (wantedBitRate == 0)
452 		wantedBitRate = (int)(rawBitRate / fBitRateScale);
453 
454 	fContext->bit_rate = wantedBitRate;
455 
456 	if (fInputFormat.type == B_MEDIA_RAW_AUDIO) {
457 		// Some audio encoders support certain bitrates only. Use the
458 		// closest match to the wantedBitRate.
459 		const int kBitRates[] = {
460 			32000, 40000, 48000, 56000, 64000, 80000, 96000, 112000, 128000,
461 			160000, 192000, 224000, 256000, 320000, 384000, 448000, 512000,
462 			576000, 640000
463 		};
464 		int diff = wantedBitRate;
465 		for (unsigned int i = 0; i < sizeof(kBitRates) / sizeof(int); i++) {
466 			int currentDiff = abs(wantedBitRate - kBitRates[i]);
467 			if (currentDiff < diff) {
468 				fContext->bit_rate = kBitRates[i];
469 				diff = currentDiff;
470 			} else
471 				break;
472 		}
473 	}
474 
475 	TRACE("  rawBitRate: %d, wantedBitRate: %d (%.1f), "
476 		"context bitrate: %d\n", rawBitRate, wantedBitRate,
477 		fEncodeParameters.quality, fContext->bit_rate);
478 
479 	// Add some known fixes from the FFmpeg API example:
480 	if (fContext->codec_id == AV_CODEC_ID_MPEG2VIDEO) {
481 		// Just for testing, we also add B frames */
482 		fContext->max_b_frames = 2;
483 	} else if (fContext->codec_id == AV_CODEC_ID_MPEG1VIDEO) {
484 		// Needed to avoid using macroblocks in which some coeffs overflow.
485 		// This does not happen with normal video, it just happens here as
486 		// the motion of the chroma plane does not match the luma plane.
487 		fContext->mb_decision = 2;
488 	}
489 
490 	// Unfortunately, we may fail later, when we try to open the codec
491 	// for real... but we need to delay this because we still allow
492 	// parameter/quality changes.
493 	return B_OK;
494 }
495 
496 
497 bool
498 AVCodecEncoder::_OpenCodecIfNeeded()
499 {
500 	if (fContext != fOwnContext) {
501 		// We are using the AVCodecContext of the AVFormatWriter plugin,
502 		// and don't maintain it's open/close state.
503 		return true;
504 	}
505 
506 	if (fCodecInitStatus == CODEC_INIT_DONE)
507 		return true;
508 
509 	if (fCodecInitStatus == CODEC_INIT_FAILED)
510 		return false;
511 
512 	fContext->strict_std_compliance = -2;
513 
514 	// Some codecs need this to be set before open
515 	fFrame->format = fContext->pix_fmt;
516 	fFrame->width = fContext->width;
517 	fFrame->height = fContext->height;
518 
519 	// Open the codec
520 	int result = avcodec_open2(fContext, fCodec, NULL);
521 	if (result >= 0)
522 		fCodecInitStatus = CODEC_INIT_DONE;
523 	else
524 		fCodecInitStatus = CODEC_INIT_FAILED;
525 
526 	TRACE("  avcodec_open(%p, %p): %d\n", fContext, fCodec, result);
527 
528 	return fCodecInitStatus == CODEC_INIT_DONE;
529 
530 }
531 
532 
533 void
534 AVCodecEncoder::_CloseCodecIfNeeded()
535 {
536 	if (fContext != fOwnContext) {
537 		// See _OpenCodecIfNeeded().
538 		return;
539 	}
540 
541 	if (fCodecInitStatus == CODEC_INIT_DONE) {
542 		avcodec_close(fContext);
543 		fCodecInitStatus = CODEC_INIT_NEEDED;
544 	}
545 }
546 
547 
548 static const int64 kNoPTSValue = 0x8000000000000000LL;
549 	// NOTE: For some reasons, I have trouble with the avcodec.h define:
550 	// #define AV_NOPTS_VALUE          INT64_C(0x8000000000000000)
551 	// INT64_C is not defined here.
552 
553 status_t
554 AVCodecEncoder::_EncodeAudio(const void* _buffer, int64 frameCount,
555 	media_encode_info* info)
556 {
557 	TRACE("AVCodecEncoder::_EncodeAudio(%p, %lld, %p)\n", _buffer, frameCount,
558 		info);
559 
560 	if (fChunkBuffer == NULL)
561 		return B_NO_MEMORY;
562 
563 	status_t ret = B_OK;
564 
565 	const uint8* buffer = reinterpret_cast<const uint8*>(_buffer);
566 
567 	size_t inputSampleSize = fInputFormat.u.raw_audio.format
568 		& media_raw_audio_format::B_AUDIO_SIZE_MASK;
569 	size_t inputFrameSize = inputSampleSize
570 		* fInputFormat.u.raw_audio.channel_count;
571 
572 	size_t bufferSize = frameCount * inputFrameSize;
573 	bufferSize = min_c(bufferSize, kDefaultChunkBufferSize);
574 
575 	if (fContext->frame_size > 1) {
576 		// Encoded audio. Things work differently from raw audio. We need
577 		// the fAudioFifo to pipe data.
578 		if (av_fifo_realloc2(fAudioFifo,
579 				av_fifo_size(fAudioFifo) + bufferSize) < 0) {
580 			TRACE("  av_fifo_realloc2() failed\n");
581             return B_NO_MEMORY;
582         }
583         av_fifo_generic_write(fAudioFifo, const_cast<uint8*>(buffer),
584         	bufferSize, NULL);
585 
586 		int frameBytes = fContext->frame_size * inputFrameSize;
587 		uint8* tempBuffer = new(std::nothrow) uint8[frameBytes];
588 		if (tempBuffer == NULL)
589 			return B_NO_MEMORY;
590 
591 		// Encode as many chunks as can be read from the FIFO.
592 		while (av_fifo_size(fAudioFifo) >= frameBytes) {
593 			av_fifo_generic_read(fAudioFifo, tempBuffer, frameBytes, NULL);
594 
595 			ret = _EncodeAudio(tempBuffer, frameBytes, fContext->frame_size,
596 				info);
597 			if (ret != B_OK)
598 				break;
599 		}
600 
601 		delete[] tempBuffer;
602 	} else {
603 		// Raw audio. The number of bytes returned from avcodec_encode_audio()
604 		// is always the same as the number of input bytes.
605 		return _EncodeAudio(buffer, bufferSize, frameCount,
606 			info);
607 	}
608 
609 	return ret;
610 }
611 
612 
613 status_t
614 AVCodecEncoder::_EncodeAudio(const uint8* buffer, size_t bufferSize,
615 	int64 frameCount, media_encode_info* info)
616 {
617 	status_t ret;
618 
619 	// Encode one audio chunk/frame.
620 	AVPacket packet;
621 	av_init_packet(&packet);
622 	// By leaving these NULL, we let the encoder allocate memory as it needs.
623 	// This way we don't risk iving a too small buffer.
624 	packet.data = NULL;
625 	packet.size = 0;
626 
627 	// We need to wrap our input data into an AVFrame structure.
628 	AVFrame frame;
629 	int gotPacket = 0;
630 
631 	if (buffer) {
632 		av_frame_unref(&frame);
633 
634 		frame.nb_samples = frameCount;
635 
636 		ret = avcodec_fill_audio_frame(&frame, fContext->channels,
637 				fContext->sample_fmt, (const uint8_t *) buffer, bufferSize, 1);
638 
639 		if (ret != 0)
640 			return B_ERROR;
641 
642 		/* Set the presentation time of the frame */
643 		frame.pts = (bigtime_t)(fFramesWritten * 1000000LL
644 			/ fInputFormat.u.raw_audio.frame_rate);
645 		fFramesWritten += frame.nb_samples;
646 
647 		ret = avcodec_encode_audio2(fContext, &packet, &frame, &gotPacket);
648 	} else {
649 		// If called with NULL, ask the encoder to flush any buffers it may
650 		// have pending.
651 		ret = avcodec_encode_audio2(fContext, &packet, NULL, &gotPacket);
652 	}
653 
654 	if (buffer && frame.extended_data != frame.data)
655 		av_freep(&frame.extended_data);
656 
657 	if (ret != 0) {
658 		TRACE("  avcodec_encode_audio() failed: %ld\n", ret);
659 		return B_ERROR;
660 	}
661 
662 	fFramesWritten += frameCount;
663 
664 	if (gotPacket) {
665 		if (fContext->coded_frame) {
666 			// Store information about the coded frame in the context.
667 			fContext->coded_frame->pts = packet.pts;
668 			fContext->coded_frame->key_frame = !!(packet.flags & AV_PKT_FLAG_KEY);
669 		}
670 
671 		// Setup media_encode_info, most important is the time stamp.
672 		info->start_time = packet.pts;
673 
674 		if (packet.flags & AV_PKT_FLAG_KEY)
675 			info->flags = B_MEDIA_KEY_FRAME;
676 		else
677 			info->flags = 0;
678 
679 		// We got a packet out of the encoder, write it to the output stream
680 		ret = WriteChunk(packet.data, packet.size, info);
681 		if (ret != B_OK) {
682 			TRACE("  error writing chunk: %s\n", strerror(ret));
683 			av_free_packet(&packet);
684 			return ret;
685 		}
686 	}
687 
688 	av_free_packet(&packet);
689 	return B_OK;
690 }
691 
692 
693 status_t
694 AVCodecEncoder::_EncodeVideo(const void* buffer, int64 frameCount,
695 	media_encode_info* info)
696 {
697 	TRACE_IO("AVCodecEncoder::_EncodeVideo(%p, %lld, %p)\n", buffer, frameCount,
698 		info);
699 
700 	if (fChunkBuffer == NULL)
701 		return B_NO_MEMORY;
702 
703 	status_t ret = B_OK;
704 
705 	while (frameCount > 0) {
706 		size_t bpr = fInputFormat.u.raw_video.display.bytes_per_row;
707 		size_t bufferSize = fInputFormat.u.raw_video.display.line_count * bpr;
708 
709 		// We should always get chunky bitmaps, so this code should be safe.
710 		fSrcFrame.data[0] = (uint8_t*)buffer;
711 		fSrcFrame.linesize[0] = bpr;
712 
713 		// Run the pixel format conversion
714 		sws_scale(fSwsContext, fSrcFrame.data, fSrcFrame.linesize, 0,
715 			fInputFormat.u.raw_video.display.line_count, fDstFrame.data,
716 			fDstFrame.linesize);
717 
718 		// Encode one video chunk/frame.
719 #if LIBAVCODEC_VERSION_INT < ((55 << 16) | (45 << 8))
720 		int usedBytes = avcodec_encode_video(fContext, fChunkBuffer,
721 			kDefaultChunkBufferSize, fFrame);
722 #else
723 		int gotPacket;
724 		AVPacket pkt;
725 		pkt.data = NULL;
726 		pkt.size = 0;
727 		av_init_packet(&pkt);
728 		int usedBytes = avcodec_encode_video2(fContext, &pkt, fFrame, &gotPacket);
729 #endif
730 		// avcodec.h says we need to set it.
731 		fFrame->pts++;
732 
733 		if (usedBytes < 0) {
734 			TRACE("  avcodec_encode_video() failed: %d\n", usedBytes);
735 			return B_ERROR;
736 		}
737 
738 #if LIBAVCODEC_VERSION_INT < ((55 << 16) | (45 << 8))
739 		// Maybe we need to use this PTS to calculate start_time:
740 		if (fContext->coded_frame->pts != kNoPTSValue) {
741 			TRACE("  codec frame PTS: %lld (codec time_base: %d/%d)\n",
742 				fContext->coded_frame->pts, fContext->time_base.num,
743 				fContext->time_base.den);
744 		} else {
745 			TRACE("  codec frame PTS: N/A (codec time_base: %d/%d)\n",
746 				fContext->time_base.num, fContext->time_base.den);
747 		}
748 #else
749 		// Maybe we need to use this PTS to calculate start_time:
750 		if (pkt.pts != AV_NOPTS_VALUE) {
751 			TRACE("  codec frame PTS: %lld (codec time_base: %d/%d)\n",
752 				pkt.pts, fContext->time_base.num,
753 				fContext->time_base.den);
754 		} else {
755 			TRACE("  codec frame PTS: N/A (codec time_base: %d/%d)\n",
756 				fContext->time_base.num, fContext->time_base.den);
757 		}
758 #endif
759 
760 		// Setup media_encode_info, most important is the time stamp.
761 		info->start_time = (bigtime_t)(fFramesWritten * 1000000LL
762 			/ fInputFormat.u.raw_video.field_rate);
763 
764 		info->flags = 0;
765 		if (fContext->coded_frame->key_frame)
766 			info->flags |= B_MEDIA_KEY_FRAME;
767 
768 		// Write the chunk
769 #if LIBAVCODEC_VERSION_INT < ((55 << 16) | (45 << 8))
770 		ret = WriteChunk(fChunkBuffer, usedBytes, info);
771 #else
772 		ret = WriteChunk(pkt.data, pkt.size, info);
773 #endif
774 		if (ret != B_OK) {
775 			TRACE("  error writing chunk: %s\n", strerror(ret));
776 			break;
777 		}
778 
779 		// Skip to the next frame (but usually, there is only one to encode
780 		// for video).
781 		frameCount--;
782 		fFramesWritten++;
783 		buffer = (const void*)((const uint8*)buffer + bufferSize);
784 	}
785 
786 	return ret;
787 }
788 
789