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