1 /* 2 * Copyright 2009-2010, Stephan Aßmus <superstippi@gmx.de> 3 * Copyright 2014, Colin Günther <coling@gmx.de> 4 * All rights reserved. Distributed under the terms of the GNU L-GPL license. 5 */ 6 7 #include "AVFormatReader.h" 8 9 #include <stdio.h> 10 #include <string.h> 11 #include <stdlib.h> 12 13 #include <new> 14 15 #include <AutoDeleter.h> 16 #include <Autolock.h> 17 #include <ByteOrder.h> 18 #include <MediaIO.h> 19 #include <MediaDefs.h> 20 #include <MediaFormats.h> 21 #include <MimeType.h> 22 23 extern "C" { 24 #include "avcodec.h" 25 #include "avformat.h" 26 } 27 28 #include "DemuxerTable.h" 29 #include "gfx_util.h" 30 #include "Utilities.h" 31 32 33 //#define TRACE_AVFORMAT_READER 34 #ifdef TRACE_AVFORMAT_READER 35 # define TRACE printf 36 # define TRACE_IO(a...) 37 # define TRACE_SEEK(a...) printf(a) 38 # define TRACE_FIND(a...) 39 # define TRACE_PACKET(a...) 40 #else 41 # define TRACE(a...) 42 # define TRACE_IO(a...) 43 # define TRACE_SEEK(a...) 44 # define TRACE_FIND(a...) 45 # define TRACE_PACKET(a...) 46 #endif 47 48 #define ERROR(a...) fprintf(stderr, a) 49 50 #if LIBAVCODEC_VERSION_INT < ((54 << 16) | (50 << 8)) 51 #define AV_CODEC_ID_PCM_S16BE CODEC_ID_PCM_S16BE 52 #define AV_CODEC_ID_PCM_S16LE CODEC_ID_PCM_S16LE 53 #define AV_CODEC_ID_PCM_U16BE CODEC_ID_PCM_U16BE 54 #define AV_CODEC_ID_PCM_U16LE CODEC_ID_PCM_U16LE 55 #define AV_CODEC_ID_PCM_S8 CODEC_ID_PCM_S8 56 #define AV_CODEC_ID_PCM_U8 CODEC_ID_PCM_U8 57 #endif 58 59 static const int64 kNoPTSValue = AV_NOPTS_VALUE; 60 61 62 static uint32 63 avformat_to_beos_byte_order(AVSampleFormat format) 64 { 65 // TODO: Huh? 66 return B_MEDIA_HOST_ENDIAN; 67 } 68 69 70 static void 71 avdictionary_to_message(AVDictionary* dictionary, BMessage* message) 72 { 73 if (dictionary == NULL) 74 return; 75 76 AVDictionaryEntry* entry = NULL; 77 while ((entry = av_dict_get(dictionary, "", entry, 78 AV_DICT_IGNORE_SUFFIX))) { 79 // convert entry keys into something more meaningful using the names from 80 // id3v2.c 81 if (strcmp(entry->key, "TALB") == 0 || strcmp(entry->key, "TAL") == 0) 82 message->AddString("album", entry->value); 83 else if (strcmp(entry->key, "TCOM") == 0) 84 message->AddString("composer", entry->value); 85 else if (strcmp(entry->key, "TCON") == 0 || strcmp(entry->key, "TCO") == 0) 86 message->AddString("genre", entry->value); 87 else if (strcmp(entry->key, "TCOP") == 0) 88 message->AddString("copyright", entry->value); 89 else if (strcmp(entry->key, "TDRL") == 0 || strcmp(entry->key, "TDRC") == 0) 90 message->AddString("date", entry->value); 91 else if (strcmp(entry->key, "TENC") == 0 || strcmp(entry->key, "TEN") == 0) 92 message->AddString("encoded_by", entry->value); 93 else if (strcmp(entry->key, "TIT2") == 0 || strcmp(entry->key, "TT2") == 0) 94 message->AddString("title", entry->value); 95 else if (strcmp(entry->key, "TLAN") == 0) 96 message->AddString("language", entry->value); 97 else if (strcmp(entry->key, "TPE1") == 0 || strcmp(entry->key, "TP1") == 0) 98 message->AddString("artist", entry->value); 99 else if (strcmp(entry->key, "TPE2") == 0 || strcmp(entry->key, "TP2") == 0) 100 message->AddString("album_artist", entry->value); 101 else if (strcmp(entry->key, "TPE3") == 0 || strcmp(entry->key, "TP3") == 0) 102 message->AddString("performer", entry->value); 103 else if (strcmp(entry->key, "TPOS") == 0) 104 message->AddString("disc", entry->value); 105 else if (strcmp(entry->key, "TPUB") == 0) 106 message->AddString("publisher", entry->value); 107 else if (strcmp(entry->key, "TRCK") == 0 || strcmp(entry->key, "TRK") == 0) 108 message->AddString("track", entry->value); 109 else if (strcmp(entry->key, "TSOA") == 0) 110 message->AddString("album-sort", entry->value); 111 else if (strcmp(entry->key, "TSOP") == 0) 112 message->AddString("artist-sort", entry->value); 113 else if (strcmp(entry->key, "TSOT") == 0) 114 message->AddString("title-sort", entry->value); 115 else if (strcmp(entry->key, "TSSE") == 0) 116 message->AddString("encoder", entry->value); 117 else if (strcmp(entry->key, "TYER") == 0) 118 message->AddString("year", entry->value); 119 else 120 message->AddString(entry->key, entry->value); 121 } 122 } 123 124 125 // #pragma mark - StreamBase 126 127 128 class StreamBase { 129 public: 130 StreamBase(BMediaIO* source, 131 BLocker* sourceLock, BLocker* streamLock); 132 virtual ~StreamBase(); 133 134 // Init an indivual AVFormatContext 135 status_t Open(); 136 137 // Setup this stream to point to the AVStream at the given streamIndex. 138 virtual status_t Init(int32 streamIndex); 139 140 inline const AVFormatContext* Context() const 141 { return fContext; } 142 int32 Index() const; 143 int32 CountStreams() const; 144 int32 StreamIndexFor(int32 virtualIndex) const; 145 inline int32 VirtualIndex() const 146 { return fVirtualIndex; } 147 148 double FrameRate() const; 149 bigtime_t Duration() const; 150 151 virtual status_t Seek(uint32 flags, int64* frame, 152 bigtime_t* time); 153 154 status_t GetNextChunk(const void** chunkBuffer, 155 size_t* chunkSize, 156 media_header* mediaHeader); 157 158 protected: 159 // I/O hooks for libavformat, cookie will be a Stream instance. 160 // Since multiple StreamCookies use the same BMediaIO source, they 161 // maintain the position individually, and may need to seek the source 162 // if it does not match anymore in _Read(). 163 static int _Read(void* cookie, uint8* buffer, 164 int bufferSize); 165 static off_t _Seek(void* cookie, off_t offset, int whence); 166 167 status_t _NextPacket(bool reuse); 168 169 int64_t _ConvertToStreamTimeBase(bigtime_t time) const; 170 bigtime_t _ConvertFromStreamTimeBase(int64_t time) const; 171 172 protected: 173 BMediaIO* fSource; 174 off_t fPosition; 175 // Since different threads may read from the source, 176 // we need to protect the file position and I/O by a lock. 177 BLocker* fSourceLock; 178 179 BLocker* fStreamLock; 180 181 AVFormatContext* fContext; 182 AVStream* fStream; 183 int32 fVirtualIndex; 184 185 media_format fFormat; 186 187 AVIOContext* fIOContext; 188 189 AVPacket fPacket; 190 bool fReusePacket; 191 192 bool fSeekByBytes; 193 bool fStreamBuildsIndexWhileReading; 194 }; 195 196 197 StreamBase::StreamBase(BMediaIO* source, BLocker* sourceLock, 198 BLocker* streamLock) 199 : 200 fSource(source), 201 fPosition(0), 202 fSourceLock(sourceLock), 203 204 fStreamLock(streamLock), 205 206 fContext(NULL), 207 fStream(NULL), 208 fVirtualIndex(-1), 209 fIOContext(NULL), 210 211 fReusePacket(false), 212 213 fSeekByBytes(false), 214 fStreamBuildsIndexWhileReading(false) 215 { 216 // NOTE: Don't use streamLock here, it may not yet be initialized! 217 218 av_new_packet(&fPacket, 0); 219 memset(&fFormat, 0, sizeof(media_format)); 220 } 221 222 223 StreamBase::~StreamBase() 224 { 225 if (fContext != NULL) 226 avformat_close_input(&fContext); 227 av_free_packet(&fPacket); 228 av_free(fContext); 229 if (fIOContext != NULL) 230 av_free(fIOContext->buffer); 231 av_free(fIOContext); 232 } 233 234 235 status_t 236 StreamBase::Open() 237 { 238 BAutolock _(fStreamLock); 239 240 // Init probing data 241 size_t bufferSize = 32768; 242 uint8* buffer = static_cast<uint8*>(av_malloc(bufferSize)); 243 if (buffer == NULL) 244 return B_NO_MEMORY; 245 246 // First try to identify the file using the MIME database, as ffmpeg 247 // (especially old versions) is not very good at this and relies on us 248 // to give it the file extension as an hint. 249 // For this we need some valid data in the buffer, the first 512 bytes 250 // should do because our MIME sniffing never uses more. 251 const char* extension = NULL; 252 BMessage message; 253 if (fSource->Read(buffer, 512) == 512) { 254 BMimeType type; 255 if (BMimeType::GuessMimeType(buffer, 512, &type) == B_OK) { 256 if (type.GetFileExtensions(&message) == B_OK) { 257 extension = message.FindString("extensions"); 258 } 259 } 260 } 261 262 // If the format is not identified, try Amiga MOD-files, because these do 263 // not currently have a sniffing rule. 264 if (extension == NULL) 265 extension = ".mod"; 266 267 // Allocate I/O context with buffer and hook functions, pass ourself as 268 // cookie. 269 memset(buffer, 0, bufferSize); 270 fIOContext = avio_alloc_context(buffer, bufferSize, 0, this, _Read, 0, 271 _Seek); 272 if (fIOContext == NULL) { 273 TRACE("StreamBase::Open() - avio_alloc_context() failed!\n"); 274 av_free(buffer); 275 return B_ERROR; 276 } 277 278 fContext = avformat_alloc_context(); 279 fContext->pb = fIOContext; 280 281 // Allocate our context and probe the input format 282 if (avformat_open_input(&fContext, extension, NULL, NULL) < 0) { 283 TRACE("StreamBase::Open() - avformat_open_input() failed!\n"); 284 // avformat_open_input() frees the context in case of failure 285 fContext = NULL; 286 av_free(fIOContext); 287 fIOContext = NULL; 288 return B_NOT_SUPPORTED; 289 } 290 291 TRACE("StreamBase::Open() - " 292 "avformat_open_input(): %s\n", fContext->iformat->name); 293 TRACE(" flags:%s%s%s%s%s\n", 294 (fContext->iformat->flags & AVFMT_GLOBALHEADER) ? " AVFMT_GLOBALHEADER" : "", 295 (fContext->iformat->flags & AVFMT_NOTIMESTAMPS) ? " AVFMT_NOTIMESTAMPS" : "", 296 (fContext->iformat->flags & AVFMT_GENERIC_INDEX) ? " AVFMT_GENERIC_INDEX" : "", 297 (fContext->iformat->flags & AVFMT_TS_DISCONT) ? " AVFMT_TS_DISCONT" : "", 298 (fContext->iformat->flags & AVFMT_VARIABLE_FPS) ? " AVFMT_VARIABLE_FPS" : "" 299 ); 300 301 302 // Retrieve stream information 303 if (avformat_find_stream_info(fContext, NULL) < 0) { 304 TRACE("StreamBase::Open() - avformat_find_stream_info() failed!\n"); 305 return B_NOT_SUPPORTED; 306 } 307 308 fSeekByBytes = (fContext->iformat->flags & AVFMT_TS_DISCONT) != 0; 309 fStreamBuildsIndexWhileReading 310 = (fContext->iformat->flags & AVFMT_GENERIC_INDEX) != 0 311 || fSeekByBytes; 312 313 TRACE("StreamBase::Open() - " 314 "av_find_stream_info() success! Seeking by bytes: %d\n", 315 fSeekByBytes); 316 317 return B_OK; 318 } 319 320 321 status_t 322 StreamBase::Init(int32 virtualIndex) 323 { 324 BAutolock _(fStreamLock); 325 326 TRACE("StreamBase::Init(%ld)\n", virtualIndex); 327 328 if (fContext == NULL) 329 return B_NO_INIT; 330 331 int32 streamIndex = StreamIndexFor(virtualIndex); 332 if (streamIndex < 0) { 333 TRACE(" bad stream index!\n"); 334 return B_BAD_INDEX; 335 } 336 337 TRACE(" context stream index: %ld\n", streamIndex); 338 339 // We need to remember the virtual index so that 340 // AVFormatReader::FreeCookie() can clear the correct stream entry. 341 fVirtualIndex = virtualIndex; 342 343 // Make us point to the AVStream at streamIndex 344 fStream = fContext->streams[streamIndex]; 345 346 // NOTE: Discarding other streams works for most, but not all containers, 347 // for example it does not work for the ASF demuxer. Since I don't know what 348 // other demuxer it breaks, let's just keep reading packets for unwanted 349 // streams, it just makes the _GetNextPacket() function slightly less 350 // efficient. 351 // // Discard all other streams 352 // for (unsigned i = 0; i < fContext->nb_streams; i++) { 353 // if (i != (unsigned)streamIndex) 354 // fContext->streams[i]->discard = AVDISCARD_ALL; 355 // } 356 357 return B_OK; 358 } 359 360 361 int32 362 StreamBase::Index() const 363 { 364 if (fStream != NULL) 365 return fStream->index; 366 return -1; 367 } 368 369 370 int32 371 StreamBase::CountStreams() const 372 { 373 // Figure out the stream count. If the context has "AVPrograms", use 374 // the first program (for now). 375 // TODO: To support "programs" properly, the BMediaFile/Track API should 376 // be extended accordingly. I guess programs are like TV channels in the 377 // same satilite transport stream. Maybe call them "TrackGroups". 378 if (fContext->nb_programs > 0) { 379 // See libavformat/utils.c:dump_format() 380 return fContext->programs[0]->nb_stream_indexes; 381 } 382 return fContext->nb_streams; 383 } 384 385 386 int32 387 StreamBase::StreamIndexFor(int32 virtualIndex) const 388 { 389 // NOTE: See CountStreams() 390 if (fContext->nb_programs > 0) { 391 const AVProgram* program = fContext->programs[0]; 392 if (virtualIndex >= 0 393 && virtualIndex < (int32)program->nb_stream_indexes) { 394 return program->stream_index[virtualIndex]; 395 } 396 } else { 397 if (virtualIndex >= 0 && virtualIndex < (int32)fContext->nb_streams) 398 return virtualIndex; 399 } 400 return -1; 401 } 402 403 404 double 405 StreamBase::FrameRate() const 406 { 407 // TODO: Find a way to always calculate a correct frame rate... 408 double frameRate = 1.0; 409 switch (fStream->codec->codec_type) { 410 case AVMEDIA_TYPE_AUDIO: 411 frameRate = (double)fStream->codec->sample_rate; 412 break; 413 case AVMEDIA_TYPE_VIDEO: 414 if (fStream->avg_frame_rate.den && fStream->avg_frame_rate.num) 415 frameRate = av_q2d(fStream->avg_frame_rate); 416 else if (fStream->r_frame_rate.den && fStream->r_frame_rate.num) 417 frameRate = av_q2d(fStream->r_frame_rate); 418 else if (fStream->time_base.den && fStream->time_base.num) 419 frameRate = 1 / av_q2d(fStream->time_base); 420 else if (fStream->codec->time_base.den 421 && fStream->codec->time_base.num) { 422 frameRate = 1 / av_q2d(fStream->codec->time_base); 423 } 424 425 // TODO: Fix up interlaced video for real 426 if (frameRate == 50.0f) 427 frameRate = 25.0f; 428 break; 429 default: 430 break; 431 } 432 if (frameRate <= 0.0) 433 frameRate = 1.0; 434 return frameRate; 435 } 436 437 438 bigtime_t 439 StreamBase::Duration() const 440 { 441 // TODO: This is not working correctly for all stream types... 442 // It seems that the calculations here are correct, because they work 443 // for a couple of streams and are in line with the documentation, but 444 // unfortunately, libavformat itself seems to set the time_base and 445 // duration wrongly sometimes. :-( 446 if ((int64)fStream->duration != kNoPTSValue) 447 return _ConvertFromStreamTimeBase(fStream->duration); 448 else if ((int64)fContext->duration != kNoPTSValue) 449 return (bigtime_t)fContext->duration; 450 451 return 0; 452 } 453 454 455 status_t 456 StreamBase::Seek(uint32 flags, int64* frame, bigtime_t* time) 457 { 458 BAutolock _(fStreamLock); 459 460 if (fContext == NULL || fStream == NULL) 461 return B_NO_INIT; 462 463 TRACE_SEEK("StreamBase::Seek(%ld,%s%s%s%s, %lld, " 464 "%lld)\n", VirtualIndex(), 465 (flags & B_MEDIA_SEEK_TO_FRAME) ? " B_MEDIA_SEEK_TO_FRAME" : "", 466 (flags & B_MEDIA_SEEK_TO_TIME) ? " B_MEDIA_SEEK_TO_TIME" : "", 467 (flags & B_MEDIA_SEEK_CLOSEST_BACKWARD) 468 ? " B_MEDIA_SEEK_CLOSEST_BACKWARD" : "", 469 (flags & B_MEDIA_SEEK_CLOSEST_FORWARD) 470 ? " B_MEDIA_SEEK_CLOSEST_FORWARD" : "", 471 *frame, *time); 472 473 double frameRate = FrameRate(); 474 if ((flags & B_MEDIA_SEEK_TO_FRAME) != 0) { 475 // Seeking is always based on time, initialize it when client seeks 476 // based on frame. 477 *time = (bigtime_t)(*frame * 1000000.0 / frameRate + 0.5); 478 } 479 480 int64_t timeStamp = *time; 481 482 int searchFlags = AVSEEK_FLAG_BACKWARD; 483 if ((flags & B_MEDIA_SEEK_CLOSEST_FORWARD) != 0) 484 searchFlags = 0; 485 486 if (fSeekByBytes) { 487 searchFlags |= AVSEEK_FLAG_BYTE; 488 489 BAutolock _(fSourceLock); 490 int64_t fileSize; 491 492 if (fSource->GetSize(&fileSize) != B_OK) 493 return B_NOT_SUPPORTED; 494 495 int64_t duration = Duration(); 496 if (duration == 0) 497 return B_NOT_SUPPORTED; 498 499 timeStamp = int64_t(fileSize * ((double)timeStamp / duration)); 500 if ((flags & B_MEDIA_SEEK_CLOSEST_BACKWARD) != 0) { 501 timeStamp -= 65536; 502 if (timeStamp < 0) 503 timeStamp = 0; 504 } 505 506 bool seekAgain = true; 507 bool seekForward = true; 508 bigtime_t lastFoundTime = -1; 509 int64_t closestTimeStampBackwards = -1; 510 while (seekAgain) { 511 if (avformat_seek_file(fContext, -1, INT64_MIN, timeStamp, 512 INT64_MAX, searchFlags) < 0) { 513 TRACE(" avformat_seek_file() (by bytes) failed.\n"); 514 return B_ERROR; 515 } 516 seekAgain = false; 517 518 // Our last packet is toast in any case. Read the next one so we 519 // know where we really seeked. 520 fReusePacket = false; 521 if (_NextPacket(true) == B_OK) { 522 while (fPacket.pts == kNoPTSValue) { 523 fReusePacket = false; 524 if (_NextPacket(true) != B_OK) 525 return B_ERROR; 526 } 527 if (fPacket.pos >= 0) 528 timeStamp = fPacket.pos; 529 bigtime_t foundTime 530 = _ConvertFromStreamTimeBase(fPacket.pts); 531 if (foundTime != lastFoundTime) { 532 lastFoundTime = foundTime; 533 if (foundTime > *time) { 534 if (closestTimeStampBackwards >= 0) { 535 timeStamp = closestTimeStampBackwards; 536 seekAgain = true; 537 seekForward = false; 538 continue; 539 } 540 int64_t diff = int64_t(fileSize 541 * ((double)(foundTime - *time) / (2 * duration))); 542 if (diff < 8192) 543 break; 544 timeStamp -= diff; 545 TRACE_SEEK(" need to seek back (%lld) (time: %.2f " 546 "-> %.2f)\n", timeStamp, *time / 1000000.0, 547 foundTime / 1000000.0); 548 if (timeStamp < 0) 549 foundTime = 0; 550 else { 551 seekAgain = true; 552 continue; 553 } 554 } else if (seekForward && foundTime < *time - 100000) { 555 closestTimeStampBackwards = timeStamp; 556 int64_t diff = int64_t(fileSize 557 * ((double)(*time - foundTime) / (2 * duration))); 558 if (diff < 8192) 559 break; 560 timeStamp += diff; 561 TRACE_SEEK(" need to seek forward (%lld) (time: " 562 "%.2f -> %.2f)\n", timeStamp, *time / 1000000.0, 563 foundTime / 1000000.0); 564 if (timeStamp > duration) 565 foundTime = duration; 566 else { 567 seekAgain = true; 568 continue; 569 } 570 } 571 } 572 TRACE_SEEK(" found time: %lld -> %lld (%.2f)\n", *time, 573 foundTime, foundTime / 1000000.0); 574 *time = foundTime; 575 *frame = (uint64)(*time * frameRate / 1000000LL + 0.5); 576 TRACE_SEEK(" seeked frame: %lld\n", *frame); 577 } else { 578 TRACE_SEEK(" _NextPacket() failed!\n"); 579 return B_ERROR; 580 } 581 } 582 } else { 583 // We may not get a PTS from the next packet after seeking, so 584 // we try to get an expected time from the index. 585 int64_t streamTimeStamp = _ConvertToStreamTimeBase(*time); 586 int index = av_index_search_timestamp(fStream, streamTimeStamp, 587 searchFlags); 588 if (index < 0) { 589 TRACE(" av_index_search_timestamp() failed\n"); 590 } else { 591 if (index > 0) { 592 const AVIndexEntry& entry = fStream->index_entries[index]; 593 streamTimeStamp = entry.timestamp; 594 } else { 595 // Some demuxers use the first index entry to store some 596 // other information, like the total playing time for example. 597 // Assume the timeStamp of the first entry is alays 0. 598 // TODO: Handle start-time offset? 599 streamTimeStamp = 0; 600 } 601 bigtime_t foundTime = _ConvertFromStreamTimeBase(streamTimeStamp); 602 bigtime_t timeDiff = foundTime > *time 603 ? foundTime - *time : *time - foundTime; 604 605 if (timeDiff > 1000000 606 && (fStreamBuildsIndexWhileReading 607 || index == fStream->nb_index_entries - 1)) { 608 // If the stream is building the index on the fly while parsing 609 // it, we only have entries in the index for positions already 610 // decoded, i.e. we cannot seek into the future. In that case, 611 // just assume that we can seek where we want and leave 612 // time/frame unmodified. Since successfully seeking one time 613 // will generate index entries for the seeked to position, we 614 // need to remember this in fStreamBuildsIndexWhileReading, 615 // since when seeking back there will be later index entries, 616 // but we still want to ignore the found entry. 617 fStreamBuildsIndexWhileReading = true; 618 TRACE_SEEK(" Not trusting generic index entry. " 619 "(Current count: %d)\n", fStream->nb_index_entries); 620 } else { 621 // If we found a reasonably time, write it into *time. 622 // After seeking, we will try to read the sought time from 623 // the next packet. If the packet has no PTS value, we may 624 // still have a more accurate time from the index lookup. 625 *time = foundTime; 626 } 627 } 628 629 if (avformat_seek_file(fContext, -1, INT64_MIN, timeStamp, INT64_MAX, 630 searchFlags) < 0) { 631 TRACE(" avformat_seek_file() failed.\n"); 632 // Try to fall back to av_seek_frame() 633 timeStamp = _ConvertToStreamTimeBase(timeStamp); 634 if (av_seek_frame(fContext, fStream->index, timeStamp, 635 searchFlags) < 0) { 636 TRACE(" avformat_seek_frame() failed as well.\n"); 637 // Fall back to seeking to the beginning by bytes 638 timeStamp = 0; 639 if (av_seek_frame(fContext, fStream->index, timeStamp, 640 AVSEEK_FLAG_BYTE) < 0) { 641 TRACE(" avformat_seek_frame() by bytes failed as " 642 "well.\n"); 643 // Do not propagate error in any case. We fail if we can't 644 // read another packet. 645 } else 646 *time = 0; 647 } 648 } 649 650 // Our last packet is toast in any case. Read the next one so 651 // we know where we really sought. 652 bigtime_t foundTime = *time; 653 654 fReusePacket = false; 655 if (_NextPacket(true) == B_OK) { 656 if (fPacket.pts != kNoPTSValue) 657 foundTime = _ConvertFromStreamTimeBase(fPacket.pts); 658 else 659 TRACE_SEEK(" no PTS in packet after seeking\n"); 660 } else 661 TRACE_SEEK(" _NextPacket() failed!\n"); 662 663 *time = foundTime; 664 TRACE_SEEK(" sought time: %.2fs\n", *time / 1000000.0); 665 *frame = (uint64)(*time * frameRate / 1000000.0 + 0.5); 666 TRACE_SEEK(" sought frame: %lld\n", *frame); 667 } 668 669 return B_OK; 670 } 671 672 673 status_t 674 StreamBase::GetNextChunk(const void** chunkBuffer, 675 size_t* chunkSize, media_header* mediaHeader) 676 { 677 BAutolock _(fStreamLock); 678 679 TRACE_PACKET("StreamBase::GetNextChunk()\n"); 680 681 // Get the last stream DTS before reading the next packet, since 682 // then it points to that one. 683 int64 lastStreamDTS = fStream->cur_dts; 684 685 status_t ret = _NextPacket(false); 686 if (ret != B_OK) { 687 *chunkBuffer = NULL; 688 *chunkSize = 0; 689 return ret; 690 } 691 692 // NOTE: AVPacket has a field called "convergence_duration", for which 693 // the documentation is quite interesting. It sounds like it could be 694 // used to know the time until the next I-Frame in streams that don't 695 // let you know the position of keyframes in another way (like through 696 // the index). 697 698 // According to libavformat documentation, fPacket is valid until the 699 // next call to av_read_frame(). This is what we want and we can share 700 // the memory with the least overhead. 701 *chunkBuffer = fPacket.data; 702 *chunkSize = fPacket.size; 703 704 if (mediaHeader != NULL) { 705 mediaHeader->type = fFormat.type; 706 mediaHeader->buffer = 0; 707 mediaHeader->destination = -1; 708 mediaHeader->time_source = -1; 709 mediaHeader->size_used = fPacket.size; 710 711 // FFmpeg recommends to use the decoding time stamps as primary source 712 // for presentation time stamps, especially for video formats that are 713 // using frame reordering. More over this way it is ensured that the 714 // returned start times are ordered in a monotonically increasing time 715 // series (even for videos that contain B-frames). 716 // \see http://git.videolan.org/?p=ffmpeg.git;a=blob;f=libavformat/avformat.h;h=1e8a6294890d580cd9ebc684eaf4ce57c8413bd8;hb=9153b33a742c4e2a85ff6230aea0e75f5a8b26c2#l1623 717 bigtime_t presentationTimeStamp; 718 if (fPacket.dts != kNoPTSValue) 719 presentationTimeStamp = fPacket.dts; 720 else if (fPacket.pts != kNoPTSValue) 721 presentationTimeStamp = fPacket.pts; 722 else 723 presentationTimeStamp = lastStreamDTS; 724 725 mediaHeader->start_time = _ConvertFromStreamTimeBase(presentationTimeStamp); 726 mediaHeader->file_pos = fPacket.pos; 727 mediaHeader->data_offset = 0; 728 switch (mediaHeader->type) { 729 case B_MEDIA_RAW_AUDIO: 730 break; 731 case B_MEDIA_ENCODED_AUDIO: 732 mediaHeader->u.encoded_audio.buffer_flags 733 = (fPacket.flags & AV_PKT_FLAG_KEY) ? B_MEDIA_KEY_FRAME : 0; 734 break; 735 case B_MEDIA_RAW_VIDEO: 736 mediaHeader->u.raw_video.line_count 737 = fFormat.u.raw_video.display.line_count; 738 break; 739 case B_MEDIA_ENCODED_VIDEO: 740 mediaHeader->u.encoded_video.field_flags 741 = (fPacket.flags & AV_PKT_FLAG_KEY) ? B_MEDIA_KEY_FRAME : 0; 742 mediaHeader->u.encoded_video.line_count 743 = fFormat.u.encoded_video.output.display.line_count; 744 break; 745 default: 746 break; 747 } 748 } 749 750 // static bigtime_t pts[2]; 751 // static bigtime_t lastPrintTime = system_time(); 752 // static BLocker printLock; 753 // if (fStream->index < 2) { 754 // if (fPacket.pts != kNoPTSValue) 755 // pts[fStream->index] = _ConvertFromStreamTimeBase(fPacket.pts); 756 // printLock.Lock(); 757 // bigtime_t now = system_time(); 758 // if (now - lastPrintTime > 1000000) { 759 // printf("PTS: %.4f/%.4f, diff: %.4f\r", pts[0] / 1000000.0, 760 // pts[1] / 1000000.0, (pts[0] - pts[1]) / 1000000.0); 761 // fflush(stdout); 762 // lastPrintTime = now; 763 // } 764 // printLock.Unlock(); 765 // } 766 767 return B_OK; 768 } 769 770 771 // #pragma mark - 772 773 774 /*static*/ int 775 StreamBase::_Read(void* cookie, uint8* buffer, int bufferSize) 776 { 777 StreamBase* stream = reinterpret_cast<StreamBase*>(cookie); 778 779 BAutolock _(stream->fSourceLock); 780 781 TRACE_IO("StreamBase::_Read(%p, %p, %d) position: %lld\n", 782 cookie, buffer, bufferSize, stream->fPosition); 783 784 if (stream->fPosition != stream->fSource->Position()) { 785 TRACE_IO("StreamBase::_Read fSource position: %lld\n", 786 stream->fSource->Position()); 787 788 off_t position 789 = stream->fSource->Seek(stream->fPosition, SEEK_SET); 790 if (position != stream->fPosition) 791 return -1; 792 } 793 794 ssize_t read = stream->fSource->Read(buffer, bufferSize); 795 if (read > 0) 796 stream->fPosition += read; 797 798 TRACE_IO(" read: %ld\n", read); 799 return (int)read; 800 801 } 802 803 804 /*static*/ off_t 805 StreamBase::_Seek(void* cookie, off_t offset, int whence) 806 { 807 TRACE_IO("StreamBase::_Seek(%p, %lld, %d)\n", 808 cookie, offset, whence); 809 810 StreamBase* stream = reinterpret_cast<StreamBase*>(cookie); 811 812 BAutolock _(stream->fSourceLock); 813 814 // Support for special file size retrieval API without seeking 815 // anywhere: 816 if (whence == AVSEEK_SIZE) { 817 off_t size; 818 if (stream->fSource->GetSize(&size) == B_OK) 819 return size; 820 return -1; 821 } 822 823 // If not requested to seek to an absolute position, we need to 824 // confirm that the stream is currently at the position that we 825 // think it is. 826 if (whence != SEEK_SET 827 && stream->fPosition != stream->fSource->Position()) { 828 off_t position 829 = stream->fSource->Seek(stream->fPosition, SEEK_SET); 830 if (position != stream->fPosition) 831 return -1; 832 } 833 834 off_t position = stream->fSource->Seek(offset, whence); 835 TRACE_IO(" position: %lld\n", position); 836 if (position < 0) 837 return -1; 838 839 stream->fPosition = position; 840 841 return position; 842 } 843 844 845 status_t 846 StreamBase::_NextPacket(bool reuse) 847 { 848 TRACE_PACKET("StreamBase::_NextPacket(%d)\n", reuse); 849 850 if (fReusePacket) { 851 // The last packet was marked for reuse, so we keep using it. 852 TRACE_PACKET(" re-using last packet\n"); 853 fReusePacket = reuse; 854 return B_OK; 855 } 856 857 av_free_packet(&fPacket); 858 859 while (true) { 860 if (av_read_frame(fContext, &fPacket) < 0) { 861 // NOTE: Even though we may get the error for a different stream, 862 // av_read_frame() is not going to be successful from here on, so 863 // it doesn't matter 864 fReusePacket = false; 865 return B_LAST_BUFFER_ERROR; 866 } 867 868 if (fPacket.stream_index == Index()) 869 break; 870 871 // This is a packet from another stream, ignore it. 872 av_free_packet(&fPacket); 873 } 874 875 // Mark this packet with the new reuse flag. 876 fReusePacket = reuse; 877 return B_OK; 878 } 879 880 881 int64_t 882 StreamBase::_ConvertToStreamTimeBase(bigtime_t time) const 883 { 884 int64 timeStamp = int64_t((double)time * fStream->time_base.den 885 / (1000000.0 * fStream->time_base.num) + 0.5); 886 if (fStream->start_time != kNoPTSValue) 887 timeStamp += fStream->start_time; 888 return timeStamp; 889 } 890 891 892 bigtime_t 893 StreamBase::_ConvertFromStreamTimeBase(int64_t time) const 894 { 895 if (fStream->start_time != kNoPTSValue) 896 time -= fStream->start_time; 897 898 return bigtime_t(1000000.0 * time * fStream->time_base.num 899 / fStream->time_base.den + 0.5); 900 } 901 902 903 // #pragma mark - AVFormatReader::Stream 904 905 906 class AVFormatReader::Stream : public StreamBase { 907 public: 908 Stream(BMediaIO* source, 909 BLocker* streamLock); 910 virtual ~Stream(); 911 912 // Setup this stream to point to the AVStream at the given streamIndex. 913 // This will also initialize the media_format. 914 virtual status_t Init(int32 streamIndex); 915 916 status_t GetMetaData(BMessage* data); 917 918 // Support for AVFormatReader 919 status_t GetStreamInfo(int64* frameCount, 920 bigtime_t* duration, media_format* format, 921 const void** infoBuffer, 922 size_t* infoSize) const; 923 924 status_t FindKeyFrame(uint32 flags, int64* frame, 925 bigtime_t* time) const; 926 virtual status_t Seek(uint32 flags, int64* frame, 927 bigtime_t* time); 928 929 private: 930 mutable BLocker fLock; 931 932 struct KeyframeInfo { 933 bigtime_t requestedTime; 934 int64 requestedFrame; 935 bigtime_t reportedTime; 936 int64 reportedFrame; 937 uint32 seekFlags; 938 }; 939 mutable KeyframeInfo fLastReportedKeyframe; 940 mutable StreamBase* fGhostStream; 941 }; 942 943 944 945 AVFormatReader::Stream::Stream(BMediaIO* source, BLocker* streamLock) 946 : 947 StreamBase(source, streamLock, &fLock), 948 fLock("stream lock"), 949 fGhostStream(NULL) 950 { 951 fLastReportedKeyframe.requestedTime = 0; 952 fLastReportedKeyframe.requestedFrame = 0; 953 fLastReportedKeyframe.reportedTime = 0; 954 fLastReportedKeyframe.reportedFrame = 0; 955 } 956 957 958 AVFormatReader::Stream::~Stream() 959 { 960 delete fGhostStream; 961 } 962 963 964 status_t 965 AVFormatReader::Stream::Init(int32 virtualIndex) 966 { 967 TRACE("AVFormatReader::Stream::Init(%ld)\n", virtualIndex); 968 969 status_t ret = StreamBase::Init(virtualIndex); 970 if (ret != B_OK) 971 return ret; 972 973 // Get a pointer to the AVCodecContext for the stream at streamIndex. 974 AVCodecContext* codecContext = fStream->codec; 975 976 #if 0 977 // stippi: Here I was experimenting with the question if some fields of the 978 // AVCodecContext change (or get filled out at all), if the AVCodec is opened. 979 class CodecOpener { 980 public: 981 CodecOpener(AVCodecContext* context) 982 { 983 fCodecContext = context; 984 AVCodec* codec = avcodec_find_decoder(context->codec_id); 985 fCodecOpen = avcodec_open(context, codec) >= 0; 986 if (!fCodecOpen) 987 TRACE(" failed to open the codec!\n"); 988 } 989 ~CodecOpener() 990 { 991 if (fCodecOpen) 992 avcodec_close(fCodecContext); 993 } 994 private: 995 AVCodecContext* fCodecContext; 996 bool fCodecOpen; 997 } codecOpener(codecContext); 998 #endif 999 1000 // initialize the media_format for this stream 1001 media_format* format = &fFormat; 1002 memset(format, 0, sizeof(media_format)); 1003 1004 media_format_description description; 1005 1006 // Set format family and type depending on codec_type of the stream. 1007 switch (codecContext->codec_type) { 1008 case AVMEDIA_TYPE_AUDIO: 1009 if ((codecContext->codec_id >= AV_CODEC_ID_PCM_S16LE) 1010 && (codecContext->codec_id <= AV_CODEC_ID_PCM_U8)) { 1011 TRACE(" raw audio\n"); 1012 format->type = B_MEDIA_RAW_AUDIO; 1013 description.family = B_ANY_FORMAT_FAMILY; 1014 // This will then apparently be handled by the (built into 1015 // BMediaTrack) RawDecoder. 1016 } else { 1017 TRACE(" encoded audio\n"); 1018 format->type = B_MEDIA_ENCODED_AUDIO; 1019 description.family = B_MISC_FORMAT_FAMILY; 1020 description.u.misc.file_format = 'ffmp'; 1021 } 1022 break; 1023 case AVMEDIA_TYPE_VIDEO: 1024 TRACE(" encoded video\n"); 1025 format->type = B_MEDIA_ENCODED_VIDEO; 1026 description.family = B_MISC_FORMAT_FAMILY; 1027 description.u.misc.file_format = 'ffmp'; 1028 break; 1029 default: 1030 TRACE(" unknown type\n"); 1031 format->type = B_MEDIA_UNKNOWN_TYPE; 1032 return B_ERROR; 1033 break; 1034 } 1035 1036 if (format->type == B_MEDIA_RAW_AUDIO) { 1037 // We cannot describe all raw-audio formats, some are unsupported. 1038 switch (codecContext->codec_id) { 1039 case AV_CODEC_ID_PCM_S16LE: 1040 format->u.raw_audio.format 1041 = media_raw_audio_format::B_AUDIO_SHORT; 1042 format->u.raw_audio.byte_order 1043 = B_MEDIA_LITTLE_ENDIAN; 1044 break; 1045 case AV_CODEC_ID_PCM_S16BE: 1046 format->u.raw_audio.format 1047 = media_raw_audio_format::B_AUDIO_SHORT; 1048 format->u.raw_audio.byte_order 1049 = B_MEDIA_BIG_ENDIAN; 1050 break; 1051 case AV_CODEC_ID_PCM_U16LE: 1052 // format->u.raw_audio.format 1053 // = media_raw_audio_format::B_AUDIO_USHORT; 1054 // format->u.raw_audio.byte_order 1055 // = B_MEDIA_LITTLE_ENDIAN; 1056 return B_NOT_SUPPORTED; 1057 break; 1058 case AV_CODEC_ID_PCM_U16BE: 1059 // format->u.raw_audio.format 1060 // = media_raw_audio_format::B_AUDIO_USHORT; 1061 // format->u.raw_audio.byte_order 1062 // = B_MEDIA_BIG_ENDIAN; 1063 return B_NOT_SUPPORTED; 1064 break; 1065 case AV_CODEC_ID_PCM_S8: 1066 format->u.raw_audio.format 1067 = media_raw_audio_format::B_AUDIO_CHAR; 1068 break; 1069 case AV_CODEC_ID_PCM_U8: 1070 format->u.raw_audio.format 1071 = media_raw_audio_format::B_AUDIO_UCHAR; 1072 break; 1073 default: 1074 return B_NOT_SUPPORTED; 1075 break; 1076 } 1077 } else { 1078 if (description.family == B_MISC_FORMAT_FAMILY) 1079 description.u.misc.codec = codecContext->codec_id; 1080 1081 BMediaFormats formats; 1082 status_t status = formats.GetFormatFor(description, format); 1083 if (status < B_OK) 1084 TRACE(" formats.GetFormatFor() error: %s\n", strerror(status)); 1085 1086 format->user_data_type = B_CODEC_TYPE_INFO; 1087 *(uint32*)format->user_data = codecContext->codec_tag; 1088 format->user_data[4] = 0; 1089 } 1090 1091 format->require_flags = 0; 1092 format->deny_flags = B_MEDIA_MAUI_UNDEFINED_FLAGS; 1093 1094 switch (format->type) { 1095 case B_MEDIA_RAW_AUDIO: 1096 format->u.raw_audio.frame_rate = (float)codecContext->sample_rate; 1097 format->u.raw_audio.channel_count = codecContext->channels; 1098 format->u.raw_audio.channel_mask = codecContext->channel_layout; 1099 ConvertAVSampleFormatToRawAudioFormat(codecContext->sample_fmt, 1100 format->u.raw_audio.format); 1101 format->u.raw_audio.buffer_size = 0; 1102 1103 // Read one packet and mark it for later re-use. (So our first 1104 // GetNextChunk() call does not read another packet.) 1105 if (_NextPacket(true) == B_OK) { 1106 TRACE(" successfully determined audio buffer size: %d\n", 1107 fPacket.size); 1108 format->u.raw_audio.buffer_size = fPacket.size; 1109 } 1110 break; 1111 1112 case B_MEDIA_ENCODED_AUDIO: 1113 format->u.encoded_audio.bit_rate = codecContext->bit_rate; 1114 format->u.encoded_audio.frame_size = codecContext->frame_size; 1115 // Fill in some info about possible output format 1116 format->u.encoded_audio.output 1117 = media_multi_audio_format::wildcard; 1118 format->u.encoded_audio.output.frame_rate 1119 = (float)codecContext->sample_rate; 1120 // Channel layout bits match in Be API and FFmpeg. 1121 format->u.encoded_audio.output.channel_count 1122 = codecContext->channels; 1123 format->u.encoded_audio.multi_info.channel_mask 1124 = codecContext->channel_layout; 1125 format->u.encoded_audio.output.byte_order 1126 = avformat_to_beos_byte_order(codecContext->sample_fmt); 1127 ConvertAVSampleFormatToRawAudioFormat(codecContext->sample_fmt, 1128 format->u.encoded_audio.output.format); 1129 if (codecContext->block_align > 0) { 1130 format->u.encoded_audio.output.buffer_size 1131 = codecContext->block_align; 1132 } else { 1133 format->u.encoded_audio.output.buffer_size 1134 = codecContext->frame_size * codecContext->channels 1135 * (format->u.encoded_audio.output.format 1136 & media_raw_audio_format::B_AUDIO_SIZE_MASK); 1137 } 1138 break; 1139 1140 case B_MEDIA_ENCODED_VIDEO: 1141 // TODO: Specifying any of these seems to throw off the format matching 1142 // later on. 1143 // format->u.encoded_video.avg_bit_rate = codecContext->bit_rate; 1144 // format->u.encoded_video.max_bit_rate = codecContext->bit_rate 1145 // + codecContext->bit_rate_tolerance; 1146 1147 // format->u.encoded_video.encoding 1148 // = media_encoded_video_format::B_ANY; 1149 1150 // format->u.encoded_video.frame_size = 1; 1151 // format->u.encoded_video.forward_history = 0; 1152 // format->u.encoded_video.backward_history = 0; 1153 1154 format->u.encoded_video.output.field_rate = FrameRate(); 1155 format->u.encoded_video.output.interlace = 1; 1156 1157 format->u.encoded_video.output.first_active = 0; 1158 format->u.encoded_video.output.last_active 1159 = codecContext->height - 1; 1160 // TODO: Maybe libavformat actually provides that info 1161 // somewhere... 1162 format->u.encoded_video.output.orientation 1163 = B_VIDEO_TOP_LEFT_RIGHT; 1164 1165 ConvertAVCodecContextToVideoAspectWidthAndHeight(*codecContext, 1166 format->u.encoded_video.output.pixel_width_aspect, 1167 format->u.encoded_video.output.pixel_height_aspect); 1168 1169 format->u.encoded_video.output.display.format 1170 = pixfmt_to_colorspace(codecContext->pix_fmt); 1171 format->u.encoded_video.output.display.line_width 1172 = codecContext->width; 1173 format->u.encoded_video.output.display.line_count 1174 = codecContext->height; 1175 TRACE(" width/height: %d/%d\n", codecContext->width, 1176 codecContext->height); 1177 format->u.encoded_video.output.display.bytes_per_row = 0; 1178 format->u.encoded_video.output.display.pixel_offset = 0; 1179 format->u.encoded_video.output.display.line_offset = 0; 1180 format->u.encoded_video.output.display.flags = 0; // TODO 1181 1182 break; 1183 1184 default: 1185 // This is an unknown format to us. 1186 break; 1187 } 1188 1189 // Add the meta data, if any 1190 if (codecContext->extradata_size > 0) { 1191 format->SetMetaData(codecContext->extradata, 1192 codecContext->extradata_size); 1193 TRACE(" extradata: %p\n", format->MetaData()); 1194 } 1195 1196 TRACE(" extradata_size: %d\n", codecContext->extradata_size); 1197 // TRACE(" intra_matrix: %p\n", codecContext->intra_matrix); 1198 // TRACE(" inter_matrix: %p\n", codecContext->inter_matrix); 1199 // TRACE(" get_buffer(): %p\n", codecContext->get_buffer); 1200 // TRACE(" release_buffer(): %p\n", codecContext->release_buffer); 1201 1202 #ifdef TRACE_AVFORMAT_READER 1203 char formatString[512]; 1204 if (string_for_format(*format, formatString, sizeof(formatString))) 1205 TRACE(" format: %s\n", formatString); 1206 1207 uint32 encoding = format->Encoding(); 1208 TRACE(" encoding '%.4s'\n", (char*)&encoding); 1209 #endif 1210 1211 return B_OK; 1212 } 1213 1214 1215 status_t 1216 AVFormatReader::Stream::GetMetaData(BMessage* data) 1217 { 1218 BAutolock _(&fLock); 1219 1220 avdictionary_to_message(fStream->metadata, data); 1221 1222 return B_OK; 1223 } 1224 1225 1226 status_t 1227 AVFormatReader::Stream::GetStreamInfo(int64* frameCount, 1228 bigtime_t* duration, media_format* format, const void** infoBuffer, 1229 size_t* infoSize) const 1230 { 1231 BAutolock _(&fLock); 1232 1233 TRACE("AVFormatReader::Stream::GetStreamInfo(%ld)\n", 1234 VirtualIndex()); 1235 1236 double frameRate = FrameRate(); 1237 TRACE(" frameRate: %.4f\n", frameRate); 1238 1239 #ifdef TRACE_AVFORMAT_READER 1240 if (fStream->start_time != kNoPTSValue) { 1241 bigtime_t startTime = _ConvertFromStreamTimeBase(fStream->start_time); 1242 TRACE(" start_time: %lld or %.5fs\n", startTime, 1243 startTime / 1000000.0); 1244 // TODO: Handle start time in FindKeyFrame() and Seek()?! 1245 } 1246 #endif // TRACE_AVFORMAT_READER 1247 1248 *duration = Duration(); 1249 1250 TRACE(" duration: %lld or %.5fs\n", *duration, *duration / 1000000.0); 1251 1252 #if 0 1253 if (fStream->nb_index_entries > 0) { 1254 TRACE(" dump of index entries:\n"); 1255 int count = 5; 1256 int firstEntriesCount = min_c(fStream->nb_index_entries, count); 1257 int i = 0; 1258 for (; i < firstEntriesCount; i++) { 1259 AVIndexEntry& entry = fStream->index_entries[i]; 1260 bigtime_t timeGlobal = entry.timestamp; 1261 bigtime_t timeNative = _ConvertFromStreamTimeBase(timeGlobal); 1262 TRACE(" [%d] native: %.5fs global: %.5fs\n", i, 1263 timeNative / 1000000.0f, timeGlobal / 1000000.0f); 1264 } 1265 if (fStream->nb_index_entries - count > i) { 1266 i = fStream->nb_index_entries - count; 1267 TRACE(" ...\n"); 1268 for (; i < fStream->nb_index_entries; i++) { 1269 AVIndexEntry& entry = fStream->index_entries[i]; 1270 bigtime_t timeGlobal = entry.timestamp; 1271 bigtime_t timeNative = _ConvertFromStreamTimeBase(timeGlobal); 1272 TRACE(" [%d] native: %.5fs global: %.5fs\n", i, 1273 timeNative / 1000000.0f, timeGlobal / 1000000.0f); 1274 } 1275 } 1276 } 1277 #endif 1278 1279 *frameCount = fStream->nb_frames * fStream->codec->frame_size; 1280 if (*frameCount == 0) { 1281 // Calculate from duration and frame rate 1282 *frameCount = (int64)(*duration * frameRate / 1000000LL); 1283 TRACE(" frameCount calculated: %lld, from context: %lld\n", 1284 *frameCount, fStream->nb_frames); 1285 } else 1286 TRACE(" frameCount: %lld\n", *frameCount); 1287 1288 *format = fFormat; 1289 1290 *infoBuffer = fStream->codec->extradata; 1291 *infoSize = fStream->codec->extradata_size; 1292 1293 return B_OK; 1294 } 1295 1296 1297 status_t 1298 AVFormatReader::Stream::FindKeyFrame(uint32 flags, int64* frame, 1299 bigtime_t* time) const 1300 { 1301 BAutolock _(&fLock); 1302 1303 if (fContext == NULL || fStream == NULL) 1304 return B_NO_INIT; 1305 1306 TRACE_FIND("AVFormatReader::Stream::FindKeyFrame(%ld,%s%s%s%s, " 1307 "%lld, %lld)\n", VirtualIndex(), 1308 (flags & B_MEDIA_SEEK_TO_FRAME) ? " B_MEDIA_SEEK_TO_FRAME" : "", 1309 (flags & B_MEDIA_SEEK_TO_TIME) ? " B_MEDIA_SEEK_TO_TIME" : "", 1310 (flags & B_MEDIA_SEEK_CLOSEST_BACKWARD) 1311 ? " B_MEDIA_SEEK_CLOSEST_BACKWARD" : "", 1312 (flags & B_MEDIA_SEEK_CLOSEST_FORWARD) 1313 ? " B_MEDIA_SEEK_CLOSEST_FORWARD" : "", 1314 *frame, *time); 1315 1316 bool inLastRequestedRange = false; 1317 if ((flags & B_MEDIA_SEEK_TO_FRAME) != 0) { 1318 if (fLastReportedKeyframe.reportedFrame 1319 <= fLastReportedKeyframe.requestedFrame) { 1320 inLastRequestedRange 1321 = *frame >= fLastReportedKeyframe.reportedFrame 1322 && *frame <= fLastReportedKeyframe.requestedFrame; 1323 } else { 1324 inLastRequestedRange 1325 = *frame >= fLastReportedKeyframe.requestedFrame 1326 && *frame <= fLastReportedKeyframe.reportedFrame; 1327 } 1328 } else if ((flags & B_MEDIA_SEEK_TO_FRAME) == 0) { 1329 if (fLastReportedKeyframe.reportedTime 1330 <= fLastReportedKeyframe.requestedTime) { 1331 inLastRequestedRange 1332 = *time >= fLastReportedKeyframe.reportedTime 1333 && *time <= fLastReportedKeyframe.requestedTime; 1334 } else { 1335 inLastRequestedRange 1336 = *time >= fLastReportedKeyframe.requestedTime 1337 && *time <= fLastReportedKeyframe.reportedTime; 1338 } 1339 } 1340 1341 if (inLastRequestedRange) { 1342 *frame = fLastReportedKeyframe.reportedFrame; 1343 *time = fLastReportedKeyframe.reportedTime; 1344 TRACE_FIND(" same as last reported keyframe\n"); 1345 return B_OK; 1346 } 1347 1348 double frameRate = FrameRate(); 1349 if ((flags & B_MEDIA_SEEK_TO_FRAME) != 0) 1350 *time = (bigtime_t)(*frame * 1000000.0 / frameRate + 0.5); 1351 1352 status_t ret; 1353 if (fGhostStream == NULL) { 1354 BAutolock _(fSourceLock); 1355 1356 fGhostStream = new(std::nothrow) StreamBase(fSource, fSourceLock, 1357 &fLock); 1358 if (fGhostStream == NULL) { 1359 TRACE(" failed to allocate ghost stream\n"); 1360 return B_NO_MEMORY; 1361 } 1362 1363 ret = fGhostStream->Open(); 1364 if (ret != B_OK) { 1365 TRACE(" ghost stream failed to open: %s\n", strerror(ret)); 1366 return B_ERROR; 1367 } 1368 1369 ret = fGhostStream->Init(fVirtualIndex); 1370 if (ret != B_OK) { 1371 TRACE(" ghost stream failed to init: %s\n", strerror(ret)); 1372 return B_ERROR; 1373 } 1374 } 1375 fLastReportedKeyframe.requestedFrame = *frame; 1376 fLastReportedKeyframe.requestedTime = *time; 1377 fLastReportedKeyframe.seekFlags = flags; 1378 1379 ret = fGhostStream->Seek(flags, frame, time); 1380 if (ret != B_OK) { 1381 TRACE(" ghost stream failed to seek: %s\n", strerror(ret)); 1382 return B_ERROR; 1383 } 1384 1385 fLastReportedKeyframe.reportedFrame = *frame; 1386 fLastReportedKeyframe.reportedTime = *time; 1387 1388 TRACE_FIND(" found time: %.2fs\n", *time / 1000000.0); 1389 if ((flags & B_MEDIA_SEEK_TO_FRAME) != 0) { 1390 *frame = int64_t(*time * FrameRate() / 1000000.0 + 0.5); 1391 TRACE_FIND(" found frame: %lld\n", *frame); 1392 } 1393 1394 return B_OK; 1395 } 1396 1397 1398 status_t 1399 AVFormatReader::Stream::Seek(uint32 flags, int64* frame, bigtime_t* time) 1400 { 1401 BAutolock _(&fLock); 1402 1403 if (fContext == NULL || fStream == NULL) 1404 return B_NO_INIT; 1405 1406 // Put the old requested values into frame/time, since we already know 1407 // that the sought frame/time will then match the reported values. 1408 // TODO: Will not work if client changes seek flags (from backwards to 1409 // forward or vice versa)!! 1410 bool inLastRequestedRange = false; 1411 if ((flags & B_MEDIA_SEEK_TO_FRAME) != 0) { 1412 if (fLastReportedKeyframe.reportedFrame 1413 <= fLastReportedKeyframe.requestedFrame) { 1414 inLastRequestedRange 1415 = *frame >= fLastReportedKeyframe.reportedFrame 1416 && *frame <= fLastReportedKeyframe.requestedFrame; 1417 } else { 1418 inLastRequestedRange 1419 = *frame >= fLastReportedKeyframe.requestedFrame 1420 && *frame <= fLastReportedKeyframe.reportedFrame; 1421 } 1422 } else if ((flags & B_MEDIA_SEEK_TO_FRAME) == 0) { 1423 if (fLastReportedKeyframe.reportedTime 1424 <= fLastReportedKeyframe.requestedTime) { 1425 inLastRequestedRange 1426 = *time >= fLastReportedKeyframe.reportedTime 1427 && *time <= fLastReportedKeyframe.requestedTime; 1428 } else { 1429 inLastRequestedRange 1430 = *time >= fLastReportedKeyframe.requestedTime 1431 && *time <= fLastReportedKeyframe.reportedTime; 1432 } 1433 } 1434 1435 if (inLastRequestedRange) { 1436 *frame = fLastReportedKeyframe.requestedFrame; 1437 *time = fLastReportedKeyframe.requestedTime; 1438 flags = fLastReportedKeyframe.seekFlags; 1439 } 1440 1441 return StreamBase::Seek(flags, frame, time); 1442 } 1443 1444 1445 // #pragma mark - AVFormatReader 1446 1447 1448 AVFormatReader::AVFormatReader() 1449 : 1450 fCopyright(""), 1451 fStreams(NULL), 1452 fSourceLock("source I/O lock") 1453 { 1454 TRACE("AVFormatReader::AVFormatReader\n"); 1455 } 1456 1457 1458 AVFormatReader::~AVFormatReader() 1459 { 1460 TRACE("AVFormatReader::~AVFormatReader\n"); 1461 if (fStreams != NULL) { 1462 // The client was supposed to call FreeCookie() on all 1463 // allocated streams. Deleting the first stream is always 1464 // prevented, we delete the other ones just in case. 1465 int32 count = fStreams[0]->CountStreams(); 1466 for (int32 i = 0; i < count; i++) 1467 delete fStreams[i]; 1468 delete[] fStreams; 1469 } 1470 } 1471 1472 1473 // #pragma mark - 1474 1475 1476 const char* 1477 AVFormatReader::Copyright() 1478 { 1479 if (fCopyright.Length() <= 0) { 1480 BMessage message; 1481 if (GetMetaData(&message) == B_OK) 1482 message.FindString("copyright", &fCopyright); 1483 } 1484 return fCopyright.String(); 1485 } 1486 1487 1488 status_t 1489 AVFormatReader::Sniff(int32* _streamCount) 1490 { 1491 TRACE("AVFormatReader::Sniff\n"); 1492 1493 BMediaIO* source = dynamic_cast<BMediaIO*>(Source()); 1494 if (source == NULL) { 1495 TRACE(" not a BMediaIO, but we need it to be one.\n"); 1496 return B_NOT_SUPPORTED; 1497 } 1498 1499 Stream* stream = new(std::nothrow) Stream(source, 1500 &fSourceLock); 1501 if (stream == NULL) { 1502 ERROR("AVFormatReader::Sniff() - failed to allocate Stream\n"); 1503 return B_NO_MEMORY; 1504 } 1505 1506 ObjectDeleter<Stream> streamDeleter(stream); 1507 1508 status_t ret = stream->Open(); 1509 if (ret != B_OK) { 1510 TRACE(" failed to detect stream: %s\n", strerror(ret)); 1511 return ret; 1512 } 1513 1514 delete[] fStreams; 1515 fStreams = NULL; 1516 1517 int32 streamCount = stream->CountStreams(); 1518 if (streamCount == 0) { 1519 TRACE(" failed to detect any streams: %s\n", strerror(ret)); 1520 return B_ERROR; 1521 } 1522 1523 fStreams = new(std::nothrow) Stream*[streamCount]; 1524 if (fStreams == NULL) { 1525 ERROR("AVFormatReader::Sniff() - failed to allocate streams\n"); 1526 return B_NO_MEMORY; 1527 } 1528 1529 memset(fStreams, 0, sizeof(Stream*) * streamCount); 1530 fStreams[0] = stream; 1531 streamDeleter.Detach(); 1532 1533 #ifdef TRACE_AVFORMAT_READER 1534 av_dump_format(const_cast<AVFormatContext*>(stream->Context()), 0, "", 0); 1535 #endif 1536 1537 if (_streamCount != NULL) 1538 *_streamCount = streamCount; 1539 1540 return B_OK; 1541 } 1542 1543 1544 void 1545 AVFormatReader::GetFileFormatInfo(media_file_format* mff) 1546 { 1547 TRACE("AVFormatReader::GetFileFormatInfo\n"); 1548 1549 if (fStreams == NULL) 1550 return; 1551 1552 // The first cookie is always there! 1553 const AVFormatContext* context = fStreams[0]->Context(); 1554 1555 if (context == NULL || context->iformat == NULL) { 1556 TRACE(" no AVFormatContext or AVInputFormat!\n"); 1557 return; 1558 } 1559 1560 const media_file_format* format = demuxer_format_for(context->iformat); 1561 1562 mff->capabilities = media_file_format::B_READABLE 1563 | media_file_format::B_KNOWS_ENCODED_VIDEO 1564 | media_file_format::B_KNOWS_ENCODED_AUDIO 1565 | media_file_format::B_IMPERFECTLY_SEEKABLE; 1566 1567 if (format != NULL) { 1568 mff->family = format->family; 1569 } else { 1570 TRACE(" no DemuxerFormat for AVInputFormat!\n"); 1571 mff->family = B_MISC_FORMAT_FAMILY; 1572 } 1573 1574 mff->version = 100; 1575 1576 if (format != NULL) { 1577 strcpy(mff->mime_type, format->mime_type); 1578 } else { 1579 // TODO: Would be nice to be able to provide this from AVInputFormat, 1580 // maybe by extending the FFmpeg code itself (all demuxers). 1581 strcpy(mff->mime_type, ""); 1582 } 1583 1584 if (context->iformat->extensions != NULL) 1585 strcpy(mff->file_extension, context->iformat->extensions); 1586 else { 1587 TRACE(" no file extensions for AVInputFormat.\n"); 1588 strcpy(mff->file_extension, ""); 1589 } 1590 1591 if (context->iformat->name != NULL) 1592 strcpy(mff->short_name, context->iformat->name); 1593 else { 1594 TRACE(" no short name for AVInputFormat.\n"); 1595 strcpy(mff->short_name, ""); 1596 } 1597 1598 if (context->iformat->long_name != NULL) 1599 sprintf(mff->pretty_name, "%s (FFmpeg)", context->iformat->long_name); 1600 else { 1601 if (format != NULL) 1602 sprintf(mff->pretty_name, "%s (FFmpeg)", format->pretty_name); 1603 else 1604 strcpy(mff->pretty_name, "Unknown (FFmpeg)"); 1605 } 1606 } 1607 1608 1609 status_t 1610 AVFormatReader::GetMetaData(BMessage* _data) 1611 { 1612 // The first cookie is always there! 1613 const AVFormatContext* context = fStreams[0]->Context(); 1614 1615 if (context == NULL) 1616 return B_NO_INIT; 1617 1618 avdictionary_to_message(context->metadata, _data); 1619 1620 // Add chapter info 1621 for (unsigned i = 0; i < context->nb_chapters; i++) { 1622 AVChapter* chapter = context->chapters[i]; 1623 BMessage chapterData; 1624 chapterData.AddInt64("start", bigtime_t(1000000.0 1625 * chapter->start * chapter->time_base.num 1626 / chapter->time_base.den + 0.5)); 1627 chapterData.AddInt64("end", bigtime_t(1000000.0 1628 * chapter->end * chapter->time_base.num 1629 / chapter->time_base.den + 0.5)); 1630 1631 avdictionary_to_message(chapter->metadata, &chapterData); 1632 _data->AddMessage("be:chapter", &chapterData); 1633 } 1634 1635 // Add program info 1636 for (unsigned i = 0; i < context->nb_programs; i++) { 1637 BMessage programData; 1638 avdictionary_to_message(context->programs[i]->metadata, &programData); 1639 _data->AddMessage("be:program", &programData); 1640 } 1641 1642 return B_OK; 1643 } 1644 1645 1646 // #pragma mark - 1647 1648 1649 status_t 1650 AVFormatReader::AllocateCookie(int32 streamIndex, void** _cookie) 1651 { 1652 TRACE("AVFormatReader::AllocateCookie(%ld)\n", streamIndex); 1653 1654 BAutolock _(fSourceLock); 1655 1656 if (fStreams == NULL) 1657 return B_NO_INIT; 1658 1659 if (streamIndex < 0 || streamIndex >= fStreams[0]->CountStreams()) 1660 return B_BAD_INDEX; 1661 1662 if (_cookie == NULL) 1663 return B_BAD_VALUE; 1664 1665 Stream* cookie = fStreams[streamIndex]; 1666 if (cookie == NULL) { 1667 // Allocate the cookie 1668 BMediaIO* source = dynamic_cast<BMediaIO*>(Source()); 1669 if (source == NULL) { 1670 TRACE(" not a BMediaIO, but we need it to be one.\n"); 1671 return B_NOT_SUPPORTED; 1672 } 1673 1674 cookie = new(std::nothrow) Stream(source, &fSourceLock); 1675 if (cookie == NULL) { 1676 ERROR("AVFormatReader::Sniff() - failed to allocate " 1677 "Stream\n"); 1678 return B_NO_MEMORY; 1679 } 1680 1681 status_t ret = cookie->Open(); 1682 if (ret != B_OK) { 1683 TRACE(" stream failed to open: %s\n", strerror(ret)); 1684 delete cookie; 1685 return ret; 1686 } 1687 } 1688 1689 status_t ret = cookie->Init(streamIndex); 1690 if (ret != B_OK) { 1691 TRACE(" stream failed to initialize: %s\n", strerror(ret)); 1692 // NOTE: Never delete the first stream! 1693 if (streamIndex != 0) 1694 delete cookie; 1695 return ret; 1696 } 1697 1698 fStreams[streamIndex] = cookie; 1699 *_cookie = cookie; 1700 1701 return B_OK; 1702 } 1703 1704 1705 status_t 1706 AVFormatReader::FreeCookie(void *_cookie) 1707 { 1708 BAutolock _(fSourceLock); 1709 1710 Stream* cookie = reinterpret_cast<Stream*>(_cookie); 1711 1712 // NOTE: Never delete the first cookie! 1713 if (cookie != NULL && cookie->VirtualIndex() != 0) { 1714 if (fStreams != NULL) 1715 fStreams[cookie->VirtualIndex()] = NULL; 1716 delete cookie; 1717 } 1718 1719 return B_OK; 1720 } 1721 1722 1723 // #pragma mark - 1724 1725 1726 status_t 1727 AVFormatReader::GetStreamInfo(void* _cookie, int64* frameCount, 1728 bigtime_t* duration, media_format* format, const void** infoBuffer, 1729 size_t* infoSize) 1730 { 1731 Stream* cookie = reinterpret_cast<Stream*>(_cookie); 1732 return cookie->GetStreamInfo(frameCount, duration, format, infoBuffer, 1733 infoSize); 1734 } 1735 1736 1737 status_t 1738 AVFormatReader::GetStreamMetaData(void* _cookie, BMessage* _data) 1739 { 1740 Stream* cookie = reinterpret_cast<Stream*>(_cookie); 1741 return cookie->GetMetaData(_data); 1742 } 1743 1744 1745 status_t 1746 AVFormatReader::Seek(void* _cookie, uint32 seekTo, int64* frame, 1747 bigtime_t* time) 1748 { 1749 Stream* cookie = reinterpret_cast<Stream*>(_cookie); 1750 return cookie->Seek(seekTo, frame, time); 1751 } 1752 1753 1754 status_t 1755 AVFormatReader::FindKeyFrame(void* _cookie, uint32 flags, int64* frame, 1756 bigtime_t* time) 1757 { 1758 Stream* cookie = reinterpret_cast<Stream*>(_cookie); 1759 return cookie->FindKeyFrame(flags, frame, time); 1760 } 1761 1762 1763 status_t 1764 AVFormatReader::GetNextChunk(void* _cookie, const void** chunkBuffer, 1765 size_t* chunkSize, media_header* mediaHeader) 1766 { 1767 Stream* cookie = reinterpret_cast<Stream*>(_cookie); 1768 return cookie->GetNextChunk(chunkBuffer, chunkSize, mediaHeader); 1769 } 1770