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