2 * Copyright 2009-2010, Stephan Amßus <superstippi@gmx.de>
3 * All rights reserved. Distributed under the terms of the MIT license.
7 #include "AVCodecEncoder.h"
14 #include <Application.h>
21 #include "EncoderTable.h"
26 //#define TRACE_AV_CODEC_ENCODER
27 #ifdef TRACE_AV_CODEC_ENCODER
29 # define TRACE_IO(a...)
32 # define TRACE_IO(a...)
36 static const size_t kDefaultChunkBufferSize
= 2 * 1024 * 1024;
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
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
51 AVCodecEncoder::AVCodecEncoder(uint32 codecID
, int bitRateScale
)
54 fBitRateScale(bitRateScale
),
55 fCodecID((CodecID
)codecID
),
57 fOwnContext(avcodec_alloc_context3(NULL
)),
58 fContext(fOwnContext
),
59 fCodecInitStatus(CODEC_INIT_NEEDED
),
60 fFrame(av_frame_alloc()),
64 TRACE("AVCodecEncoder::AVCodecEncoder()\n");
70 AVCodecEncoder::_Init()
72 fChunkBuffer
= new(std::nothrow
) uint8
[kDefaultChunkBufferSize
];
74 fCodec
= avcodec_find_encoder(fCodecID
);
75 TRACE(" found AVCodec for %u: %p\n", fCodecID
, fCodec
);
78 memset(&fInputFormat
, 0, sizeof(media_format
));
80 fAudioFifo
= av_fifo_alloc(0);
82 fDstFrame
.data
[0] = NULL
;
83 fDstFrame
.data
[1] = NULL
;
84 fDstFrame
.data
[2] = NULL
;
85 fDstFrame
.data
[3] = NULL
;
87 fDstFrame
.linesize
[0] = 0;
88 fDstFrame
.linesize
[1] = 0;
89 fDstFrame
.linesize
[2] = 0;
90 fDstFrame
.linesize
[3] = 0;
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
;
99 AVCodecEncoder::~AVCodecEncoder()
101 TRACE("AVCodecEncoder::~AVCodecEncoder()\n");
103 _CloseCodecIfNeeded();
105 if (fSwsContext
!= NULL
)
106 sws_freeContext(fSwsContext
);
108 av_fifo_free(fAudioFifo
);
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().
114 if (fFrame
!= NULL
) {
115 fFrame
->data
[0] = NULL
;
116 fFrame
->data
[1] = NULL
;
117 fFrame
->data
[2] = NULL
;
118 fFrame
->data
[3] = NULL
;
120 fFrame
->linesize
[0] = 0;
121 fFrame
->linesize
[1] = 0;
122 fFrame
->linesize
[2] = 0;
123 fFrame
->linesize
[3] = 0;
127 av_free(fOwnContext
);
129 delete[] fChunkBuffer
;
134 AVCodecEncoder::AcceptedFormat(const media_format
* proposedInputFormat
,
135 media_format
* _acceptedInputFormat
)
137 TRACE("AVCodecEncoder::AcceptedFormat(%p, %p)\n", proposedInputFormat
,
138 _acceptedInputFormat
);
140 if (proposedInputFormat
== NULL
)
143 if (_acceptedInputFormat
!= NULL
) {
144 memcpy(_acceptedInputFormat
, proposedInputFormat
,
145 sizeof(media_format
));
153 AVCodecEncoder::SetUp(const media_format
* inputFormat
)
155 TRACE("AVCodecEncoder::SetUp()\n");
157 if (fContext
== NULL
)
160 if (inputFormat
== NULL
)
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
);
169 if (fCodec
== NULL
) {
170 TRACE(" encoder not found!\n");
174 _CloseCodecIfNeeded();
176 fInputFormat
= *inputFormat
;
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.
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
;
201 AVCodecEncoder::GetEncodeParameters(encode_parameters
* parameters
) const
203 TRACE("AVCodecEncoder::GetEncodeParameters(%p)\n", parameters
);
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;
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);
226 parameters
->quality
= fEncodeParameters
.quality
;
233 AVCodecEncoder::SetEncodeParameters(encode_parameters
* parameters
)
235 TRACE("AVCodecEncoder::SetEncodeParameters(%p)\n", parameters
);
237 if (fFramesWritten
> 0)
238 return B_NOT_SUPPORTED
;
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
;
247 // TODO: Auto-bit_rate versus user supplied. See above.
248 // int avgBytesPerSecond = 0;
249 // int maxBytesPerSecond = 0;
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);
263 // if (maxBytesPerSecond < avgBytesPerSecond)
264 // maxBytesPerSecond = avgBytesPerSecond;
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;
280 AVCodecEncoder::Encode(const void* buffer
, int64 frameCount
,
281 media_encode_info
* info
)
283 TRACE("AVCodecEncoder::Encode(%p, %lld, %p)\n", buffer
, frameCount
, info
);
285 if (!_OpenCodecIfNeeded())
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
);
301 AVCodecEncoder::_Setup()
303 TRACE("AVCodecEncoder::_Setup\n");
307 if (fInputFormat
.type
== B_MEDIA_RAW_VIDEO
) {
308 TRACE(" B_MEDIA_RAW_VIDEO\n");
310 fContext
->time_base
.den
= (int)fInputFormat
.u
.raw_video
.field_rate
;
311 fContext
->time_base
.num
= 1;
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;
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
];
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;
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);
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;
355 // Allocate space for colorspace converted AVPicture
356 // TODO: Check allocations...
357 avpicture_alloc(&fDstFrame
, fContext
->pix_fmt
, fContext
->width
,
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];
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];
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
);
376 } else if (fInputFormat
.type
== B_MEDIA_RAW_AUDIO
) {
377 TRACE(" B_MEDIA_RAW_AUDIO\n");
379 fContext
->sample_rate
= (int)fInputFormat
.u
.raw_audio
.frame_rate
;
381 fContext
->channels
= fInputFormat
.u
.raw_audio
.channel_count
;
383 rawBitRate
= fContext
->sample_rate
* fContext
->channels
384 * (fInputFormat
.u
.raw_audio
.format
385 & media_raw_audio_format::B_AUDIO_SIZE_MASK
) * 8;
387 switch (fInputFormat
.u
.raw_audio
.format
) {
388 case media_raw_audio_format::B_AUDIO_FLOAT
:
389 fContext
->sample_fmt
= AV_SAMPLE_FMT_FLT
;
391 case media_raw_audio_format::B_AUDIO_DOUBLE
:
392 fContext
->sample_fmt
= AV_SAMPLE_FMT_DBL
;
394 case media_raw_audio_format::B_AUDIO_INT
:
395 fContext
->sample_fmt
= AV_SAMPLE_FMT_S32
;
397 case media_raw_audio_format::B_AUDIO_SHORT
:
398 fContext
->sample_fmt
= AV_SAMPLE_FMT_S16
;
400 case media_raw_audio_format::B_AUDIO_UCHAR
:
401 fContext
->sample_fmt
= AV_SAMPLE_FMT_U8
;
404 case media_raw_audio_format::B_AUDIO_CHAR
:
406 return B_MEDIA_BAD_FORMAT
;
409 if (fInputFormat
.u
.raw_audio
.channel_mask
== 0) {
410 // guess the channel mask...
411 switch (fInputFormat
.u
.raw_audio
.channel_count
) {
414 fContext
->channel_layout
= AV_CH_LAYOUT_STEREO
;
417 fContext
->channel_layout
= AV_CH_LAYOUT_MONO
;
420 fContext
->channel_layout
= AV_CH_LAYOUT_SURROUND
;
423 fContext
->channel_layout
= AV_CH_LAYOUT_QUAD
;
426 fContext
->channel_layout
= AV_CH_LAYOUT_5POINT0
;
429 fContext
->channel_layout
= AV_CH_LAYOUT_5POINT1
;
432 fContext
->channel_layout
= AV_CH_LAYOUT_7POINT1
;
435 fContext
->channel_layout
= AV_CH_LAYOUT_7POINT1_WIDE
;
439 // The bits match 1:1 for media_multi_channels and FFmpeg defines.
440 fContext
->channel_layout
= fInputFormat
.u
.raw_audio
.channel_mask
;
443 TRACE(" UNSUPPORTED MEDIA TYPE!\n");
444 return B_NOT_SUPPORTED
;
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
);
454 fContext
->bit_rate
= wantedBitRate
;
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,
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
];
475 TRACE(" rawBitRate: %d, wantedBitRate: %d (%.1f), "
476 "context bitrate: %d\n", rawBitRate
, wantedBitRate
,
477 fEncodeParameters
.quality
, fContext
->bit_rate
);
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;
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.
498 AVCodecEncoder::_OpenCodecIfNeeded()
500 if (fContext
!= fOwnContext
) {
501 // We are using the AVCodecContext of the AVFormatWriter plugin,
502 // and don't maintain it's open/close state.
506 if (fCodecInitStatus
== CODEC_INIT_DONE
)
509 if (fCodecInitStatus
== CODEC_INIT_FAILED
)
512 fContext
->strict_std_compliance
= -2;
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
;
520 int result
= avcodec_open2(fContext
, fCodec
, NULL
);
522 fCodecInitStatus
= CODEC_INIT_DONE
;
524 fCodecInitStatus
= CODEC_INIT_FAILED
;
526 TRACE(" avcodec_open(%p, %p): %d\n", fContext
, fCodec
, result
);
528 return fCodecInitStatus
== CODEC_INIT_DONE
;
534 AVCodecEncoder::_CloseCodecIfNeeded()
536 if (fContext
!= fOwnContext
) {
537 // See _OpenCodecIfNeeded().
541 if (fCodecInitStatus
== CODEC_INIT_DONE
) {
542 avcodec_close(fContext
);
543 fCodecInitStatus
= CODEC_INIT_NEEDED
;
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.
554 AVCodecEncoder::_EncodeAudio(const void* _buffer
, int64 frameCount
,
555 media_encode_info
* info
)
557 TRACE("AVCodecEncoder::_EncodeAudio(%p, %lld, %p)\n", _buffer
, frameCount
,
560 if (fChunkBuffer
== NULL
)
565 const uint8
* buffer
= reinterpret_cast<const uint8
*>(_buffer
);
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
;
572 size_t bufferSize
= frameCount
* inputFrameSize
;
573 bufferSize
= min_c(bufferSize
, kDefaultChunkBufferSize
);
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");
583 av_fifo_generic_write(fAudioFifo
, const_cast<uint8
*>(buffer
),
586 int frameBytes
= fContext
->frame_size
* inputFrameSize
;
587 uint8
* tempBuffer
= new(std::nothrow
) uint8
[frameBytes
];
588 if (tempBuffer
== NULL
)
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
);
595 ret
= _EncodeAudio(tempBuffer
, frameBytes
, fContext
->frame_size
,
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
,
614 AVCodecEncoder::_EncodeAudio(const uint8
* buffer
, size_t bufferSize
,
615 int64 frameCount
, media_encode_info
* info
)
619 // Encode one audio chunk/frame.
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.
627 // We need to wrap our input data into an AVFrame structure.
632 av_frame_unref(&frame
);
634 frame
.nb_samples
= frameCount
;
636 ret
= avcodec_fill_audio_frame(&frame
, fContext
->channels
,
637 fContext
->sample_fmt
, (const uint8_t *) buffer
, bufferSize
, 1);
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
;
647 ret
= avcodec_encode_audio2(fContext
, &packet
, &frame
, &gotPacket
);
649 // If called with NULL, ask the encoder to flush any buffers it may
651 ret
= avcodec_encode_audio2(fContext
, &packet
, NULL
, &gotPacket
);
654 if (buffer
&& frame
.extended_data
!= frame
.data
)
655 av_freep(&frame
.extended_data
);
658 TRACE(" avcodec_encode_audio() failed: %ld\n", ret
);
662 fFramesWritten
+= frameCount
;
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
);
671 // Setup media_encode_info, most important is the time stamp.
672 info
->start_time
= packet
.pts
;
674 if (packet
.flags
& AV_PKT_FLAG_KEY
)
675 info
->flags
= B_MEDIA_KEY_FRAME
;
679 // We got a packet out of the encoder, write it to the output stream
680 ret
= WriteChunk(packet
.data
, packet
.size
, info
);
682 TRACE(" error writing chunk: %s\n", strerror(ret
));
683 av_free_packet(&packet
);
688 av_free_packet(&packet
);
694 AVCodecEncoder::_EncodeVideo(const void* buffer
, int64 frameCount
,
695 media_encode_info
* info
)
697 TRACE_IO("AVCodecEncoder::_EncodeVideo(%p, %lld, %p)\n", buffer
, frameCount
,
700 if (fChunkBuffer
== NULL
)
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
;
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
;
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
,
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
);
727 av_init_packet(&pkt
);
728 int usedBytes
= avcodec_encode_video2(fContext
, &pkt
, fFrame
, &gotPacket
);
730 // avcodec.h says we need to set it.
734 TRACE(" avcodec_encode_video() failed: %d\n", usedBytes
);
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
);
745 TRACE(" codec frame PTS: N/A (codec time_base: %d/%d)\n",
746 fContext
->time_base
.num
, fContext
->time_base
.den
);
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
);
755 TRACE(" codec frame PTS: N/A (codec time_base: %d/%d)\n",
756 fContext
->time_base
.num
, fContext
->time_base
.den
);
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
);
765 if (fContext
->coded_frame
->key_frame
)
766 info
->flags
|= B_MEDIA_KEY_FRAME
;
769 #if LIBAVCODEC_VERSION_INT < ((55 << 16) | (45 << 8))
770 ret
= WriteChunk(fChunkBuffer
, usedBytes
, info
);
772 ret
= WriteChunk(pkt
.data
, pkt
.size
, info
);
775 TRACE(" error writing chunk: %s\n", strerror(ret
));
779 // Skip to the next frame (but usually, there is only one to encode
783 buffer
= (const void*)((const uint8
*)buffer
+ bufferSize
);