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