Bring matroska library up to latest version. Allows V2 matroska file playback

git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@30943 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
David McPaul
2009-06-02 09:34:16 +00:00
parent 938fd5a7e0
commit 4cf2271b57
6 changed files with 214 additions and 213 deletions
@@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2004-2006 Mike Matsnev. All Rights Reserved. * Copyright (c) 2004-2009 Mike Matsnev. All Rights Reserved.
* *
* Redistribution and use in source and binary forms, with or without * Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions * modification, are permitted provided that the following conditions
@@ -25,7 +25,7 @@
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
* *
* $Id: MatroskaParser.c,v 1.61 2006/10/28 10:39:45 mike Exp $ * $Id: MatroskaParser.c,v >1.61 Unknown mike Exp $
* *
*/ */
@@ -50,7 +50,7 @@
#include "MatroskaParser.h" #include "MatroskaParser.h"
#ifdef MATROSKA_COMPRESSION_SUPPORT #ifdef MATROSKA_COMPRESSION_SUPPORT
#include "zlib.h" #include <zlib.h>
#endif #endif
#define EBML_VERSION 1 #define EBML_VERSION 1
@@ -96,8 +96,7 @@ static char *mystrdup(struct InputStream *is,const char *src) {
return dst; return dst;
} }
#ifdef _WIN32 static void mystrlcpy(char *dst,const char *src,unsigned size) {
static void strlcpy(char *dst,const char *src,unsigned size) {
unsigned i; unsigned i;
for (i=0;i+1<size && src[i];++i) for (i=0;i+1<size && src[i];++i)
@@ -105,7 +104,6 @@ static void strlcpy(char *dst,const char *src,unsigned size) {
if (i<size) if (i<size)
dst[i] = 0; dst[i] = 0;
} }
#endif
struct Cue { struct Cue {
ulonglong Time; ulonglong Time;
@@ -240,7 +238,7 @@ static void myvsnprintf_uint_impl(char **pdest,char *de,int width,int zero,
int rem = (int)(val % base); int rem = (int)(val % base);
val = val / base; val = val / base;
*--np = rem < 10 ? rem + '0' : rem - 10 + letter; *--np = (char)(rem < 10 ? rem + '0' : rem - 10 + letter);
} }
rw = (int)(tmp - np + sizeof(tmp) - 1); rw = (int)(tmp - np + sizeof(tmp) - 1);
@@ -290,7 +288,7 @@ static void myvsnprintf_int(char **pdest,char *de,int width,int zero,
static void myvsnprintf(char *dest,unsigned dsize,const char *fmt,va_list ap) { static void myvsnprintf(char *dest,unsigned dsize,const char *fmt,va_list ap) {
// s,d,x,u,ll // s,d,x,u,ll
char *de = dest + dsize - 1; char *de = dest + dsize - 1;
int state = 0, width = 0, zero = 0, neg = 0, ll = 0; int state = 0, width, zero, neg, ll;
if (dsize <= 1) { if (dsize <= 1) {
if (dsize > 0) if (dsize > 0)
@@ -687,7 +685,7 @@ static ulonglong readVLUIntImp(MatroskaFile *mf,int *mask) {
c = readch(mf); c = readch(mf);
if (c == EOF) if (c == EOF)
return EOF; return 0; // XXX should errorjmp()?
if (c == 0) if (c == 0)
errorjmp(mf,"Invalid first byte of EBML integer: 0"); errorjmp(mf,"Invalid first byte of EBML integer: 0");
@@ -1078,6 +1076,8 @@ static void parseSegmentInfo(MatroskaFile *mf,ulonglong toplen) {
} }
static void parseFirstCluster(MatroskaFile *mf,ulonglong toplen) { static void parseFirstCluster(MatroskaFile *mf,ulonglong toplen) {
ulonglong end = filepos(mf) + toplen;
mf->seen.Cluster = 1; mf->seen.Cluster = 1;
mf->firstTimecode = 0; mf->firstTimecode = 0;
@@ -1089,7 +1089,7 @@ static void parseFirstCluster(MatroskaFile *mf,ulonglong toplen) {
readVLUInt(mf); // track number readVLUInt(mf); // track number
mf->firstTimecode += readSInt(mf, 2); mf->firstTimecode += readSInt(mf, 2);
skipbytes(mf,start + toplen - filepos(mf)); skipbytes(mf,end - filepos(mf));
return; return;
case 0xa0: // BlockGroup case 0xa0: // BlockGroup
FOREACH(mf,len) FOREACH(mf,len)
@@ -1097,7 +1097,7 @@ static void parseFirstCluster(MatroskaFile *mf,ulonglong toplen) {
readVLUInt(mf); // track number readVLUInt(mf); // track number
mf->firstTimecode += readSInt(mf,2); mf->firstTimecode += readSInt(mf,2);
skipbytes(mf,start + toplen - filepos(mf)); skipbytes(mf,end - filepos(mf));
return; return;
ENDFOR(mf); ENDFOR(mf);
break; break;
@@ -1247,7 +1247,7 @@ static void parseTrackEntry(MatroskaFile *mf,ulonglong toplen) {
ulonglong v; ulonglong v;
char *cp = NULL, *cs = NULL; char *cp = NULL, *cs = NULL;
size_t cplen = 0, cslen = 0, cpadd = 0; size_t cplen = 0, cslen = 0, cpadd = 0;
unsigned CompScope = 0, num_comp = 0; unsigned CompScope, num_comp = 0;
if (mf->nTracks >= MAX_TRACKS) if (mf->nTracks >= MAX_TRACKS)
errorjmp(mf,"Too many tracks."); errorjmp(mf,"Too many tracks.");
@@ -1424,7 +1424,7 @@ static void parseTrackEntry(MatroskaFile *mf,ulonglong toplen) {
// handle compressed CodecPrivate // handle compressed CodecPrivate
if (t.CompEnabled && t.CompMethod == COMP_ZLIB && (CompScope & 2) && cplen > 0) { if (t.CompEnabled && t.CompMethod == COMP_ZLIB && (CompScope & 2) && cplen > 0) {
z_stream zs; z_stream zs;
char tmp[64], *ncp; Bytef tmp[64], *ncp;
int code; int code;
uLong ncplen; uLong ncplen;
@@ -1432,7 +1432,7 @@ static void parseTrackEntry(MatroskaFile *mf,ulonglong toplen) {
if (inflateInit(&zs) != Z_OK) if (inflateInit(&zs) != Z_OK)
errorjmp(mf, "inflateInit failed"); errorjmp(mf, "inflateInit failed");
zs.next_in = cp; zs.next_in = (Bytef *)cp;
zs.avail_in = cplen; zs.avail_in = cplen;
do { do {
@@ -1450,7 +1450,7 @@ static void parseTrackEntry(MatroskaFile *mf,ulonglong toplen) {
inflateReset(&zs); inflateReset(&zs);
zs.next_in = cp; zs.next_in = (Bytef *)cp;
zs.avail_in = cplen; zs.avail_in = cplen;
zs.next_out = ncp; zs.next_out = ncp;
zs.avail_out = ncplen; zs.avail_out = ncplen;
@@ -1460,7 +1460,7 @@ static void parseTrackEntry(MatroskaFile *mf,ulonglong toplen) {
inflateEnd(&zs); inflateEnd(&zs);
cp = ncp; cp = (char *)ncp;
cplen = ncplen; cplen = ncplen;
} }
#endif #endif
@@ -1491,7 +1491,7 @@ static void parseTrackEntry(MatroskaFile *mf,ulonglong toplen) {
} }
if (cslen) { if (cslen) {
tp->CompMethodPrivate = (char *)(tp+1) + cplen; tp->CompMethodPrivate = (char *)(tp+1) + cplen;
tp->CompMethodPrivateSize = cslen; tp->CompMethodPrivateSize = (unsigned)cslen;
memcpy(tp->CompMethodPrivate, cs, cslen); memcpy(tp->CompMethodPrivate, cs, cslen);
} }
@@ -1982,7 +1982,13 @@ static void parsePointers(MatroskaFile *mf) {
static void parseSegment(MatroskaFile *mf,ulonglong toplen) { static void parseSegment(MatroskaFile *mf,ulonglong toplen) {
ulonglong nextpos; ulonglong nextpos;
unsigned nSeekHeads = 0, dontstop = 0; unsigned nSeekHeads = 0, dontstop = 0;
jmp_buf jb;
memcpy(&jb,&mf->jb,sizeof(jb));
if (setjmp(mf->jb))
mf->flags &= ~MPF_ERROR;
else {
// we want to read data until we find a seekhead or a trackinfo // we want to read data until we find a seekhead or a trackinfo
FOREACH(mf,toplen) FOREACH(mf,toplen)
case 0x114d9b74: // SeekHead case 0x114d9b74: // SeekHead
@@ -2004,19 +2010,8 @@ static void parseSegment(MatroskaFile *mf,ulonglong toplen) {
if (id != 0x114d9b74) // chained SeekHead doesnt point to a SeekHead? if (id != 0x114d9b74) // chained SeekHead doesnt point to a SeekHead?
break; break;
len = readSize(mf); len = readSize(mf);
} else if (mf->pSegmentInfo && mf->pTracks && mf->pCues && mf->pCluster) { // we have pointers to all key elements
// XXX EVIL HACK
// Some software doesnt index tags via SeekHead, so we continue
// reading the segment after the second SeekHead
if (mf->pTags || nSeekHeads<2 || filepos(mf)>=start+toplen) {
parsePointers(mf);
return;
} }
// reset nextpos pointer to current position } while (mf->pSeekHead && nSeekHeads < 10);
nextpos = filepos(mf);
dontstop = 1;
}
} while (mf->pSeekHead);
seek(mf,nextpos); // resume reading segment seek(mf,nextpos); // resume reading segment
break; break;
case 0x1549a966: // SegmentInfo case 0x1549a966: // SegmentInfo
@@ -2056,11 +2051,15 @@ static void parseSegment(MatroskaFile *mf,ulonglong toplen) {
if (!dontstop && mf->pSegmentInfo && mf->pTracks && mf->pCluster) if (!dontstop && mf->pSegmentInfo && mf->pTracks && mf->pCluster)
break; break;
ENDFOR2(); ENDFOR2();
}
memcpy(&mf->jb,&jb,sizeof(jb));
parsePointers(mf); parsePointers(mf);
} }
static void parseBlockAdditions(MatroskaFile *mf, ulonglong toplen, ulonglong timecode, unsigned track) { static void parseBlockAdditions(MatroskaFile *mf, ulonglong toplen, ulonglong timecode, unsigned track) {
ulonglong add_id = 1, add_pos = 0, add_len = 0; ulonglong add_id = 1, add_pos, add_len;
unsigned char have_add; unsigned char have_add;
FOREACH(mf, toplen) FOREACH(mf, toplen)
@@ -2095,7 +2094,6 @@ static void parseBlockGroup(MatroskaFile *mf,ulonglong toplen,ulonglong timecode
ulonglong v; ulonglong v;
ulonglong duration = 0; ulonglong duration = 0;
ulonglong dpos; ulonglong dpos;
// unsigned add_id = 0;
struct QueueEntry *qe,*qf = NULL; struct QueueEntry *qe,*qf = NULL;
unsigned char have_duration = 0, have_block = 0; unsigned char have_duration = 0, have_block = 0;
unsigned char gap = 0; unsigned char gap = 0;
@@ -2152,10 +2150,10 @@ found:
errorjmp(mf,"Unexpected EOF while reading Block flags"); errorjmp(mf,"Unexpected EOF while reading Block flags");
if (blockex) if (blockex)
ref = !(c & 0x80); ref = (unsigned char)!(c & 0x80);
gap = c & 0x1; gap = (unsigned char)(c & 0x1);
lacing = (c >> 1) & 3; lacing = (unsigned char)((c >> 1) & 3);
if (lacing) { if (lacing) {
c = readch(mf); c = readch(mf);
@@ -2474,7 +2472,7 @@ static void reindex(MatroskaFile *mf) {
jmp_buf jb; jmp_buf jb;
ulonglong pos = mf->pCluster; ulonglong pos = mf->pCluster;
ulonglong step = 10*1024*1024; ulonglong step = 10*1024*1024;
ulonglong size, tc = 0, isize; ulonglong size, tc, isize;
longlong next_cluster; longlong next_cluster;
int id, have_tc, bad; int id, have_tc, bad;
struct Cue *cue; struct Cue *cue;
@@ -2762,7 +2760,7 @@ MatroskaFile *mkv_OpenEx(InputStream *io,
{ {
MatroskaFile *mf = io->memalloc(io,sizeof(*mf)); MatroskaFile *mf = io->memalloc(io,sizeof(*mf));
if (mf == NULL) { if (mf == NULL) {
strlcpy(err_msg,"Out of memory",msgsize); mystrlcpy(err_msg,"Out of memory",msgsize);
return NULL; return NULL;
} }
@@ -2776,7 +2774,7 @@ MatroskaFile *mkv_OpenEx(InputStream *io,
seek(mf,base); seek(mf,base);
parseFile(mf); parseFile(mf);
} else { // parser error } else { // parser error
strlcpy(err_msg,mf->errmsg,msgsize); mystrlcpy(err_msg,mf->errmsg,msgsize);
mkv_Close(mf); mkv_Close(mf);
return NULL; return NULL;
} }
@@ -2917,7 +2915,7 @@ void mkv_Seek(MatroskaFile *mf,ulonglong timecode,unsigned flags) {
mkv_SetTrackMask(mf,mf->trackMask); mkv_SetTrackMask(mf,mf->trackMask);
if (flags & MKVF_SEEK_TO_PREV_KEYFRAME) { if (flags & (MKVF_SEEK_TO_PREV_KEYFRAME | MKVF_SEEK_TO_PREV_KEYFRAME_STRICT)) {
// we do this in two stages // we do this in two stages
// a. find the last keyframes before the require position // a. find the last keyframes before the require position
// b. seek to them // b. seek to them
@@ -2932,7 +2930,7 @@ void mkv_Seek(MatroskaFile *mf,ulonglong timecode,unsigned flags) {
EmptyQueues(mf); EmptyQueues(mf);
mf->readPosition = mf->Cues[j].Position + mf->pSegment; mf->readPosition = mf->Cues[j].Position + mf->pSegment;
mf->tcCluster = mf->Cues[j].Time / mf->Seg.TimecodeScale; mf->tcCluster = mf->Cues[j].Time;
for (;;) { for (;;) {
if ((ret = fillQueues(mf,0)) < 0 || ret == RBRESYNC) if ((ret = fillQueues(mf,0)) < 0 || ret == RBRESYNC)
@@ -2940,7 +2938,7 @@ void mkv_Seek(MatroskaFile *mf,ulonglong timecode,unsigned flags) {
// drain queues until we get to the required timecode // drain queues until we get to the required timecode
for (n=0;n<mf->nTracks;++n) { for (n=0;n<mf->nTracks;++n) {
if (mf->Queues[n].head && mf->Queues[n].head->Start<timecode) { if (mf->Queues[n].head && (mf->Queues[n].head->Start<timecode || (m_seendf[n] == 0 && m_kftime[n] == MAXU64))) {
if (IS_DELTA(mf->Queues[n].head)) if (IS_DELTA(mf->Queues[n].head))
m_seendf[n] = 1; m_seendf[n] = 1;
else else
@@ -2956,6 +2954,11 @@ void mkv_Seek(MatroskaFile *mf,ulonglong timecode,unsigned flags) {
QFree(mf,QGet(&mf->Queues[n])); QFree(mf,QGet(&mf->Queues[n]));
} }
// We've drained the queue, so the frame at head is the next one past the requered point.
// In strict mode we are done, but when seeking is not strict we use the head frame
// if it's not an audio track (we accept preroll within a frame for audio), and the head frame
// is a keyframe
if (!(flags & MKVF_SEEK_TO_PREV_KEYFRAME_STRICT))
if (mf->Queues[n].head && (mf->Tracks[n]->Type != TT_AUDIO || mf->Queues[n].head->Start<=timecode)) if (mf->Queues[n].head && (mf->Tracks[n]->Type != TT_AUDIO || mf->Queues[n].head->Start<=timecode))
if (!IS_DELTA(mf->Queues[n].head)) if (!IS_DELTA(mf->Queues[n].head))
m_kftime[n] = mf->Queues[n].head->Start; m_kftime[n] = mf->Queues[n].head->Start;
@@ -2987,7 +2990,7 @@ again:;
EmptyQueues(mf); EmptyQueues(mf);
mf->readPosition = mf->Cues[j].Position + mf->pSegment; mf->readPosition = mf->Cues[j].Position + mf->pSegment;
mf->tcCluster = mf->Cues[j].Time / mf->Seg.TimecodeScale; mf->tcCluster = mf->Cues[j].Time;
for (mask=0;;) { for (mask=0;;) {
if ((ret = fillQueues(mf,mask)) < 0 || ret == RBRESYNC) if ((ret = fillQueues(mf,mask)) < 0 || ret == RBRESYNC)
@@ -3182,30 +3185,30 @@ CompressedStream *cs_Create(/* in */ MatroskaFile *mf,
ti = mkv_GetTrackInfo(mf, tracknum); ti = mkv_GetTrackInfo(mf, tracknum);
if (ti == NULL) { if (ti == NULL) {
strlcpy(errormsg, "No such track.", msgsize); mystrlcpy(errormsg, "No such track.", msgsize);
return NULL; return NULL;
} }
if (!ti->CompEnabled) { if (!ti->CompEnabled) {
strlcpy(errormsg, "Track is not compressed.", msgsize); mystrlcpy(errormsg, "Track is not compressed.", msgsize);
return NULL; return NULL;
} }
if (ti->CompMethod != COMP_ZLIB) { if (ti->CompMethod != COMP_ZLIB) {
strlcpy(errormsg, "Unsupported compression method.", msgsize); mystrlcpy(errormsg, "Unsupported compression method.", msgsize);
return NULL; return NULL;
} }
cs = mf->cache->memalloc(mf->cache,sizeof(*cs)); cs = mf->cache->memalloc(mf->cache,sizeof(*cs));
if (cs == NULL) { if (cs == NULL) {
strlcpy(errormsg, "Ouf of memory.", msgsize); mystrlcpy(errormsg, "Ouf of memory.", msgsize);
return NULL; return NULL;
} }
memset(&cs->zs,0,sizeof(cs->zs)); memset(&cs->zs,0,sizeof(cs->zs));
code = inflateInit(&cs->zs); code = inflateInit(&cs->zs);
if (code != Z_OK) { if (code != Z_OK) {
strlcpy(errormsg, "ZLib error.", msgsize); mystrlcpy(errormsg, "ZLib error.", msgsize);
mf->cache->memfree(mf->cache,cs); mf->cache->memfree(mf->cache,cs);
return NULL; return NULL;
} }
@@ -3243,7 +3246,6 @@ int mkv_ReadData(MatroskaFile *mf,ulonglong FilePos, void *Buffer,unsig
return (mf->cache->read(mf->cache, FilePos, Buffer, Count) != Count); return (mf->cache->read(mf->cache, FilePos, Buffer, Count) != Count);
} }
/* read and decode more data from current frame, return number of bytes decoded, /* read and decode more data from current frame, return number of bytes decoded,
* 0 on end of frame, or -1 on error */ * 0 on end of frame, or -1 on error */
int cs_ReadData(CompressedStream *cs,char *buffer,unsigned bufsize) int cs_ReadData(CompressedStream *cs,char *buffer,unsigned bufsize)
@@ -3267,7 +3269,7 @@ int cs_ReadData(CompressedStream *cs,char *buffer,unsigned bufsize)
cs->decoded_ptr += todo; cs->decoded_ptr += todo;
} else { } else {
/* setup output buffer */ /* setup output buffer */
cs->zs.next_out = cs->decoded_buffer; cs->zs.next_out = (Bytef *)cs->decoded_buffer;
cs->zs.avail_out = sizeof(cs->decoded_buffer); cs->zs.avail_out = sizeof(cs->decoded_buffer);
/* try to read more data */ /* try to read more data */
@@ -3277,11 +3279,11 @@ int cs_ReadData(CompressedStream *cs,char *buffer,unsigned bufsize)
todo = sizeof(cs->frame_buffer); todo = sizeof(cs->frame_buffer);
if (cs->mf->cache->read(cs->mf->cache, cs->frame_pos, cs->frame_buffer, todo) != (int)todo) { if (cs->mf->cache->read(cs->mf->cache, cs->frame_pos, cs->frame_buffer, todo) != (int)todo) {
strlcpy(cs->errmsg, "File read failed", sizeof(cs->errmsg)); mystrlcpy(cs->errmsg, "File read failed", sizeof(cs->errmsg));
return -1; return -1;
} }
cs->zs.next_in = cs->frame_buffer; cs->zs.next_in = (Bytef *)cs->frame_buffer;
cs->zs.avail_in = todo; cs->zs.avail_in = todo;
cs->frame_pos += todo; cs->frame_pos += todo;
@@ -3291,7 +3293,7 @@ int cs_ReadData(CompressedStream *cs,char *buffer,unsigned bufsize)
/* try to decode more data */ /* try to decode more data */
code = inflate(&cs->zs,Z_NO_FLUSH); code = inflate(&cs->zs,Z_NO_FLUSH);
if (code != Z_OK && code != Z_STREAM_END) { if (code != Z_OK && code != Z_STREAM_END) {
strlcpy(cs->errmsg, "ZLib error.", sizeof(cs->errmsg)); mystrlcpy(cs->errmsg, "ZLib error.", sizeof(cs->errmsg));
return -1; return -1;
} }
@@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2004-2006 Mike Matsnev. All Rights Reserved. * Copyright (c) 2004-2009 Mike Matsnev. All Rights Reserved.
* *
* Redistribution and use in source and binary forms, with or without * Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions * modification, are permitted provided that the following conditions
@@ -25,7 +25,7 @@
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
* *
* $Id: MatroskaParser.h,v 1.19 2006/03/11 10:57:13 mike Exp $ * $Id: MatroskaParser.h,v >1.19 Unknown mike Exp $
* *
*/ */
@@ -128,13 +128,12 @@ struct TrackInfo {
void *CompMethodPrivate; void *CompMethodPrivate;
unsigned CompMethodPrivateSize; unsigned CompMethodPrivateSize;
unsigned MaxBlockAdditionID; unsigned MaxBlockAdditionID;
struct {
unsigned int Enabled:1; unsigned int Enabled:1;
unsigned int Default:1; unsigned int Default:1;
unsigned int Lacing:1; unsigned int Lacing:1;
unsigned int DecodeAll:1; unsigned int DecodeAll:1;
unsigned int CompEnabled:1; unsigned int CompEnabled:1;
};
union { union {
struct { struct {
@@ -148,9 +147,8 @@ struct TrackInfo {
unsigned int CropL, CropT, CropR, CropB; unsigned int CropL, CropT, CropR, CropB;
unsigned int ColourSpace; unsigned int ColourSpace;
MKFLOAT GammaValue; MKFLOAT GammaValue;
struct {
unsigned int Interlaced:1; unsigned int Interlaced:1;
};
} Video; } Video;
struct { struct {
MKFLOAT SamplingFreq; MKFLOAT SamplingFreq;
@@ -233,7 +231,6 @@ struct Chapter {
char SegmentUID[16]; char SegmentUID[16];
struct {
unsigned int Hidden:1; unsigned int Hidden:1;
unsigned int Enabled:1; unsigned int Enabled:1;
@@ -241,7 +238,6 @@ struct Chapter {
unsigned int Default:1; unsigned int Default:1;
unsigned int Ordered:1; unsigned int Ordered:1;
}; };
};
typedef struct Chapter Chapter; typedef struct Chapter Chapter;
@@ -320,6 +316,7 @@ X ulonglong mkv_GetSegmentTop(MatroskaFile *mf);
* on next read * on next read
*/ */
#define MKVF_SEEK_TO_PREV_KEYFRAME 1 #define MKVF_SEEK_TO_PREV_KEYFRAME 1
#define MKVF_SEEK_TO_PREV_KEYFRAME_STRICT 2
X void mkv_Seek(/* in */ MatroskaFile *mf, X void mkv_Seek(/* in */ MatroskaFile *mf,
/* in */ ulonglong timecode /* in ns */, /* in */ ulonglong timecode /* in ns */,
@@ -366,7 +363,6 @@ X int mkv_ReadFrame(/* in */ MatroskaFile *mf,
int mkv_ReadData(MatroskaFile *mf,ulonglong FilePos, void *Buffer,unsigned int Count); int mkv_ReadData(MatroskaFile *mf,ulonglong FilePos, void *Buffer,unsigned int Count);
#ifdef MATROSKA_COMPRESSION_SUPPORT #ifdef MATROSKA_COMPRESSION_SUPPORT
/* Compressed streams support */ /* Compressed streams support */
struct CompressedStream; struct CompressedStream;
@@ -1,5 +1,7 @@
SubDir HAIKU_TOP src add-ons media plugins matroska libebml ; SubDir HAIKU_TOP src add-ons media plugins matroska libebml ;
SubDirHdrs [ FDirName $(SUBDIR) ebml ] ;
StaticLibrary libebml.a : StaticLibrary libebml.a :
Debug.cpp Debug.cpp
EbmlBinary.cpp EbmlBinary.cpp
@@ -36,8 +36,8 @@
#include <clocale> #include <clocale>
#include <string> #include <string>
#include "ebml/c/libebml_t.h" #include "c/libebml_t.h"
#include "ebml/EbmlConfig.h" #include "EbmlConfig.h"
#include "EbmlEndian.h" // binary needs to be defined #include "EbmlEndian.h" // binary needs to be defined
START_LIBEBML_NAMESPACE START_LIBEBML_NAMESPACE
@@ -1,6 +1,7 @@
SubDir HAIKU_TOP src add-ons media plugins matroska libmatroska ; SubDir HAIKU_TOP src add-ons media plugins matroska libmatroska ;
SubDirHdrs [ FDirName $(SUBDIR) $(DOTDOT) libebml ] ; SubDirHdrs [ FDirName $(SUBDIR) $(DOTDOT) libebml ] ;
SubDirHdrs [ FDirName $(SUBDIR) $(DOTDOT) libebml ebml ] ;
StaticLibrary libmatroska.a : StaticLibrary libmatroska.a :
FileKax.cpp FileKax.cpp
@@ -78,7 +78,7 @@ struct mkv_cookie
}; };
static uint8 static uint8
matroska_samplerate_to_samplerateindex(float samplerate) matroska_samplerate_to_samplerateindex(double samplerate)
{ {
if (samplerate <= 7350.0) { if (samplerate <= 7350.0) {
return 12; return 12;
@@ -142,15 +142,15 @@ mkvReader::CreateFakeAACDecoderConfig(const TrackInfo *track, uint8 **fakeExtraD
profile = 3; profile = 3;
} }
uint8 sampleRateIndex = matroska_samplerate_to_samplerateindex(track->Audio.SamplingFreq); uint8 sampleRateIndex = matroska_samplerate_to_samplerateindex(track->AV.Audio.SamplingFreq);
TRACE("Profile %d, SampleRate %f, SampleRateIndex %d\n",profile, track->Audio.SamplingFreq, sampleRateIndex); TRACE("Profile %d, SampleRate %f, SampleRateIndex %d\n",profile, track->AV.Audio.SamplingFreq, sampleRateIndex);
// profile 5 bits // profile 5 bits
// SampleRateIndex 4 bits // SampleRateIndex 4 bits
// Channels 4 Bits // Channels 4 Bits
(*fakeExtraData)[0] = (profile << 3) | ((sampleRateIndex & 0x0E) >> 1); (*fakeExtraData)[0] = (profile << 3) | ((sampleRateIndex & 0x0E) >> 1);
(*fakeExtraData)[1] = ((sampleRateIndex & 0x01) << 7) | (track->Audio.Channels << 3); (*fakeExtraData)[1] = ((sampleRateIndex & 0x01) << 7) | (track->AV.Audio.Channels << 3);
if (strstr(track->CodecID, "SBR")) { if (strstr(track->CodecID, "SBR")) {
TRACE("Extension SBR Needs more configuration\n"); TRACE("Extension SBR Needs more configuration\n");
// Sync Extension 0x2b7 11 bits // Sync Extension 0x2b7 11 bits
@@ -160,7 +160,7 @@ mkvReader::CreateFakeAACDecoderConfig(const TrackInfo *track, uint8 **fakeExtraD
// if SampleRateIndex = 15 // if SampleRateIndex = 15
// ExtendedSamplingFrequency 24 bits // ExtendedSamplingFrequency 24 bits
sampleRateIndex = matroska_samplerate_to_samplerateindex(track->Audio.OutputSamplingFreq); sampleRateIndex = matroska_samplerate_to_samplerateindex(track->AV.Audio.OutputSamplingFreq);
(*fakeExtraData)[2] = 0x56; (*fakeExtraData)[2] = 0x56;
(*fakeExtraData)[3] = 0xE5; (*fakeExtraData)[3] = 0xE5;
if (sampleRateIndex != 15) { if (sampleRateIndex != 15) {
@@ -168,7 +168,7 @@ mkvReader::CreateFakeAACDecoderConfig(const TrackInfo *track, uint8 **fakeExtraD
return 5; return 5;
} }
uint32 sampleRate = uint32(track->Audio.OutputSamplingFreq); uint32 sampleRate = uint32(track->AV.Audio.OutputSamplingFreq);
(*fakeExtraData)[4] = 0x80 | (sampleRateIndex << 3) | ((sampleRate & 0xFFF0 ) >> 4); (*fakeExtraData)[4] = 0x80 | (sampleRateIndex << 3) | ((sampleRate & 0xFFF0 ) >> 4);
(*fakeExtraData)[5] = (sampleRate & 0x0FFF) << 4; (*fakeExtraData)[5] = (sampleRate & 0x0FFF) << 4;
@@ -185,7 +185,7 @@ mkvReader::CreateFakeAACDecoderConfig(const TrackInfo *track, uint8 **fakeExtraD
const char * const char *
mkvReader::Copyright() mkvReader::Copyright()
{ {
return "Matroska reader, " B_UTF8_COPYRIGHT " by Marcus Overhagen"; return "Matroska reader, " B_UTF8_COPYRIGHT " by Marcus Overhagen\nUsing MatroskaParser " B_UTF8_COPYRIGHT " by Mike Matsnev";
} }
status_t status_t
@@ -296,23 +296,23 @@ mkvReader::SetupVideoCookie(mkv_cookie *cookie)
cookie->audio = false; cookie->audio = false;
TRACE("video StereoMode: %d\n", cookie->track_info->Video.StereoMode); TRACE("video StereoMode: %d\n", cookie->track_info->AV.Video.StereoMode);
TRACE("video DisplayUnit: %d\n", cookie->track_info->Video.DisplayUnit); TRACE("video DisplayUnit: %d\n", cookie->track_info->AV.Video.DisplayUnit);
TRACE("video AspectRatioType: %d\n", cookie->track_info->Video.AspectRatioType); TRACE("video AspectRatioType: %d\n", cookie->track_info->AV.Video.AspectRatioType);
TRACE("video PixelWidth: %d\n", cookie->track_info->Video.PixelWidth); TRACE("video PixelWidth: %d\n", cookie->track_info->AV.Video.PixelWidth);
TRACE("video PixelHeight: %d\n", cookie->track_info->Video.PixelHeight); TRACE("video PixelHeight: %d\n", cookie->track_info->AV.Video.PixelHeight);
TRACE("video DisplayWidth: %d\n", cookie->track_info->Video.DisplayWidth); TRACE("video DisplayWidth: %d\n", cookie->track_info->AV.Video.DisplayWidth);
TRACE("video DisplayHeight: %d\n", cookie->track_info->Video.DisplayHeight); TRACE("video DisplayHeight: %d\n", cookie->track_info->AV.Video.DisplayHeight);
TRACE("video ColourSpace: %d\n", cookie->track_info->Video.ColourSpace); TRACE("video ColourSpace: %d\n", cookie->track_info->AV.Video.ColourSpace);
TRACE("video GammaValue: %.4f\n", cookie->track_info->Video.GammaValue); TRACE("video GammaValue: %.4f\n", cookie->track_info->AV.Video.GammaValue);
TRACE("video Interlaced: %d\n", cookie->track_info->Video.Interlaced); TRACE("video Interlaced: %d\n", cookie->track_info->AV.Video.Interlaced);
cookie->frame_rate = get_frame_rate(cookie->track_info->DefaultDuration); cookie->frame_rate = get_frame_rate(cookie->track_info->DefaultDuration);
cookie->duration = get_duration_in_us(fFileInfo->Duration); cookie->duration = get_duration_in_us(fFileInfo->Duration);
cookie->frame_count = get_frame_count_by_default_duration(fFileInfo->Duration, cookie->track_info->DefaultDuration); cookie->frame_count = get_frame_count_by_default_duration(fFileInfo->Duration, cookie->track_info->DefaultDuration);
cookie->line_count = cookie->track_info->Video.PixelHeight; cookie->line_count = cookie->track_info->AV.Video.PixelHeight;
TRACE("mkvReader::Sniff: TimecodeScale %Ld\n", fFileInfo->TimecodeScale); TRACE("mkvReader::Sniff: TimecodeScale %Ld\n", fFileInfo->TimecodeScale);
TRACE("mkvReader::Sniff: Duration %Ld\n", fFileInfo->Duration); TRACE("mkvReader::Sniff: Duration %Ld\n", fFileInfo->Duration);
@@ -334,10 +334,10 @@ mkvReader::SetupVideoCookie(mkv_cookie *cookie)
uint16 width_aspect_ratio; uint16 width_aspect_ratio;
uint16 height_aspect_ratio; uint16 height_aspect_ratio;
get_pixel_aspect_ratio(&width_aspect_ratio, &height_aspect_ratio, get_pixel_aspect_ratio(&width_aspect_ratio, &height_aspect_ratio,
cookie->track_info->Video.PixelWidth, cookie->track_info->AV.Video.PixelWidth,
cookie->track_info->Video.PixelHeight, cookie->track_info->AV.Video.PixelHeight,
cookie->track_info->Video.DisplayWidth, cookie->track_info->AV.Video.DisplayWidth,
cookie->track_info->Video.DisplayHeight); cookie->track_info->AV.Video.DisplayHeight);
// cookie->format.u.encoded_video.max_bit_rate = // cookie->format.u.encoded_video.max_bit_rate =
// cookie->format.u.encoded_video.avg_bit_rate = // cookie->format.u.encoded_video.avg_bit_rate =
@@ -349,8 +349,8 @@ mkvReader::SetupVideoCookie(mkv_cookie *cookie)
cookie->format.u.encoded_video.output.pixel_width_aspect = width_aspect_ratio; cookie->format.u.encoded_video.output.pixel_width_aspect = width_aspect_ratio;
cookie->format.u.encoded_video.output.pixel_height_aspect = height_aspect_ratio; cookie->format.u.encoded_video.output.pixel_height_aspect = height_aspect_ratio;
// cookie->format.u.encoded_video.output.display.format = 0; // cookie->format.u.encoded_video.output.display.format = 0;
cookie->format.u.encoded_video.output.display.line_width = cookie->track_info->Video.PixelWidth; cookie->format.u.encoded_video.output.display.line_width = cookie->track_info->AV.Video.PixelWidth;
cookie->format.u.encoded_video.output.display.line_count = cookie->track_info->Video.PixelHeight; cookie->format.u.encoded_video.output.display.line_count = cookie->track_info->AV.Video.PixelHeight;
cookie->format.u.encoded_video.output.display.bytes_per_row = 0; cookie->format.u.encoded_video.output.display.bytes_per_row = 0;
cookie->format.u.encoded_video.output.display.pixel_offset = 0; cookie->format.u.encoded_video.output.display.pixel_offset = 0;
cookie->format.u.encoded_video.output.display.line_offset = 0; cookie->format.u.encoded_video.output.display.line_offset = 0;
@@ -373,14 +373,14 @@ mkvReader::SetupAudioCookie(mkv_cookie *cookie)
cookie->audio = true; cookie->audio = true;
TRACE("audio SamplingFreq: %.3f\n", cookie->track_info->Audio.SamplingFreq); TRACE("audio SamplingFreq: %.3f\n", cookie->track_info->AV.Audio.SamplingFreq);
TRACE("audio OutputSamplingFreq: %.3f\n", cookie->track_info->Audio.OutputSamplingFreq); TRACE("audio OutputSamplingFreq: %.3f\n", cookie->track_info->AV.Audio.OutputSamplingFreq);
TRACE("audio Channels: %d\n", cookie->track_info->Audio.Channels); TRACE("audio Channels: %d\n", cookie->track_info->AV.Audio.Channels);
TRACE("audio BitDepth: %d\n", cookie->track_info->Audio.BitDepth); TRACE("audio BitDepth: %d\n", cookie->track_info->AV.Audio.BitDepth);
TRACE("CodecID: %s\n", cookie->track_info->CodecID); TRACE("CodecID: %s\n", cookie->track_info->CodecID);
cookie->frame_rate = cookie->track_info->Audio.SamplingFreq; cookie->frame_rate = cookie->track_info->AV.Audio.SamplingFreq;
cookie->duration = get_duration_in_us(fFileInfo->Duration); cookie->duration = get_duration_in_us(fFileInfo->Duration);
cookie->frame_count = get_frame_count_by_frame_rate(fFileInfo->Duration, cookie->frame_rate); cookie->frame_count = get_frame_count_by_frame_rate(fFileInfo->Duration, cookie->frame_rate);
@@ -394,8 +394,8 @@ mkvReader::SetupAudioCookie(mkv_cookie *cookie)
} }
cookie->format.u.encoded_audio.output.frame_rate = cookie->frame_rate; cookie->format.u.encoded_audio.output.frame_rate = cookie->frame_rate;
cookie->format.u.encoded_audio.output.channel_count = cookie->track_info->Audio.Channels; cookie->format.u.encoded_audio.output.channel_count = cookie->track_info->AV.Audio.Channels;
cookie->format.u.encoded_audio.bit_rate = cookie->track_info->Audio.BitDepth * cookie->format.u.encoded_audio.output.channel_count * cookie->frame_rate; cookie->format.u.encoded_audio.bit_rate = cookie->track_info->AV.Audio.BitDepth * cookie->format.u.encoded_audio.output.channel_count * cookie->frame_rate;
cookie->private_data = (uint8 *)cookie->track_info->CodecPrivate; cookie->private_data = (uint8 *)cookie->track_info->CodecPrivate;
cookie->private_data_size = cookie->track_info->CodecPrivateSize; cookie->private_data_size = cookie->track_info->CodecPrivateSize;