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