2 * Copyright (c) 2004, Marcus Overhagen
5 * Redistribution and use in source and binary forms, with or without modification,
6 * are permitted provided that the following conditions are met:
8 * * Redistributions of source code must retain the above copyright notice,
9 * this list of conditions and the following disclaimer.
10 * * Redistributions in binary form must reproduce the above copyright notice,
11 * this list of conditions and the following disclaimer in the documentation
12 * and/or other materials provided with the distribution.
14 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
15 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
16 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
17 * IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
18 * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
19 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
20 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
21 * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
22 * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
23 * OF THE POSSIBILITY OF SUCH DAMAGE.
29 #include <ByteOrder.h>
30 #include <InterfaceDefs.h>
31 #include <MediaFormats.h>
32 #include "RawFormats.h"
33 #include "matroska_reader.h"
34 #include "matroska_codecs.h"
35 #include "matroska_util.h"
37 #define TRACE_MKV_READER
38 #ifdef TRACE_MKV_READER
44 #define ERROR(a...) fprintf(stderr, a)
60 const TrackInfo
*track_info
;
62 int private_data_size
;
63 uint8
* private_data
; // reference
65 uint8
* fake_private_data
; // created as needed
81 matroska_samplerate_to_samplerateindex(double samplerate
)
83 if (samplerate
<= 7350.0) {
85 } else if (samplerate
<= 8000.0) {
87 } else if (samplerate
<= 11025.0) {
89 } else if (samplerate
<= 12000.0) {
91 } else if (samplerate
<= 16000.0) {
93 } else if (samplerate
<= 22050.0) {
95 } else if (samplerate
<= 24000.0) {
97 } else if (samplerate
<= 32000.0) {
99 } else if (samplerate
<= 44100.0) {
101 } else if (samplerate
<= 48000.0) {
103 } else if (samplerate
<= 64000.0) {
105 } else if (samplerate
<= 88200.0) {
107 } else if (samplerate
<= 96000.0) {
114 mkvReader::mkvReader()
119 TRACE("mkvReader::mkvReader\n");
123 mkvReader::~mkvReader()
130 mkvReader::CreateFakeAACDecoderConfig(const TrackInfo
*track
, uint8
**fakeExtraData
)
132 // Try to fake up a valid Decoder Config for the AAC decoder to parse
133 TRACE("AAC (%s) requires private data (attempting to fake one)\n",track
->CodecID
);
137 if (strstr(track
->CodecID
,"MAIN")) {
139 } else if (strstr(track
->CodecID
,"LC")) {
141 } else if (strstr(track
->CodecID
,"SSR")) {
145 uint8 sampleRateIndex
= matroska_samplerate_to_samplerateindex(track
->AV
.Audio
.SamplingFreq
);
147 TRACE("Profile %d, SampleRate %f, SampleRateIndex %d\n",profile
, track
->AV
.Audio
.SamplingFreq
, sampleRateIndex
);
150 // SampleRateIndex 4 bits
152 (*fakeExtraData
)[0] = (profile
<< 3) | ((sampleRateIndex
& 0x0E) >> 1);
153 (*fakeExtraData
)[1] = ((sampleRateIndex
& 0x01) << 7) | (track
->AV
.Audio
.Channels
<< 3);
154 if (strstr(track
->CodecID
, "SBR")) {
155 TRACE("Extension SBR Needs more configuration\n");
156 // Sync Extension 0x2b7 11 bits
157 // Extension Audio Object Type 0x5 5 bits
158 // SBR present flag 0x1 1 bit
159 // SampleRateIndex 3 bits
160 // if SampleRateIndex = 15
161 // ExtendedSamplingFrequency 24 bits
163 sampleRateIndex
= matroska_samplerate_to_samplerateindex(track
->AV
.Audio
.OutputSamplingFreq
);
164 (*fakeExtraData
)[2] = 0x56;
165 (*fakeExtraData
)[3] = 0xE5;
166 if (sampleRateIndex
!= 15) {
167 (*fakeExtraData
)[4] = 0x80 | (sampleRateIndex
<< 3);
171 uint32 sampleRate
= uint32(track
->AV
.Audio
.OutputSamplingFreq
);
173 (*fakeExtraData
)[4] = 0x80 | (sampleRateIndex
<< 3) | ((sampleRate
& 0xFFF0 ) >> 4);
174 (*fakeExtraData
)[5] = (sampleRate
& 0x0FFF) << 4;
175 (*fakeExtraData
)[6] = sampleRate
<< 12;
176 (*fakeExtraData
)[7] = sampleRate
<< 20;
186 mkvReader::Copyright()
188 return "Matroska reader, " B_UTF8_COPYRIGHT
" by Marcus Overhagen\nUsing MatroskaParser " B_UTF8_COPYRIGHT
" by Mike Matsnev";
192 mkvReader::Sniff(int32
*streamCount
)
194 TRACE("mkvReader::Sniff\n");
198 fInputStream
= CreateFileCache(Source());
200 TRACE("mkvReader::Sniff: failed to create file cache\n");
204 fFile
= mkv_Open(fInputStream
, err_msg
, sizeof(err_msg
));
206 TRACE("mkvReader::Sniff: open failed, error: %s\n", err_msg
);
210 fFileInfo
= mkv_GetFileInfo(fFile
);
212 *streamCount
= mkv_GetNumTracks(fFile
);
214 TRACE("mkvReader::Sniff: file has %ld streams\n", *streamCount
);
215 TRACE("mkvReader::Sniff: TimecodeScale %Ld\n", fFileInfo
->TimecodeScale
);
216 TRACE("mkvReader::Sniff: Duration %Ld\n", fFileInfo
->Duration
);
222 mkvReader::GetFileFormatInfo(media_file_format
*mff
)
224 mff
->capabilities
= media_file_format::B_READABLE
225 | media_file_format::B_KNOWS_ENCODED_VIDEO
226 | media_file_format::B_KNOWS_ENCODED_AUDIO
227 | media_file_format::B_IMPERFECTLY_SEEKABLE
;
228 mff
->family
= B_MISC_FORMAT_FAMILY
;
230 strcpy(mff
->mime_type
, "video/x-matroska"); // "audio/x-matroska"
231 strcpy(mff
->file_extension
, "mkv");
232 strcpy(mff
->short_name
, "Matroska");
233 strcpy(mff
->pretty_name
, "Matroska file format");
237 mkvReader::AllocateCookie(int32 streamNumber
, void **_cookie
)
239 mkv_cookie
*cookie
= new mkv_cookie
;
242 TRACE("mkvReader::AllocateCookie: stream %ld\n", streamNumber
);
244 cookie
->stream
= streamNumber
;
246 cookie
->buffer_size
= 0;
247 cookie
->track_info
= mkv_GetTrackInfo(fFile
, streamNumber
);
250 // TRACE("Number: %d\n", cookie->track_info->Number);
251 // TRACE("Type: %d\n", cookie->track_info->Type);
252 // TRACE("TrackOverlay: %d\n", cookie->track_info->TrackOverlay);
253 // TRACE("UID: %Ld\n", cookie->track_info->UID);
254 // TRACE("MinCache: %Ld\n", cookie->track_info->MinCache);
255 // TRACE("MaxCache: %Ld\n", cookie->track_info->MaxCache);
256 TRACE("DefaultDuration: %Ld\n", cookie
->track_info
->DefaultDuration
);
257 TRACE("TimecodeScale: %.6f\n", cookie
->track_info
->TimecodeScale
);
258 TRACE("Name: %s\n", cookie
->track_info
->Name
);
259 TRACE("Language: %s\n", cookie
->track_info
->Language
);
260 TRACE("CodecID: %s\n", cookie
->track_info
->CodecID
);
263 switch (cookie
->track_info
->Type
) {
264 case TRACK_TYPE_VIDEO
:
265 status
= SetupVideoCookie(cookie
);
267 case TRACK_TYPE_AUDIO
:
268 status
= SetupAudioCookie(cookie
);
270 case TRACK_TYPE_TEXT
:
271 status
= SetupTextCookie(cookie
);
274 TRACE("unknown track type %d\n", cookie
->track_info
->Type
);
287 mkvReader::SetupVideoCookie(mkv_cookie
*cookie
)
290 cookie
->file
= mkv_Open(fInputStream
, err_msg
, sizeof(err_msg
));
292 TRACE("mkvReader::SetupVideoCookie: open failed, error: %s\n", err_msg
);
295 mkv_SetTrackMask(cookie
->file
, ~(1 << cookie
->stream
));
297 cookie
->audio
= false;
299 TRACE("video StereoMode: %d\n", cookie
->track_info
->AV
.Video
.StereoMode
);
300 TRACE("video DisplayUnit: %d\n", cookie
->track_info
->AV
.Video
.DisplayUnit
);
301 TRACE("video AspectRatioType: %d\n", cookie
->track_info
->AV
.Video
.AspectRatioType
);
302 TRACE("video PixelWidth: %d\n", cookie
->track_info
->AV
.Video
.PixelWidth
);
303 TRACE("video PixelHeight: %d\n", cookie
->track_info
->AV
.Video
.PixelHeight
);
304 TRACE("video DisplayWidth: %d\n", cookie
->track_info
->AV
.Video
.DisplayWidth
);
305 TRACE("video DisplayHeight: %d\n", cookie
->track_info
->AV
.Video
.DisplayHeight
);
306 TRACE("video ColourSpace: %d\n", cookie
->track_info
->AV
.Video
.ColourSpace
);
307 TRACE("video GammaValue: %.4f\n", cookie
->track_info
->AV
.Video
.GammaValue
);
309 TRACE("video Interlaced: %d\n", cookie
->track_info
->AV
.Video
.Interlaced
);
311 cookie
->frame_rate
= get_frame_rate(cookie
->track_info
->DefaultDuration
);
312 cookie
->duration
= get_duration_in_us(fFileInfo
->Duration
);
313 cookie
->frame_count
= get_frame_count_by_default_duration(fFileInfo
->Duration
, cookie
->track_info
->DefaultDuration
);
315 cookie
->line_count
= cookie
->track_info
->AV
.Video
.PixelHeight
;
317 TRACE("mkvReader::Sniff: TimecodeScale %Ld\n", fFileInfo
->TimecodeScale
);
318 TRACE("mkvReader::Sniff: Duration %Ld\n", fFileInfo
->Duration
);
320 TRACE("frame_rate: %.6f\n", cookie
->frame_rate
);
321 TRACE("duration: %Ld (%.6f)\n", cookie
->duration
, cookie
->duration
/ 1E6
);
322 TRACE("frame_count: %Ld\n", cookie
->frame_count
);
325 res
= GetVideoFormat(&cookie
->format
, cookie
->track_info
->CodecID
, cookie
->track_info
->CodecPrivate
, cookie
->track_info
->CodecPrivateSize
);
327 TRACE("mkvReader::SetupVideoCookie: codec not recognized\n");
331 cookie
->private_data
= (uint8
*)cookie
->track_info
->CodecPrivate
;
332 cookie
->private_data_size
= cookie
->track_info
->CodecPrivateSize
;
334 uint16 width_aspect_ratio
;
335 uint16 height_aspect_ratio
;
336 get_pixel_aspect_ratio(&width_aspect_ratio
, &height_aspect_ratio
,
337 cookie
->track_info
->AV
.Video
.PixelWidth
,
338 cookie
->track_info
->AV
.Video
.PixelHeight
,
339 cookie
->track_info
->AV
.Video
.DisplayWidth
,
340 cookie
->track_info
->AV
.Video
.DisplayHeight
);
342 // cookie->format.u.encoded_video.max_bit_rate =
343 // cookie->format.u.encoded_video.avg_bit_rate =
344 cookie
->format
.u
.encoded_video
.output
.field_rate
= cookie
->frame_rate
;
345 cookie
->format
.u
.encoded_video
.output
.interlace
= 1; // 1: progressive
346 cookie
->format
.u
.encoded_video
.output
.first_active
= 0;
347 cookie
->format
.u
.encoded_video
.output
.last_active
= cookie
->line_count
- 1;
348 cookie
->format
.u
.encoded_video
.output
.orientation
= B_VIDEO_TOP_LEFT_RIGHT
;
349 cookie
->format
.u
.encoded_video
.output
.pixel_width_aspect
= width_aspect_ratio
;
350 cookie
->format
.u
.encoded_video
.output
.pixel_height_aspect
= height_aspect_ratio
;
351 // cookie->format.u.encoded_video.output.display.format = 0;
352 cookie
->format
.u
.encoded_video
.output
.display
.line_width
= cookie
->track_info
->AV
.Video
.PixelWidth
;
353 cookie
->format
.u
.encoded_video
.output
.display
.line_count
= cookie
->track_info
->AV
.Video
.PixelHeight
;
354 cookie
->format
.u
.encoded_video
.output
.display
.bytes_per_row
= 0;
355 cookie
->format
.u
.encoded_video
.output
.display
.pixel_offset
= 0;
356 cookie
->format
.u
.encoded_video
.output
.display
.line_offset
= 0;
357 cookie
->format
.u
.encoded_video
.output
.display
.flags
= 0;
364 mkvReader::SetupAudioCookie(mkv_cookie
*cookie
)
367 cookie
->file
= mkv_Open(fInputStream
, err_msg
, sizeof(err_msg
));
369 TRACE("mkvReader::SetupVideoCookie: open failed, error: %s\n", err_msg
);
372 mkv_SetTrackMask(cookie
->file
, ~(1 << cookie
->stream
));
374 cookie
->audio
= true;
376 TRACE("audio SamplingFreq: %.3f\n", cookie
->track_info
->AV
.Audio
.SamplingFreq
);
377 TRACE("audio OutputSamplingFreq: %.3f\n", cookie
->track_info
->AV
.Audio
.OutputSamplingFreq
);
378 TRACE("audio Channels: %d\n", cookie
->track_info
->AV
.Audio
.Channels
);
379 TRACE("audio BitDepth: %d\n", cookie
->track_info
->AV
.Audio
.BitDepth
);
381 TRACE("CodecID: %s\n", cookie
->track_info
->CodecID
);
383 cookie
->frame_rate
= cookie
->track_info
->AV
.Audio
.SamplingFreq
;
384 cookie
->duration
= get_duration_in_us(fFileInfo
->Duration
);
385 cookie
->frame_count
= get_frame_count_by_frame_rate(fFileInfo
->Duration
, cookie
->frame_rate
);
387 TRACE("frame_rate: %.6f\n", cookie
->frame_rate
);
388 TRACE("duration: %Ld (%.6f)\n", cookie
->duration
, cookie
->duration
/ 1E6
);
389 TRACE("frame_count: %Ld\n", cookie
->frame_count
);
391 if (GetAudioFormat(&cookie
->format
, cookie
->track_info
->CodecID
, cookie
->track_info
->CodecPrivate
, cookie
->track_info
->CodecPrivateSize
) != B_OK
) {
392 TRACE("mkvReader::SetupAudioCookie: codec not recognized\n");
396 cookie
->format
.u
.encoded_audio
.output
.frame_rate
= cookie
->frame_rate
;
397 cookie
->format
.u
.encoded_audio
.output
.channel_count
= cookie
->track_info
->AV
.Audio
.Channels
;
398 cookie
->format
.u
.encoded_audio
.bit_rate
= cookie
->track_info
->AV
.Audio
.BitDepth
* cookie
->format
.u
.encoded_audio
.output
.channel_count
* cookie
->frame_rate
;
400 cookie
->private_data
= (uint8
*)cookie
->track_info
->CodecPrivate
;
401 cookie
->private_data_size
= cookie
->track_info
->CodecPrivateSize
;
403 if (IS_CODEC(cookie
->track_info
->CodecID
, "A_AAC")) {
404 if (cookie
->private_data_size
== 0) {
405 // we create our own private data and keep a reference for us to dispose.
406 cookie
->fake_private_data
= new uint8
[8];
407 cookie
->private_data
= cookie
->fake_private_data
;
409 cookie
->private_data_size
= CreateFakeAACDecoderConfig(cookie
->track_info
, &cookie
->private_data
);
412 cookie
->format
.u
.encoded_audio
.output
.format
= media_raw_audio_format::B_AUDIO_SHORT
;
413 cookie
->format
.u
.encoded_audio
.bit_rate
= 64000 * cookie
->format
.u
.encoded_audio
.output
.channel_count
;
421 mkvReader::SetupTextCookie(mkv_cookie
*cookie
)
429 mkvReader::FreeCookie(void *_cookie
)
431 mkv_cookie
*cookie
= (mkv_cookie
*)_cookie
;
433 mkv_Close(cookie
->file
);
435 delete [] cookie
->buffer
;
436 delete [] cookie
->fake_private_data
;
444 mkvReader::GetStreamInfo(void *_cookie
, int64
*frameCount
, bigtime_t
*duration
,
445 media_format
*format
, const void **infoBuffer
, size_t *infoSize
)
447 mkv_cookie
*cookie
= (mkv_cookie
*)_cookie
;
449 *frameCount
= cookie
->frame_count
;
450 *duration
= cookie
->duration
;
451 *format
= cookie
->format
;
452 *infoBuffer
= cookie
->private_data
;
453 *infoSize
= cookie
->private_data_size
;
460 mkvReader::Seek(void *cookie
, uint32 flags
, int64
*frame
, bigtime_t
*time
)
462 // Seek to the specified frame or time
463 mkv_cookie
*mkvcookie
= (mkv_cookie
*)cookie
;
465 TRACE("mkvReader::Seek: seekTo%s%s%s%s, time %Ld, frame %Ld\n",
466 (flags
& B_MEDIA_SEEK_TO_TIME
) ? " B_MEDIA_SEEK_TO_TIME" : "",
467 (flags
& B_MEDIA_SEEK_TO_FRAME
) ? " B_MEDIA_SEEK_TO_FRAME" : "",
468 (flags
& B_MEDIA_SEEK_CLOSEST_FORWARD
) ? " B_MEDIA_SEEK_CLOSEST_FORWARD" : "",
469 (flags
& B_MEDIA_SEEK_CLOSEST_BACKWARD
) ? " B_MEDIA_SEEK_CLOSEST_BACKWARD" : "",
472 if (flags
& B_MEDIA_SEEK_TO_FRAME
) {
473 *time
= bigtime_t(*frame
* (1000000.0 / mkvcookie
->frame_rate
));
476 if (flags
& B_MEDIA_SEEK_CLOSEST_BACKWARD
) {
477 mkv_Seek(mkvcookie
->file
, *time
* 1000, MKVF_SEEK_TO_PREV_KEYFRAME
);
478 } else if (flags
& B_MEDIA_SEEK_CLOSEST_FORWARD
) {
479 mkv_Seek(mkvcookie
->file
, *time
* 1000, 0);
480 mkv_SkipToKeyframe(mkvcookie
->file
);
482 mkv_Seek(mkvcookie
->file
, *time
* 1000, 0);
486 timecode
= mkv_GetLowestQTimecode(mkvcookie
->file
);
490 *time
= timecode
/ 1000;
491 *frame
= get_frame_count_by_frame_rate(timecode
, mkvcookie
->frame_rate
);
497 mkvReader::FindKeyFrame(void* cookie
, uint32 flags
,
498 int64
* frame
, bigtime_t
* time
)
500 // Find the nearest keyframe to the given time or frame.
502 mkv_cookie
*mkvcookie
= (mkv_cookie
*)cookie
;
504 if (flags
& B_MEDIA_SEEK_TO_FRAME
) {
505 // convert frame to time as matroska seeks by time
506 *time
= bigtime_t(*frame
* (1000000.0 / mkvcookie
->frame_rate
));
509 TRACE("mkvReader::FindKeyFrame: seekTo%s%s%s%s, time %Ld, frame %Ld\n",
510 (flags
& B_MEDIA_SEEK_TO_TIME
) ? " B_MEDIA_SEEK_TO_TIME" : "",
511 (flags
& B_MEDIA_SEEK_TO_FRAME
) ? " B_MEDIA_SEEK_TO_FRAME" : "",
512 (flags
& B_MEDIA_SEEK_CLOSEST_FORWARD
) ? " B_MEDIA_SEEK_CLOSEST_FORWARD" : "",
513 (flags
& B_MEDIA_SEEK_CLOSEST_BACKWARD
) ? " B_MEDIA_SEEK_CLOSEST_BACKWARD" : "",
516 if (flags
& B_MEDIA_SEEK_CLOSEST_BACKWARD
) {
517 mkv_Seek(mkvcookie
->file
, *time
* 1000, MKVF_SEEK_TO_PREV_KEYFRAME
);
518 } else if (flags
& B_MEDIA_SEEK_CLOSEST_FORWARD
) {
519 mkv_Seek(mkvcookie
->file
, *time
* 1000, 0);
520 mkv_SkipToKeyframe(mkvcookie
->file
);
522 mkv_Seek(mkvcookie
->file
, *time
* 1000, 0);
526 timecode
= mkv_GetLowestQTimecode(mkvcookie
->file
);
530 // convert time found to frame
531 *time
= timecode
/ 1000;
532 *frame
= get_frame_count_by_frame_rate(timecode
, mkvcookie
->frame_rate
);
534 TRACE("Found keyframe at frame %Ld time %Ld\n",*frame
,*time
);
540 mkvReader::GetNextChunk(void *_cookie
,
541 const void **chunkBuffer
, size_t *chunkSize
,
542 media_header
*mediaHeader
)
544 mkv_cookie
*cookie
= (mkv_cookie
*)_cookie
;
548 ulonglong StartTime
; /* in ns */
549 ulonglong EndTime
; /* in ns */
550 ulonglong FilePos
; /* in bytes from start of file */
551 unsigned int FrameSize
; /* in bytes */
552 unsigned int FrameFlags
;
555 return B_MEDIA_NO_HANDLER
;
557 res
= mkv_ReadFrame(cookie
->file
, 0, &track
, &StartTime
, &EndTime
, &FilePos
, &FrameSize
, &FrameFlags
);
561 if (cookie
->buffer_size
< FrameSize
) {
562 cookie
->buffer
= (char *)realloc(cookie
->buffer
, FrameSize
);
563 cookie
->buffer_size
= FrameSize
;
566 res
= mkv_ReadData(cookie
->file
, FilePos
, cookie
->buffer
, FrameSize
);
570 *chunkBuffer
= cookie
->buffer
;
571 *chunkSize
= FrameSize
;
573 bool keyframe
= false;
576 mediaHeader
->start_time
= StartTime
/ 1000;
577 mediaHeader
->type
= B_MEDIA_ENCODED_AUDIO
;
578 mediaHeader
->u
.encoded_audio
.buffer_flags
= keyframe
? B_MEDIA_KEY_FRAME
: 0;
580 mediaHeader
->start_time
= StartTime
/ 1000;
581 mediaHeader
->type
= B_MEDIA_ENCODED_VIDEO
;
582 mediaHeader
->u
.encoded_video
.field_flags
= keyframe
? B_MEDIA_KEY_FRAME
: 0;
583 mediaHeader
->u
.encoded_video
.first_active_line
= 0;
584 mediaHeader
->u
.encoded_video
.line_count
= cookie
->line_count
;
592 mkvReaderPlugin::NewReader()
594 return new mkvReader
;
598 MediaPlugin
*instantiate_plugin()
600 return new mkvReaderPlugin
;