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