1 #include "MediaExtractor.h" 2 #include "PluginManager.h" 3 #include "debug.h" 4 5 #include <Autolock.h> 6 7 #include <stdio.h> 8 #include <string.h> 9 10 11 MediaExtractor::MediaExtractor(BDataIO *source, int32 flags) 12 { 13 CALLED(); 14 fSource = source; 15 fStreamInfo = 0; 16 17 fErr = _CreateReader(&fReader, &fStreamCount, &fMff, source); 18 if (fErr) { 19 fStreamCount = 0; 20 fReader = 0; 21 return; 22 } 23 24 fStreamInfo = new stream_info[fStreamCount]; 25 26 // initialize stream infos 27 for (int32 i = 0; i < fStreamCount; i++) { 28 fStreamInfo[i].status = B_OK; 29 fStreamInfo[i].cookie = 0; 30 fStreamInfo[i].hasCookie = true; 31 fStreamInfo[i].infoBuffer = 0; 32 fStreamInfo[i].infoBufferSize = 0; 33 memset(&fStreamInfo[i].encodedFormat, 0, sizeof(fStreamInfo[i].encodedFormat)); 34 } 35 36 // create all stream cookies 37 for (int32 i = 0; i < fStreamCount; i++) { 38 if (B_OK != fReader->AllocateCookie(i, &fStreamInfo[i].cookie)) { 39 fStreamInfo[i].cookie = 0; 40 fStreamInfo[i].hasCookie = false; 41 fStreamInfo[i].status = B_ERROR; 42 printf("MediaExtractor::MediaExtractor: AllocateCookie for stream %ld failed\n", i); 43 } 44 } 45 46 // get info for all streams 47 for (int32 i = 0; i < fStreamCount; i++) { 48 if (fStreamInfo[i].status != B_OK) 49 continue; 50 int64 frameCount; 51 bigtime_t duration; 52 if (B_OK != fReader->GetStreamInfo(fStreamInfo[i].cookie, &frameCount, &duration, 53 &fStreamInfo[i].encodedFormat, 54 &fStreamInfo[i].infoBuffer, 55 &fStreamInfo[i].infoBufferSize)) { 56 fStreamInfo[i].status = B_ERROR; 57 printf("MediaExtractor::MediaExtractor: GetStreamInfo for stream %ld failed\n", i); 58 } 59 } 60 } 61 62 MediaExtractor::~MediaExtractor() 63 { 64 CALLED(); 65 66 // free all stream cookies 67 for (int32 i = 0; i < fStreamCount; i++) { 68 if (fStreamInfo[i].hasCookie) 69 fReader->FreeCookie(fStreamInfo[i].cookie); 70 } 71 72 if (fReader) 73 _DestroyReader(fReader); 74 75 delete [] fStreamInfo; 76 // fSource is owned by the BMediaFile 77 } 78 79 status_t 80 MediaExtractor::InitCheck() 81 { 82 CALLED(); 83 return fErr; 84 } 85 86 void 87 MediaExtractor::GetFileFormatInfo(media_file_format *mfi) const 88 { 89 CALLED(); 90 *mfi = fMff; 91 } 92 93 int32 94 MediaExtractor::StreamCount() 95 { 96 CALLED(); 97 return fStreamCount; 98 } 99 100 const media_format * 101 MediaExtractor::EncodedFormat(int32 stream) 102 { 103 return &fStreamInfo[stream].encodedFormat; 104 } 105 106 int64 107 MediaExtractor::CountFrames(int32 stream) const 108 { 109 CALLED(); 110 int64 frameCount; 111 bigtime_t duration; 112 media_format format; 113 void *infoBuffer; 114 int32 infoSize; 115 116 fReader->GetStreamInfo(fStreamInfo[stream].cookie, &frameCount, &duration, &format, &infoBuffer, &infoSize); 117 118 return frameCount; 119 } 120 121 bigtime_t 122 MediaExtractor::Duration(int32 stream) const 123 { 124 CALLED(); 125 int64 frameCount; 126 bigtime_t duration; 127 media_format format; 128 void *infoBuffer; 129 int32 infoSize; 130 131 fReader->GetStreamInfo(fStreamInfo[stream].cookie, &frameCount, &duration, &format, &infoBuffer, &infoSize); 132 133 return duration; 134 } 135 136 status_t 137 MediaExtractor::Seek(int32 stream, uint32 seekTo, 138 int64 *frame, bigtime_t *time) 139 { 140 CALLED(); 141 status_t result; 142 result = fReader->Seek(fStreamInfo[stream].cookie, seekTo, frame, time); 143 if (result != B_OK) 144 return result; 145 146 // clear buffered chunks 147 return B_OK; 148 } 149 150 status_t 151 MediaExtractor::GetNextChunk(int32 stream, 152 void **chunkBuffer, int32 *chunkSize, 153 media_header *mediaHeader) 154 { 155 //CALLED(); 156 // get buffered chunk 157 158 // XXX until this is done in a single extractor thread, 159 // XXX make calls to GetNextChunk thread save 160 static BLocker locker; 161 BAutolock lock(locker); 162 163 // XXX this should be done in a different thread, and double buffered for each stream 164 return fReader->GetNextChunk(fStreamInfo[stream].cookie, chunkBuffer, chunkSize, mediaHeader); 165 } 166 167 class MediaExtractorChunkProvider : public ChunkProvider { 168 private: 169 MediaExtractor * fExtractor; 170 int32 fStream; 171 public: 172 MediaExtractorChunkProvider(MediaExtractor * extractor, int32 stream) { 173 fExtractor = extractor; 174 fStream = stream; 175 } 176 virtual status_t GetNextChunk(void **chunkBuffer, int32 *chunkSize, 177 media_header *mediaHeader) { 178 return fExtractor->GetNextChunk(fStream,chunkBuffer,chunkSize,mediaHeader); 179 } 180 }; 181 182 status_t 183 MediaExtractor::CreateDecoder(int32 stream, Decoder **decoder, media_codec_info *mci) 184 { 185 CALLED(); 186 status_t res; 187 188 res = fStreamInfo[stream].status; 189 if (res != B_OK) { 190 printf("MediaExtractor::CreateDecoder can't create decoder for stream %ld\n", stream); 191 return res; 192 } 193 194 res = _CreateDecoder(decoder, fStreamInfo[stream].encodedFormat); 195 if (res != B_OK) { 196 printf("MediaExtractor::CreateDecoder failed for stream %ld\n", stream); 197 return res; 198 } 199 200 (*decoder)->Setup(new MediaExtractorChunkProvider(this, stream)); 201 202 res = (*decoder)->Setup(&fStreamInfo[stream].encodedFormat, fStreamInfo[stream].infoBuffer , fStreamInfo[stream].infoBufferSize); 203 if (res != B_OK) { 204 printf("MediaExtractor::CreateDecoder Setup failed for stream %ld: %ld (%s)\n", 205 stream, res, strerror(res)); 206 return res; 207 } 208 209 (*decoder)->GetCodecInfo(mci); 210 211 return B_OK; 212 } 213 214