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
AVCodecEncoder(uint32 codecID,int bitRateScale)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
_Init()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
~AVCodecEncoder()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
AcceptedFormat(const media_format * proposedInputFormat,media_format * _acceptedInputFormat)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
SetUp(const media_format * inputFormat)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
GetEncodeParameters(encode_parameters * parameters) const150 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
SetEncodeParameters(encode_parameters * parameters)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
Encode(const void * buffer,int64 frameCount,media_encode_info * info)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
get_channel_count(AVCodecContext * context)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
set_channel_count(AVCodecContext * context,int count)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
_Setup()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
_OpenCodecIfNeeded()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
_EncodeAudio(const void * _buffer,int64 frameCount,media_encode_info * info)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