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