mirror of https://github.com/odrling/Aegisub
Update Haali's MatroskaParser.c/.h in the main source tree (there's a copy in the FFMS2 folder as well, which will be updated later). Should fix a crash with x264-generated MKV's.
Originally committed to SVN as r2884.
This commit is contained in:
parent
866f9d21fc
commit
33c31e3eee
|
@ -1,31 +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
|
|
||||||
* modification, are permitted provided that the following conditions
|
|
||||||
* are met:
|
|
||||||
*
|
|
||||||
* 1. Redistributions of source code must retain the above copyright
|
|
||||||
* notice immediately at the beginning of the file, without modification,
|
|
||||||
* this list of conditions, and the following disclaimer.
|
|
||||||
* 2. Redistributions in binary form must reproduce the above copyright
|
|
||||||
* notice, this list of conditions and the following disclaimer in the
|
|
||||||
* documentation and/or other materials provided with the distribution.
|
|
||||||
* 3. Absolutely no warranty of function or purpose is made by the author
|
|
||||||
* Mike Matsnev.
|
|
||||||
*
|
|
||||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
|
|
||||||
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
|
||||||
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
|
||||||
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
|
|
||||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
|
||||||
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
|
||||||
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
|
||||||
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
|
||||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
|
||||||
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
||||||
*
|
|
||||||
* $Id: MatroskaParser.c,v 1.59.2.4 2006/01/13 01:44:45 mike Exp $
|
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
@ -35,10 +9,6 @@
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <setjmp.h>
|
#include <setjmp.h>
|
||||||
|
|
||||||
#ifdef _MSC_VER
|
|
||||||
#pragma warning(disable: 4701)
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifdef _WIN32
|
#ifdef _WIN32
|
||||||
// MS names some functions differently
|
// MS names some functions differently
|
||||||
#define alloca _alloca
|
#define alloca _alloca
|
||||||
|
@ -100,8 +70,7 @@ static char *mystrdup(struct InputStream *is,const char *src) {
|
||||||
return dst;
|
return dst;
|
||||||
}
|
}
|
||||||
|
|
||||||
#if !defined(__FreeBSD__) && !defined(__APPLE__)
|
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)
|
||||||
|
@ -109,7 +78,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;
|
||||||
|
@ -244,7 +212,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 = (char) (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);
|
||||||
|
@ -294,7 +262,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)
|
||||||
|
@ -570,7 +538,7 @@ static void readbytes(MatroskaFile *mf,void *buffer,int len) {
|
||||||
static void skipbytes(MatroskaFile *mf,ulonglong len) {
|
static void skipbytes(MatroskaFile *mf,ulonglong len) {
|
||||||
int nb = mf->buflen - mf->bufpos;
|
int nb = mf->buflen - mf->bufpos;
|
||||||
|
|
||||||
if (nb > (int)len)
|
if (nb > len)
|
||||||
nb = (int)len;
|
nb = (int)len;
|
||||||
|
|
||||||
mf->bufpos += nb;
|
mf->bufpos += nb;
|
||||||
|
@ -691,7 +659,7 @@ static ulonglong readVLUIntImp(MatroskaFile *mf,int *mask) {
|
||||||
|
|
||||||
c = readch(mf);
|
c = readch(mf);
|
||||||
if (c == EOF)
|
if (c == EOF)
|
||||||
return (ulonglong)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");
|
||||||
|
@ -766,7 +734,6 @@ static MKFLOAT readFloat(MatroskaFile *mf,unsigned int len) {
|
||||||
#ifdef MATROSKA_INTEGER_ONLY
|
#ifdef MATROSKA_INTEGER_ONLY
|
||||||
MKFLOAT f;
|
MKFLOAT f;
|
||||||
int shift;
|
int shift;
|
||||||
f.v = 0;
|
|
||||||
#else
|
#else
|
||||||
union {
|
union {
|
||||||
unsigned int ui;
|
unsigned int ui;
|
||||||
|
@ -774,9 +741,6 @@ static MKFLOAT readFloat(MatroskaFile *mf,unsigned int len) {
|
||||||
float f;
|
float f;
|
||||||
double d;
|
double d;
|
||||||
} u;
|
} u;
|
||||||
ui = 0;
|
|
||||||
d = 0;
|
|
||||||
ull = 0;
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
if (len!=4 && len!=8)
|
if (len!=4 && len!=8)
|
||||||
|
@ -850,7 +814,7 @@ static void readString(MatroskaFile *mf,ulonglong len,char *buffer,int buflen) {
|
||||||
|
|
||||||
nread = buflen - 1;
|
nread = buflen - 1;
|
||||||
|
|
||||||
if (nread > (int)len)
|
if (nread > len)
|
||||||
nread = (int)len;
|
nread = (int)len;
|
||||||
|
|
||||||
readbytes(mf,buffer,nread);
|
readbytes(mf,buffer,nread);
|
||||||
|
@ -916,6 +880,16 @@ static void readLangCC(MatroskaFile *mf, ulonglong len, char lcc[4]) {
|
||||||
#define STRGETA(f,v,len) STRGETF(f,v,len,myalloca)
|
#define STRGETA(f,v,len) STRGETF(f,v,len,myalloca)
|
||||||
#define STRGETM(f,v,len) STRGETF(f,v,len,f->cache->memalloc)
|
#define STRGETM(f,v,len) STRGETF(f,v,len,f->cache->memalloc)
|
||||||
|
|
||||||
|
static int IsWritingApp(MatroskaFile *mf,const char *str) {
|
||||||
|
const char *cp = mf->Seg.WritingApp;
|
||||||
|
if (!cp)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
while (*str && *str++==*cp++) ;
|
||||||
|
|
||||||
|
return !*str;
|
||||||
|
}
|
||||||
|
|
||||||
static void parseEBML(MatroskaFile *mf,ulonglong toplen) {
|
static void parseEBML(MatroskaFile *mf,ulonglong toplen) {
|
||||||
ulonglong v;
|
ulonglong v;
|
||||||
char buf[32];
|
char buf[32];
|
||||||
|
@ -1059,6 +1033,7 @@ static void parseSegmentInfo(MatroskaFile *mf,ulonglong toplen) {
|
||||||
break;
|
break;
|
||||||
case 0x4461: // DateUTC
|
case 0x4461: // DateUTC
|
||||||
mf->Seg.DateUTC = readUInt(mf,(unsigned)len);
|
mf->Seg.DateUTC = readUInt(mf,(unsigned)len);
|
||||||
|
mf->Seg.DateUTCValid = 1;
|
||||||
break;
|
break;
|
||||||
case 0x7ba9: // Title
|
case 0x7ba9: // Title
|
||||||
STRGETM(mf,mf->Seg.Title,len);
|
STRGETM(mf,mf->Seg.Title,len);
|
||||||
|
@ -1075,6 +1050,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;
|
||||||
|
|
||||||
|
@ -1086,7 +1063,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)
|
||||||
|
@ -1094,7 +1071,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;
|
||||||
|
@ -1244,7 +1221,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.");
|
||||||
|
@ -1421,7 +1398,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;
|
||||||
|
|
||||||
|
@ -1429,11 +1406,11 @@ 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 = (Bytef*) cp;
|
zs.next_in = (Bytef *)cp;
|
||||||
zs.avail_in = cplen;
|
zs.avail_in = cplen;
|
||||||
|
|
||||||
do {
|
do {
|
||||||
zs.next_out = (Bytef*) tmp;
|
zs.next_out = tmp;
|
||||||
zs.avail_out = sizeof(tmp);
|
zs.avail_out = sizeof(tmp);
|
||||||
|
|
||||||
code = inflate(&zs, Z_NO_FLUSH);
|
code = inflate(&zs, Z_NO_FLUSH);
|
||||||
|
@ -1447,9 +1424,9 @@ static void parseTrackEntry(MatroskaFile *mf,ulonglong toplen) {
|
||||||
|
|
||||||
inflateReset(&zs);
|
inflateReset(&zs);
|
||||||
|
|
||||||
zs.next_in = (Bytef*) cp;
|
zs.next_in = (Bytef *)cp;
|
||||||
zs.avail_in = cplen;
|
zs.avail_in = cplen;
|
||||||
zs.next_out = (Bytef*) ncp;
|
zs.next_out = ncp;
|
||||||
zs.avail_out = ncplen;
|
zs.avail_out = ncplen;
|
||||||
|
|
||||||
if (inflate(&zs, Z_FINISH) != Z_STREAM_END)
|
if (inflate(&zs, Z_FINISH) != Z_STREAM_END)
|
||||||
|
@ -1457,7 +1434,7 @@ static void parseTrackEntry(MatroskaFile *mf,ulonglong toplen) {
|
||||||
|
|
||||||
inflateEnd(&zs);
|
inflateEnd(&zs);
|
||||||
|
|
||||||
cp = ncp;
|
cp = (char *)ncp;
|
||||||
cplen = ncplen;
|
cplen = ncplen;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
@ -1488,7 +1465,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);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1979,7 +1956,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
|
||||||
|
@ -2001,19 +1984,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
|
||||||
|
@ -2053,11 +2025,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)
|
||||||
|
@ -2089,10 +2065,9 @@ static void parseBlockAdditions(MatroskaFile *mf, ulonglong toplen, ulonglong ti
|
||||||
}
|
}
|
||||||
|
|
||||||
static void parseBlockGroup(MatroskaFile *mf,ulonglong toplen,ulonglong timecode, int blockex) {
|
static void parseBlockGroup(MatroskaFile *mf,ulonglong toplen,ulonglong timecode, int blockex) {
|
||||||
ulonglong v=0;
|
ulonglong v;
|
||||||
ulonglong duration = 0;
|
ulonglong duration = 0;
|
||||||
ulonglong dpos=0;
|
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;
|
||||||
|
@ -2149,7 +2124,7 @@ found:
|
||||||
errorjmp(mf,"Unexpected EOF while reading Block flags");
|
errorjmp(mf,"Unexpected EOF while reading Block flags");
|
||||||
|
|
||||||
if (blockex)
|
if (blockex)
|
||||||
ref = (unsigned char)(!(c & 0x80));
|
ref = (unsigned char)!(c & 0x80);
|
||||||
|
|
||||||
gap = (unsigned char)(c & 0x1);
|
gap = (unsigned char)(c & 0x1);
|
||||||
lacing = (unsigned char)((c >> 1) & 3);
|
lacing = (unsigned char)((c >> 1) & 3);
|
||||||
|
@ -2246,14 +2221,17 @@ out:
|
||||||
errorjmp(mf,"Found a BlockGroup without Block");
|
errorjmp(mf,"Found a BlockGroup without Block");
|
||||||
|
|
||||||
if (nframes > 1) {
|
if (nframes > 1) {
|
||||||
|
ulonglong defd = mf->Tracks[tracknum]->DefaultDuration;
|
||||||
|
v = qf->Start;
|
||||||
|
|
||||||
if (have_duration) {
|
if (have_duration) {
|
||||||
duration = mul3(mf->Tracks[tracknum]->TimecodeScale,
|
duration = mul3(mf->Tracks[tracknum]->TimecodeScale,
|
||||||
duration * mf->Seg.TimecodeScale);
|
duration * mf->Seg.TimecodeScale);
|
||||||
|
|
||||||
for (qe = qf; nframes > 1; --nframes, qe = qe->next) {
|
for (qe = qf; nframes > 1; --nframes, qe = qe->next) {
|
||||||
qe->Start = v;
|
qe->Start = v;
|
||||||
v += dpos;
|
v += defd;
|
||||||
duration -= dpos;
|
duration -= defd;
|
||||||
qe->End = v;
|
qe->End = v;
|
||||||
#if 0
|
#if 0
|
||||||
qe->flags &= ~(FRAME_UNKNOWN_START|FRAME_UNKNOWN_END);
|
qe->flags &= ~(FRAME_UNKNOWN_START|FRAME_UNKNOWN_END);
|
||||||
|
@ -2263,11 +2241,9 @@ out:
|
||||||
qe->End = v + duration;
|
qe->End = v + duration;
|
||||||
qe->flags &= ~FRAME_UNKNOWN_END;
|
qe->flags &= ~FRAME_UNKNOWN_END;
|
||||||
} else if (mf->Tracks[tracknum]->DefaultDuration) {
|
} else if (mf->Tracks[tracknum]->DefaultDuration) {
|
||||||
dpos = mf->Tracks[tracknum]->DefaultDuration;
|
|
||||||
v = qf->Start;
|
|
||||||
for (qe = qf; nframes > 0; --nframes, qe = qe->next) {
|
for (qe = qf; nframes > 0; --nframes, qe = qe->next) {
|
||||||
qe->Start = v;
|
qe->Start = v;
|
||||||
v += dpos;
|
v += defd;
|
||||||
qe->End = v;
|
qe->End = v;
|
||||||
qe->flags &= ~(FRAME_UNKNOWN_START|FRAME_UNKNOWN_END);
|
qe->flags &= ~(FRAME_UNKNOWN_START|FRAME_UNKNOWN_END);
|
||||||
}
|
}
|
||||||
|
@ -2758,7 +2734,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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2772,7 +2748,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;
|
||||||
}
|
}
|
||||||
|
@ -2913,7 +2889,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
|
||||||
|
@ -2928,7 +2904,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)
|
||||||
|
@ -2936,7 +2912,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
|
||||||
|
@ -2952,6 +2928,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;
|
||||||
|
@ -2983,7 +2964,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)
|
||||||
|
@ -3178,30 +3159,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;
|
||||||
}
|
}
|
||||||
|
@ -3257,7 +3238,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 = (Bytef*) 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 */
|
||||||
|
@ -3267,11 +3248,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 = (Bytef*) 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;
|
||||||
|
@ -3281,7 +3262,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,41 +1,11 @@
|
||||||
/*
|
/*
|
||||||
* 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
|
|
||||||
* modification, are permitted provided that the following conditions
|
|
||||||
* are met:
|
|
||||||
*
|
|
||||||
* 1. Redistributions of source code must retain the above copyright
|
|
||||||
* notice immediately at the beginning of the file, without modification,
|
|
||||||
* this list of conditions, and the following disclaimer.
|
|
||||||
* 2. Redistributions in binary form must reproduce the above copyright
|
|
||||||
* notice, this list of conditions and the following disclaimer in the
|
|
||||||
* documentation and/or other materials provided with the distribution.
|
|
||||||
* 3. Absolutely no warranty of function or purpose is made by the author
|
|
||||||
* Mike Matsnev.
|
|
||||||
*
|
|
||||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
|
|
||||||
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
|
||||||
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
|
||||||
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
|
|
||||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
|
||||||
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
|
||||||
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
|
||||||
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
|
||||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
|
||||||
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
||||||
*
|
|
||||||
* $Id: MatroskaParser.h,v 1.18.2.6 2006/01/13 01:44:45 mike Exp $
|
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifndef MATROSKA_PARSER_H
|
#ifndef MATROSKA_PARSER_H
|
||||||
#define MATROSKA_PARSER_H
|
#define MATROSKA_PARSER_H
|
||||||
|
|
||||||
#ifdef _MSC_VER
|
|
||||||
#pragma warning(disable: 4201)
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/* Random notes:
|
/* Random notes:
|
||||||
*
|
*
|
||||||
* The parser does not process frame data in any way and does not read it into
|
* The parser does not process frame data in any way and does not read it into
|
||||||
|
@ -132,13 +102,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 {
|
||||||
|
@ -152,9 +121,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;
|
||||||
|
@ -184,7 +152,8 @@ struct SegmentInfo {
|
||||||
char *WritingApp;
|
char *WritingApp;
|
||||||
ulonglong TimecodeScale;
|
ulonglong TimecodeScale;
|
||||||
ulonglong Duration;
|
ulonglong Duration;
|
||||||
ulonglong DateUTC;
|
longlong DateUTC;
|
||||||
|
char DateUTCValid;
|
||||||
};
|
};
|
||||||
|
|
||||||
typedef struct SegmentInfo SegmentInfo;
|
typedef struct SegmentInfo SegmentInfo;
|
||||||
|
@ -236,14 +205,12 @@ 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;
|
||||||
|
|
||||||
// Editions
|
// Editions
|
||||||
unsigned int Default:1;
|
unsigned int Default:1;
|
||||||
unsigned int Ordered:1;
|
unsigned int Ordered:1;
|
||||||
};
|
|
||||||
};
|
};
|
||||||
|
|
||||||
typedef struct Chapter Chapter;
|
typedef struct Chapter Chapter;
|
||||||
|
@ -323,6 +290,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 */,
|
||||||
|
@ -399,8 +367,4 @@ X const char *cs_GetLastError(CompressedStream *cs);
|
||||||
|
|
||||||
#undef X
|
#undef X
|
||||||
|
|
||||||
#ifdef _MSC_VER
|
|
||||||
#pragma warning(default: 4201)
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -222,9 +222,6 @@ const AegiVideoFrame FFmpegSourceVideoProvider::GetFrame(int _n, int FormatType)
|
||||||
// this is what we'll return eventually
|
// this is what we'll return eventually
|
||||||
AegiVideoFrame &DstFrame = CurFrame;
|
AegiVideoFrame &DstFrame = CurFrame;
|
||||||
|
|
||||||
// FIXME: find out how this actually works with ffmpeg
|
|
||||||
//bool big_endian = Endian::BigToMachine((unsigned int)1)==(unsigned int)1;
|
|
||||||
|
|
||||||
// choose output format
|
// choose output format
|
||||||
if (FormatType & FORMAT_RGB32) {
|
if (FormatType & FORMAT_RGB32) {
|
||||||
DstFormat = FFMS_GetPixFmt("bgra");
|
DstFormat = FFMS_GetPixFmt("bgra");
|
||||||
|
|
Loading…
Reference in New Issue