3rdparty/licenseReport: Add seperate LGPL checks
[haiku.git] / src / add-ons / media / plugins / matroska / matroska_reader.cpp
blob2da2060532e7213d56d5cbfd3637156b1af3c98b
1 /*
2 * Copyright (c) 2004, Marcus Overhagen
3 * All rights reserved.
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.
25 #include <stdio.h>
26 #include <string.h>
27 #include <malloc.h>
28 #include <DataIO.h>
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
39 #define TRACE printf
40 #else
41 #define TRACE(a...)
42 #endif
44 #define ERROR(a...) fprintf(stderr, a)
47 enum {
48 TRACK_TYPE_VIDEO = 1,
49 TRACK_TYPE_AUDIO = 2,
50 TRACK_TYPE_TEXT = 17,
54 struct mkv_cookie
56 unsigned stream;
57 char * buffer;
58 unsigned buffer_size;
60 const TrackInfo *track_info;
62 int private_data_size;
63 uint8 * private_data; // reference
65 uint8 * fake_private_data; // created as needed
67 float frame_rate;
68 int64 frame_count;
69 bigtime_t duration;
70 media_format format;
72 MatroskaFile *file;
74 bool audio;
76 // video only:
77 uint32 line_count;
80 static uint8
81 matroska_samplerate_to_samplerateindex(double samplerate)
83 if (samplerate <= 7350.0) {
84 return 12;
85 } else if (samplerate <= 8000.0) {
86 return 11;
87 } else if (samplerate <= 11025.0) {
88 return 10;
89 } else if (samplerate <= 12000.0) {
90 return 9;
91 } else if (samplerate <= 16000.0) {
92 return 8;
93 } else if (samplerate <= 22050.0) {
94 return 7;
95 } else if (samplerate <= 24000.0) {
96 return 6;
97 } else if (samplerate <= 32000.0) {
98 return 5;
99 } else if (samplerate <= 44100.0) {
100 return 4;
101 } else if (samplerate <= 48000.0) {
102 return 3;
103 } else if (samplerate <= 64000.0) {
104 return 2;
105 } else if (samplerate <= 88200.0) {
106 return 1;
107 } else if (samplerate <= 96000.0) {
108 return 0;
111 return 15;
114 mkvReader::mkvReader()
115 : fInputStream(0)
116 , fFile(0)
117 , fFileInfo(0)
119 TRACE("mkvReader::mkvReader\n");
123 mkvReader::~mkvReader()
125 mkv_Close(fFile);
126 free(fInputStream);
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);
135 int profile = 1;
137 if (strstr(track->CodecID,"MAIN")) {
138 profile = 1;
139 } else if (strstr(track->CodecID,"LC")) {
140 profile = 2;
141 } else if (strstr(track->CodecID,"SSR")) {
142 profile = 3;
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);
149 // profile 5 bits
150 // SampleRateIndex 4 bits
151 // Channels 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);
168 return 5;
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;
177 return 8;
178 } else {
179 return 2;
182 return 0;
185 const char *
186 mkvReader::Copyright()
188 return "Matroska reader, " B_UTF8_COPYRIGHT " by Marcus Overhagen\nUsing MatroskaParser " B_UTF8_COPYRIGHT " by Mike Matsnev";
191 status_t
192 mkvReader::Sniff(int32 *streamCount)
194 TRACE("mkvReader::Sniff\n");
196 char err_msg[100];
198 fInputStream = CreateFileCache(Source());
199 if (!fInputStream) {
200 TRACE("mkvReader::Sniff: failed to create file cache\n");
201 return B_ERROR;
204 fFile = mkv_Open(fInputStream, err_msg, sizeof(err_msg));
205 if (!fFile) {
206 TRACE("mkvReader::Sniff: open failed, error: %s\n", err_msg);
207 return B_ERROR;
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);
218 return B_OK;
221 void
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;
229 mff->version = 100;
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");
236 status_t
237 mkvReader::AllocateCookie(int32 streamNumber, void **_cookie)
239 mkv_cookie *cookie = new mkv_cookie;
240 *_cookie = cookie;
242 TRACE("mkvReader::AllocateCookie: stream %ld\n", streamNumber);
244 cookie->stream = streamNumber;
245 cookie->buffer = 0;
246 cookie->buffer_size = 0;
247 cookie->track_info = mkv_GetTrackInfo(fFile, streamNumber);
248 cookie->file = 0;
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);
262 status_t status;
263 switch (cookie->track_info->Type) {
264 case TRACK_TYPE_VIDEO:
265 status = SetupVideoCookie(cookie);
266 break;
267 case TRACK_TYPE_AUDIO:
268 status = SetupAudioCookie(cookie);
269 break;
270 case TRACK_TYPE_TEXT:
271 status = SetupTextCookie(cookie);
272 break;
273 default:
274 TRACE("unknown track type %d\n", cookie->track_info->Type);
275 status = B_ERROR;
276 break;
279 if (status != B_OK)
280 delete cookie;
282 return status;
286 status_t
287 mkvReader::SetupVideoCookie(mkv_cookie *cookie)
289 char err_msg[100];
290 cookie->file = mkv_Open(fInputStream, err_msg, sizeof(err_msg));
291 if (!cookie->file) {
292 TRACE("mkvReader::SetupVideoCookie: open failed, error: %s\n", err_msg);
293 return B_ERROR;
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);
324 status_t res;
325 res = GetVideoFormat(&cookie->format, cookie->track_info->CodecID, cookie->track_info->CodecPrivate, cookie->track_info->CodecPrivateSize);
326 if (res != B_OK) {
327 TRACE("mkvReader::SetupVideoCookie: codec not recognized\n");
328 return B_ERROR;
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;
359 return B_OK;
363 status_t
364 mkvReader::SetupAudioCookie(mkv_cookie *cookie)
366 char err_msg[100];
367 cookie->file = mkv_Open(fInputStream, err_msg, sizeof(err_msg));
368 if (!cookie->file) {
369 TRACE("mkvReader::SetupVideoCookie: open failed, error: %s\n", err_msg);
370 return B_ERROR;
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");
393 return B_ERROR;
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;
416 return B_OK;
420 status_t
421 mkvReader::SetupTextCookie(mkv_cookie *cookie)
423 TRACE("text\n");
424 return B_ERROR;
428 status_t
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;
438 delete cookie;
439 return B_OK;
443 status_t
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;
448 if (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;
455 return B_OK;
459 status_t
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" : "",
470 *time, *frame);
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);
481 } else {
482 mkv_Seek(mkvcookie->file, *time * 1000, 0);
485 int64 timecode;
486 timecode = mkv_GetLowestQTimecode(mkvcookie->file);
487 if (timecode < 0)
488 return B_ERROR;
490 *time = timecode / 1000;
491 *frame = get_frame_count_by_frame_rate(timecode, mkvcookie->frame_rate);
493 return B_OK;
496 status_t
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" : "",
514 *time, *frame);
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);
521 } else {
522 mkv_Seek(mkvcookie->file, *time * 1000, 0);
525 int64 timecode;
526 timecode = mkv_GetLowestQTimecode(mkvcookie->file);
527 if (timecode < 0)
528 return B_ERROR;
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);
536 return B_OK;
539 status_t
540 mkvReader::GetNextChunk(void *_cookie,
541 const void **chunkBuffer, size_t *chunkSize,
542 media_header *mediaHeader)
544 mkv_cookie *cookie = (mkv_cookie *)_cookie;
546 int res;
547 unsigned int track;
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;
554 if (!cookie->file)
555 return B_MEDIA_NO_HANDLER;
557 res = mkv_ReadFrame(cookie->file, 0, &track, &StartTime, &EndTime, &FilePos, &FrameSize, &FrameFlags);
558 if (res < 0)
559 return B_ERROR;
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);
567 if (res > 0)
568 return B_ERROR;
570 *chunkBuffer = cookie->buffer;
571 *chunkSize = FrameSize;
573 bool keyframe = false;
575 if (cookie->audio) {
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;
579 } else {
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;
587 return B_OK;
591 Reader *
592 mkvReaderPlugin::NewReader()
594 return new mkvReader;
598 MediaPlugin *instantiate_plugin()
600 return new mkvReaderPlugin;