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