1 /* 2 * Copyright 2009-2010, Stephan Amßus <superstippi@gmx.de> 3 * All rights reserved. Distributed under the terms of the MIT license. 4 */ 5 6 7 #include "AVCodecEncoder.h" 8 9 #include <new> 10 11 #include <stdio.h> 12 #include <string.h> 13 14 #include <Application.h> 15 #include <Roster.h> 16 17 extern "C" { 18 #include "rational.h" 19 } 20 21 #include "EncoderTable.h" 22 #include "gfx_util.h" 23 24 25 #undef TRACE 26 //#define TRACE_AV_CODEC_ENCODER 27 #ifdef TRACE_AV_CODEC_ENCODER 28 # define TRACE printf 29 # define TRACE_IO(a...) 30 #else 31 # define TRACE(a...) 32 # define TRACE_IO(a...) 33 #endif 34 35 36 static const size_t kDefaultChunkBufferSize = 2 * 1024 * 1024; 37 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 43 #endif 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 48 #endif 49 50 51 AVCodecEncoder::AVCodecEncoder(uint32 codecID, int bitRateScale) 52 : 53 Encoder(), 54 fBitRateScale(bitRateScale), 55 fCodecID((CodecID)codecID), 56 fCodec(NULL), 57 fOwnContext(avcodec_alloc_context3(NULL)), 58 fContext(fOwnContext), 59 fCodecInitStatus(CODEC_INIT_NEEDED), 60 fFrame(av_frame_alloc()), 61 fSwsContext(NULL), 62 fFramesWritten(0) 63 { 64 TRACE("AVCodecEncoder::AVCodecEncoder()\n"); 65 _Init(); 66 } 67 68 69 void 70 AVCodecEncoder::_Init() 71 { 72 fChunkBuffer = new(std::nothrow) uint8[kDefaultChunkBufferSize]; 73 if (fCodecID > 0) { 74 fCodec = avcodec_find_encoder(fCodecID); 75 TRACE(" found AVCodec for %u: %p\n", fCodecID, fCodec); 76 } 77 78 memset(&fInputFormat, 0, sizeof(media_format)); 79 80 fAudioFifo = av_fifo_alloc(0); 81 82 fDstFrame.data[0] = NULL; 83 fDstFrame.data[1] = NULL; 84 fDstFrame.data[2] = NULL; 85 fDstFrame.data[3] = NULL; 86 87 fDstFrame.linesize[0] = 0; 88 fDstFrame.linesize[1] = 0; 89 fDstFrame.linesize[2] = 0; 90 fDstFrame.linesize[3] = 0; 91 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; 96 } 97 98 99 AVCodecEncoder::~AVCodecEncoder() 100 { 101 TRACE("AVCodecEncoder::~AVCodecEncoder()\n"); 102 103 _CloseCodecIfNeeded(); 104 105 if (fSwsContext != NULL) 106 sws_freeContext(fSwsContext); 107 108 av_fifo_free(fAudioFifo); 109 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(). 113 114 if (fFrame != NULL) { 115 fFrame->data[0] = NULL; 116 fFrame->data[1] = NULL; 117 fFrame->data[2] = NULL; 118 fFrame->data[3] = NULL; 119 120 fFrame->linesize[0] = 0; 121 fFrame->linesize[1] = 0; 122 fFrame->linesize[2] = 0; 123 fFrame->linesize[3] = 0; 124 av_free(fFrame); 125 } 126 127 av_free(fOwnContext); 128 129 delete[] fChunkBuffer; 130 } 131 132 133 status_t 134 AVCodecEncoder::AcceptedFormat(const media_format* proposedInputFormat, 135 media_format* _acceptedInputFormat) 136 { 137 TRACE("AVCodecEncoder::AcceptedFormat(%p, %p)\n", proposedInputFormat, 138 _acceptedInputFormat); 139 140 if (proposedInputFormat == NULL) 141 return B_BAD_VALUE; 142 143 if (_acceptedInputFormat != NULL) { 144 memcpy(_acceptedInputFormat, proposedInputFormat, 145 sizeof(media_format)); 146 } 147 148 return B_OK; 149 } 150 151 152 status_t 153 AVCodecEncoder::SetUp(const media_format* inputFormat) 154 { 155 TRACE("AVCodecEncoder::SetUp()\n"); 156 157 if (fContext == NULL) 158 return B_NO_INIT; 159 160 if (inputFormat == NULL) 161 return B_BAD_VALUE; 162 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); 168 } 169 if (fCodec == NULL) { 170 TRACE(" encoder not found!\n"); 171 return B_NO_INIT; 172 } 173 174 _CloseCodecIfNeeded(); 175 176 fInputFormat = *inputFormat; 177 fFramesWritten = 0; 178 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. 186 app_info appInfo; 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; 193 } 194 } 195 196 return _Setup(); 197 } 198 199 200 status_t 201 AVCodecEncoder::GetEncodeParameters(encode_parameters* parameters) const 202 { 203 TRACE("AVCodecEncoder::GetEncodeParameters(%p)\n", parameters); 204 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; 213 // 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); 224 // } 225 226 parameters->quality = fEncodeParameters.quality; 227 228 return B_OK; 229 } 230 231 232 status_t 233 AVCodecEncoder::SetEncodeParameters(encode_parameters* parameters) 234 { 235 TRACE("AVCodecEncoder::SetEncodeParameters(%p)\n", parameters); 236 237 if (fFramesWritten > 0) 238 return B_NOT_SUPPORTED; 239 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; 245 } 246 247 // TODO: Auto-bit_rate versus user supplied. See above. 248 // int avgBytesPerSecond = 0; 249 // int maxBytesPerSecond = 0; 250 // 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); 261 // } 262 // 263 // if (maxBytesPerSecond < avgBytesPerSecond) 264 // maxBytesPerSecond = avgBytesPerSecond; 265 // 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; 273 // } 274 275 return _Setup(); 276 } 277 278 279 status_t 280 AVCodecEncoder::Encode(const void* buffer, int64 frameCount, 281 media_encode_info* info) 282 { 283 TRACE("AVCodecEncoder::Encode(%p, %lld, %p)\n", buffer, frameCount, info); 284 285 if (!_OpenCodecIfNeeded()) 286 return B_NO_INIT; 287 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); 292 else 293 return B_NO_INIT; 294 } 295 296 297 // #pragma mark - 298 299 300 status_t 301 AVCodecEncoder::_Setup() 302 { 303 TRACE("AVCodecEncoder::_Setup\n"); 304 305 int rawBitRate; 306 307 if (fInputFormat.type == B_MEDIA_RAW_VIDEO) { 308 TRACE(" B_MEDIA_RAW_VIDEO\n"); 309 // frame rate 310 fContext->time_base.den = (int)fInputFormat.u.raw_video.field_rate; 311 fContext->time_base.num = 1; 312 // video size 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; 316 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]; 323 } 324 } 325 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; 334 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); 345 } 346 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; 351 } 352 353 fFrame->pts = 0; 354 355 // Allocate space for colorspace converted AVPicture 356 // TODO: Check allocations... 357 avpicture_alloc(&fDstFrame, fContext->pix_fmt, fContext->width, 358 fContext->height); 359 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]; 365 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]; 370 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); 375 376 } else if (fInputFormat.type == B_MEDIA_RAW_AUDIO) { 377 TRACE(" B_MEDIA_RAW_AUDIO\n"); 378 // frame rate 379 fContext->sample_rate = (int)fInputFormat.u.raw_audio.frame_rate; 380 // channels 381 fContext->channels = fInputFormat.u.raw_audio.channel_count; 382 // raw bitrate 383 rawBitRate = fContext->sample_rate * fContext->channels 384 * (fInputFormat.u.raw_audio.format 385 & media_raw_audio_format::B_AUDIO_SIZE_MASK) * 8; 386 // sample format 387 switch (fInputFormat.u.raw_audio.format) { 388 case media_raw_audio_format::B_AUDIO_FLOAT: 389 fContext->sample_fmt = AV_SAMPLE_FMT_FLT; 390 break; 391 case media_raw_audio_format::B_AUDIO_DOUBLE: 392 fContext->sample_fmt = AV_SAMPLE_FMT_DBL; 393 break; 394 case media_raw_audio_format::B_AUDIO_INT: 395 fContext->sample_fmt = AV_SAMPLE_FMT_S32; 396 break; 397 case media_raw_audio_format::B_AUDIO_SHORT: 398 fContext->sample_fmt = AV_SAMPLE_FMT_S16; 399 break; 400 case media_raw_audio_format::B_AUDIO_UCHAR: 401 fContext->sample_fmt = AV_SAMPLE_FMT_U8; 402 break; 403 404 case media_raw_audio_format::B_AUDIO_CHAR: 405 default: 406 return B_MEDIA_BAD_FORMAT; 407 break; 408 } 409 if (fInputFormat.u.raw_audio.channel_mask == 0) { 410 // guess the channel mask... 411 switch (fInputFormat.u.raw_audio.channel_count) { 412 default: 413 case 2: 414 fContext->channel_layout = AV_CH_LAYOUT_STEREO; 415 break; 416 case 1: 417 fContext->channel_layout = AV_CH_LAYOUT_MONO; 418 break; 419 case 3: 420 fContext->channel_layout = AV_CH_LAYOUT_SURROUND; 421 break; 422 case 4: 423 fContext->channel_layout = AV_CH_LAYOUT_QUAD; 424 break; 425 case 5: 426 fContext->channel_layout = AV_CH_LAYOUT_5POINT0; 427 break; 428 case 6: 429 fContext->channel_layout = AV_CH_LAYOUT_5POINT1; 430 break; 431 case 8: 432 fContext->channel_layout = AV_CH_LAYOUT_7POINT1; 433 break; 434 case 10: 435 fContext->channel_layout = AV_CH_LAYOUT_7POINT1_WIDE; 436 break; 437 } 438 } else { 439 // The bits match 1:1 for media_multi_channels and FFmpeg defines. 440 fContext->channel_layout = fInputFormat.u.raw_audio.channel_mask; 441 } 442 } else { 443 TRACE(" UNSUPPORTED MEDIA TYPE!\n"); 444 return B_NOT_SUPPORTED; 445 } 446 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); 453 454 fContext->bit_rate = wantedBitRate; 455 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, 462 576000, 640000 463 }; 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]; 469 diff = currentDiff; 470 } else 471 break; 472 } 473 } 474 475 TRACE(" rawBitRate: %d, wantedBitRate: %d (%.1f), " 476 "context bitrate: %d\n", rawBitRate, wantedBitRate, 477 fEncodeParameters.quality, fContext->bit_rate); 478 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; 488 } 489 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. 493 return B_OK; 494 } 495 496 497 bool 498 AVCodecEncoder::_OpenCodecIfNeeded() 499 { 500 if (fContext != fOwnContext) { 501 // We are using the AVCodecContext of the AVFormatWriter plugin, 502 // and don't maintain it's open/close state. 503 return true; 504 } 505 506 if (fCodecInitStatus == CODEC_INIT_DONE) 507 return true; 508 509 if (fCodecInitStatus == CODEC_INIT_FAILED) 510 return false; 511 512 fContext->strict_std_compliance = -2; 513 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; 518 519 // Open the codec 520 int result = avcodec_open2(fContext, fCodec, NULL); 521 if (result >= 0) 522 fCodecInitStatus = CODEC_INIT_DONE; 523 else 524 fCodecInitStatus = CODEC_INIT_FAILED; 525 526 TRACE(" avcodec_open(%p, %p): %d\n", fContext, fCodec, result); 527 528 return fCodecInitStatus == CODEC_INIT_DONE; 529 530 } 531 532 533 void 534 AVCodecEncoder::_CloseCodecIfNeeded() 535 { 536 if (fContext != fOwnContext) { 537 // See _OpenCodecIfNeeded(). 538 return; 539 } 540 541 if (fCodecInitStatus == CODEC_INIT_DONE) { 542 avcodec_close(fContext); 543 fCodecInitStatus = CODEC_INIT_NEEDED; 544 } 545 } 546 547 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. 552 553 status_t 554 AVCodecEncoder::_EncodeAudio(const void* _buffer, int64 frameCount, 555 media_encode_info* info) 556 { 557 TRACE("AVCodecEncoder::_EncodeAudio(%p, %lld, %p)\n", _buffer, frameCount, 558 info); 559 560 if (fChunkBuffer == NULL) 561 return B_NO_MEMORY; 562 563 status_t ret = B_OK; 564 565 const uint8* buffer = reinterpret_cast<const uint8*>(_buffer); 566 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; 571 572 size_t bufferSize = frameCount * inputFrameSize; 573 bufferSize = min_c(bufferSize, kDefaultChunkBufferSize); 574 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"); 581 return B_NO_MEMORY; 582 } 583 av_fifo_generic_write(fAudioFifo, const_cast<uint8*>(buffer), 584 bufferSize, NULL); 585 586 int frameBytes = fContext->frame_size * inputFrameSize; 587 uint8* tempBuffer = new(std::nothrow) uint8[frameBytes]; 588 if (tempBuffer == NULL) 589 return B_NO_MEMORY; 590 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); 594 595 ret = _EncodeAudio(tempBuffer, frameBytes, fContext->frame_size, 596 info); 597 if (ret != B_OK) 598 break; 599 } 600 601 delete[] tempBuffer; 602 } else { 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, 606 info); 607 } 608 609 return ret; 610 } 611 612 613 status_t 614 AVCodecEncoder::_EncodeAudio(const uint8* buffer, size_t bufferSize, 615 int64 frameCount, media_encode_info* info) 616 { 617 status_t ret; 618 619 // Encode one audio chunk/frame. 620 AVPacket packet; 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. 624 packet.data = NULL; 625 packet.size = 0; 626 627 // We need to wrap our input data into an AVFrame structure. 628 AVFrame frame; 629 int gotPacket = 0; 630 631 if (buffer) { 632 av_frame_unref(&frame); 633 634 frame.nb_samples = frameCount; 635 636 ret = avcodec_fill_audio_frame(&frame, fContext->channels, 637 fContext->sample_fmt, (const uint8_t *) buffer, bufferSize, 1); 638 639 if (ret != 0) 640 return B_ERROR; 641 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; 646 647 ret = avcodec_encode_audio2(fContext, &packet, &frame, &gotPacket); 648 } else { 649 // If called with NULL, ask the encoder to flush any buffers it may 650 // have pending. 651 ret = avcodec_encode_audio2(fContext, &packet, NULL, &gotPacket); 652 } 653 654 if (buffer && frame.extended_data != frame.data) 655 av_freep(&frame.extended_data); 656 657 if (ret != 0) { 658 TRACE(" avcodec_encode_audio() failed: %ld\n", ret); 659 return B_ERROR; 660 } 661 662 fFramesWritten += frameCount; 663 664 if (gotPacket) { 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); 669 } 670 671 // Setup media_encode_info, most important is the time stamp. 672 info->start_time = packet.pts; 673 674 if (packet.flags & AV_PKT_FLAG_KEY) 675 info->flags = B_MEDIA_KEY_FRAME; 676 else 677 info->flags = 0; 678 679 // We got a packet out of the encoder, write it to the output stream 680 ret = WriteChunk(packet.data, packet.size, info); 681 if (ret != B_OK) { 682 TRACE(" error writing chunk: %s\n", strerror(ret)); 683 av_free_packet(&packet); 684 return ret; 685 } 686 } 687 688 av_free_packet(&packet); 689 return B_OK; 690 } 691 692 693 status_t 694 AVCodecEncoder::_EncodeVideo(const void* buffer, int64 frameCount, 695 media_encode_info* info) 696 { 697 TRACE_IO("AVCodecEncoder::_EncodeVideo(%p, %lld, %p)\n", buffer, frameCount, 698 info); 699 700 if (fChunkBuffer == NULL) 701 return B_NO_MEMORY; 702 703 status_t ret = B_OK; 704 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; 708 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; 712 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, 716 fDstFrame.linesize); 717 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); 722 #else 723 int gotPacket; 724 AVPacket pkt; 725 pkt.data = NULL; 726 pkt.size = 0; 727 av_init_packet(&pkt); 728 int usedBytes = avcodec_encode_video2(fContext, &pkt, fFrame, &gotPacket); 729 #endif 730 // avcodec.h says we need to set it. 731 fFrame->pts++; 732 733 if (usedBytes < 0) { 734 TRACE(" avcodec_encode_video() failed: %d\n", usedBytes); 735 return B_ERROR; 736 } 737 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); 744 } else { 745 TRACE(" codec frame PTS: N/A (codec time_base: %d/%d)\n", 746 fContext->time_base.num, fContext->time_base.den); 747 } 748 #else 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); 754 } else { 755 TRACE(" codec frame PTS: N/A (codec time_base: %d/%d)\n", 756 fContext->time_base.num, fContext->time_base.den); 757 } 758 #endif 759 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); 763 764 info->flags = 0; 765 if (fContext->coded_frame->key_frame) 766 info->flags |= B_MEDIA_KEY_FRAME; 767 768 // Write the chunk 769 #if LIBAVCODEC_VERSION_INT < ((55 << 16) | (45 << 8)) 770 ret = WriteChunk(fChunkBuffer, usedBytes, info); 771 #else 772 ret = WriteChunk(pkt.data, pkt.size, info); 773 #endif 774 if (ret != B_OK) { 775 TRACE(" error writing chunk: %s\n", strerror(ret)); 776 break; 777 } 778 779 // Skip to the next frame (but usually, there is only one to encode 780 // for video). 781 frameCount--; 782 fFramesWritten++; 783 buffer = (const void*)((const uint8*)buffer + bufferSize); 784 } 785 786 return ret; 787 } 788 789