MatroskaParser.c

00001 00002 #ifndef WIN32 00003 00004 /* 00005 00006 * Copyright (c) 2004-2005 Mike Matsnev. All Rights Reserved. 00007 00008 * 00009 00010 * Redistribution and use in source and binary forms, with or without 00011 00012 * modification, are permitted provided that the following conditions 00013 00014 * are met: 00015 00016 * 00017 00018 * 1. Redistributions of source code must retain the above copyright 00019 00020 * notice immediately at the beginning of the file, without modification, 00021 00022 * this list of conditions, and the following disclaimer. 00023 00024 * 2. Redistributions in binary form must reproduce the above copyright 00025 00026 * notice, this list of conditions and the following disclaimer in the 00027 00028 * documentation and/or other materials provided with the distribution. 00029 00030 * 3. Absolutely no warranty of function or purpose is made by the author 00031 00032 * Mike Matsnev. 00033 00034 * 00035 00036 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 00037 00038 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 00039 00040 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 00041 00042 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 00043 00044 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 00045 00046 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 00047 00048 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 00049 00050 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 00051 00052 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 00053 00054 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 00055 00056 * 00057 00058 * $Id: MatroskaParser.c,v 1.6 2006/04/05 08:58:50 mkropfbe Exp $ 00059 00060 * 00061 00062 */ 00063 00064 00065 00066 #include <stdlib.h> 00067 00068 #include <stdarg.h> 00069 00070 #include <stdio.h> 00071 00072 #include <string.h> 00073 00074 #include <setjmp.h> 00075 00076 00077 00078 #ifdef _WIN32 00079 00080 // MS names some functions differently 00081 00082 #define alloca _alloca 00083 00084 #define inline __inline 00085 00086 00087 00088 #include <tchar.h> 00089 00090 #endif 00091 00092 00093 00094 #ifndef EVCBUG 00095 00096 #define EVCBUG 00097 00098 #endif 00099 00100 00101 00102 #include "MatroskaParser.h" 00103 00104 00105 #ifdef MATROSKA_COMPRESSION_SUPPORT 00106 00107 #include <zlib.h> 00108 00109 #endif 00110 00111 #define EBML_VERSION 1 00112 00113 #define EBML_MAX_ID_LENGTH 4 00114 00115 #define EBML_MAX_SIZE_LENGTH 8 00116 00117 #define MATROSKA_VERSION 2 00118 00119 #define MATROSKA_DOCTYPE "matroska" 00120 00121 00122 00123 #define MAX_STRING_LEN 1023 00124 00125 #define QSEGSIZE 512 00126 00127 #define MAX_TRACKS 32 00128 00129 #define MAX_READAHEAD (256*1024) 00130 00131 00132 00133 #define MAXCLUSTER (64*1048576) 00134 00135 #define MAXFRAME (4*1048576) 00136 00137 00138 00139 #ifdef WIN32 00140 00141 #define LL(x) x##i64 00142 00143 #define ULL(x) x##ui64 00144 00145 #else 00146 00147 #define LL(x) x##ll 00148 00149 #define ULL(x) x##ull 00150 00151 #endif 00152 00153 00154 00155 #define MAXU64 ULL(0xffffffffffffffff) 00156 00157 #define ONE ULL(1) 00158 00159 00160 00161 // compatibility 00162 00163 static char *mystrdup(struct InputStream *is,const char *src) { 00164 00165 size_t len; 00166 00167 char *dst; 00168 00169 00170 00171 if (src==NULL) 00172 00173 return NULL; 00174 00175 00176 00177 len = strlen(src); 00178 00179 dst = is->memalloc(is,len+1); 00180 00181 if (dst==NULL) 00182 00183 return NULL; 00184 00185 00186 00187 memcpy(dst,src,len+1); 00188 00189 00190 00191 return dst; 00192 00193 } 00194 00195 00196 00197 00198 00199 00200 struct Cue { 00201 00202 ulonglong Time; 00203 00204 ulonglong Position; 00205 00206 ulonglong Block; 00207 00208 unsigned char Track; 00209 00210 }; 00211 00212 00213 00214 struct QueueEntry { 00215 00216 struct QueueEntry *next; 00217 00218 unsigned int Length; 00219 00220 00221 00222 ulonglong Start; 00223 00224 ulonglong End; 00225 00226 ulonglong Position; 00227 00228 00229 00230 unsigned int flags; 00231 00232 }; 00233 00234 00235 00236 struct Queue { 00237 00238 struct QueueEntry *head; 00239 00240 struct QueueEntry *tail; 00241 00242 }; 00243 00244 00245 00246 #define MPF_ERROR 0x10000 00247 00248 #define IBSZ 1024 00249 00250 00251 00252 #define RBRESYNC 1 00253 00254 00255 00256 struct MatroskaFile { 00257 00258 // parser config 00259 00260 unsigned flags; 00261 00262 00263 00264 // input 00265 00266 InputStream *cache; 00267 00268 00269 00270 // internal buffering 00271 00272 char inbuf[IBSZ]; 00273 00274 ulonglong bufbase; // file offset of the first byte in buffer 00275 00276 int bufpos; // current read position in buffer 00277 00278 int buflen; // valid bytes in buffer 00279 00280 00281 00282 // error reporting 00283 00284 char errmsg[128]; 00285 00286 jmp_buf jb; 00287 00288 00289 00290 // pointers to key elements 00291 00292 ulonglong pSegment; 00293 00294 ulonglong pSeekHead; 00295 00296 ulonglong pSegmentInfo; 00297 00298 ulonglong pCluster; 00299 00300 ulonglong pTracks; 00301 00302 ulonglong pCues; 00303 00304 ulonglong pAttachments; 00305 00306 ulonglong pChapters; 00307 00308 ulonglong pTags; 00309 00310 00311 00312 // flags for key elements 00313 00314 struct { 00315 00316 unsigned int SegmentInfo:1; 00317 00318 unsigned int Cluster:1; 00319 00320 unsigned int Tracks:1; 00321 00322 unsigned int Cues:1; 00323 00324 unsigned int Attachments:1; 00325 00326 unsigned int Chapters:1; 00327 00328 unsigned int Tags:1; 00329 00330 } seen; 00331 00332 00333 00334 // file info 00335 00336 ulonglong firstTimecode; 00337 00338 00339 00340 // SegmentInfo 00341 00342 struct SegmentInfo Seg; 00343 00344 00345 00346 // Tracks 00347 00348 unsigned int nTracks,nTracksSize; 00349 00350 struct TrackInfo **Tracks; 00351 00352 00353 00354 // Queues 00355 00356 struct QueueEntry *QFreeList; 00357 00358 unsigned int nQBlocks,nQBlocksSize; 00359 00360 struct QueueEntry **QBlocks; 00361 00362 struct Queue *Queues; 00363 00364 ulonglong readPosition; 00365 00366 unsigned int trackMask; 00367 00368 ulonglong pSegmentTop; // offset of next byte after the segment 00369 00370 ulonglong tcCluster; // current cluster timecode 00371 00372 00373 00374 // Cues 00375 00376 unsigned int nCues,nCuesSize; 00377 00378 struct Cue *Cues; 00379 00380 00381 00382 // Attachments 00383 00384 unsigned int nAttachments,nAttachmentsSize; 00385 00386 struct Attachment *Attachments; 00387 00388 00389 00390 // Chapters 00391 00392 unsigned int nChapters,nChaptersSize; 00393 00394 struct Chapter *Chapters; 00395 00396 00397 00398 // Tags 00399 00400 unsigned int nTags,nTagsSize; 00401 00402 struct Tag *Tags; 00403 00404 }; 00405 00406 00407 00409 00410 // error reporting 00411 00412 static void myvsnprintf_string(char **pdest,char *de,const char *str) { 00413 00414 char *dest = *pdest; 00415 00416 00417 00418 while (dest < de && *str) 00419 00420 *dest++ = *str++; 00421 00422 00423 00424 *pdest = dest; 00425 00426 } 00427 00428 00429 00430 static void myvsnprintf_uint_impl(char **pdest,char *de,int width,int zero, 00431 00432 int neg,unsigned base,int letter, 00433 00434 int ms,ulonglong val) 00435 00436 { 00437 00438 char *dest = *pdest; 00439 00440 char tmp[21]; /* enough for 64 bit ints */ 00441 00442 char *np = tmp + sizeof(tmp); 00443 00444 int rw,pad,trail; 00445 00446 char pc = zero ? '0' : ' '; 00447 00448 00449 00450 *--np = '\0'; 00451 00452 if (val == 0) 00453 00454 *--np = '0'; 00455 00456 else 00457 00458 while (val != 0) { 00459 00460 int rem = (int)(val % base); 00461 00462 val = val / base; 00463 00464 00465 00466 *--np = rem < 10 ? rem + '0' : rem - 10 + letter; 00467 00468 } 00469 00470 00471 00472 rw = (int)(tmp - np + sizeof(tmp) - 1); 00473 00474 if (ms) 00475 00476 ++rw; 00477 00478 00479 00480 pad = trail = 0; 00481 00482 00483 00484 if (rw < width) 00485 00486 pad = width - rw; 00487 00488 00489 00490 if (neg) 00491 00492 trail = pad, pad = 0; 00493 00494 00495 00496 if (dest < de && ms) 00497 00498 *dest++ = '-'; 00499 00500 00501 00502 while (dest < de && pad--) 00503 00504 *dest++ = pc; 00505 00506 00507 00508 while (dest < de && *np) 00509 00510 *dest++ = *np++; 00511 00512 00513 00514 while (dest < de && trail--) 00515 00516 *dest++ = ' '; 00517 00518 00519 00520 *pdest = dest; 00521 00522 } 00523 00524 00525 00526 static void myvsnprintf_uint(char **pdest,char *de,int width,int zero, 00527 00528 int neg,unsigned base,int letter, 00529 00530 ulonglong val) 00531 00532 { 00533 00534 myvsnprintf_uint_impl(pdest,de,width,zero,neg,base,letter,0,val); 00535 00536 } 00537 00538 00539 00540 static void myvsnprintf_int(char **pdest,char *de,int width,int zero, 00541 00542 int neg,unsigned base,int letter, 00543 00544 longlong val) 00545 00546 { 00547 00548 if (val < 0) 00549 00550 myvsnprintf_uint_impl(pdest,de,width,zero,neg,base,letter,1,-val); 00551 00552 else 00553 00554 myvsnprintf_uint_impl(pdest,de,width,zero,neg,base,letter,0,val); 00555 00556 } 00557 00558 00559 00560 static void myvsnprintf(char *dest,unsigned dsize,const char *fmt,va_list ap) { 00561 00562 // s,d,x,u,ll 00563 00564 char *de = dest + dsize - 1; 00565 00566 int state = 0, width, zero, neg, ll; 00567 00568 00569 00570 if (dsize <= 1) { 00571 00572 if (dsize > 0) 00573 00574 *dest = '\0'; 00575 00576 return; 00577 00578 } 00579 00580 00581 00582 while (*fmt && dest < de) 00583 00584 switch (state) { 00585 00586 case 0: 00587 00588 if (*fmt == '%') { 00589 00590 ++fmt; 00591 00592 state = 1; 00593 00594 width = zero = neg = ll = 0; 00595 00596 } else 00597 00598 *dest++ = *fmt++; 00599 00600 break; 00601 00602 case 1: 00603 00604 if (*fmt == '-') { 00605 00606 neg = 1; 00607 00608 ++fmt; 00609 00610 state = 2; 00611 00612 break; 00613 00614 } 00615 00616 if (*fmt == '0') 00617 00618 zero = 1; 00619 00620 state = 2; 00621 00622 case 2: 00623 00624 if (*fmt >= '0' && *fmt <= '9') { 00625 00626 width = width * 10 + *fmt++ - '0'; 00627 00628 break; 00629 00630 } 00631 00632 state = 3; 00633 00634 case 3: 00635 00636 if (*fmt == 'l') { 00637 00638 ++ll; 00639 00640 ++fmt; 00641 00642 break; 00643 00644 } 00645 00646 state = 4; 00647 00648 case 4: 00649 00650 switch (*fmt) { 00651 00652 case 's': 00653 00654 myvsnprintf_string(&dest,de,va_arg(ap,const char *)); 00655 00656 break; 00657 00658 case 'd': 00659 00660 switch (ll) { 00661 00662 case 0: 00663 00664 myvsnprintf_int(&dest,de,width,zero,neg,10,'a',va_arg(ap,int)); 00665 00666 break; 00667 00668 case 1: 00669 00670 myvsnprintf_int(&dest,de,width,zero,neg,10,'a',va_arg(ap,long)); 00671 00672 break; 00673 00674 case 2: 00675 00676 myvsnprintf_int(&dest,de,width,zero,neg,10,'a',va_arg(ap,longlong)); 00677 00678 break; 00679 00680 } 00681 00682 break; 00683 00684 case 'u': 00685 00686 switch (ll) { 00687 00688 case 0: 00689 00690 myvsnprintf_uint(&dest,de,width,zero,neg,10,'a',va_arg(ap,unsigned int)); 00691 00692 break; 00693 00694 case 1: 00695 00696 myvsnprintf_uint(&dest,de,width,zero,neg,10,'a',va_arg(ap,unsigned long)); 00697 00698 break; 00699 00700 case 2: 00701 00702 myvsnprintf_uint(&dest,de,width,zero,neg,10,'a',va_arg(ap,ulonglong)); 00703 00704 break; 00705 00706 } 00707 00708 break; 00709 00710 case 'x': 00711 00712 switch (ll) { 00713 00714 case 0: 00715 00716 myvsnprintf_uint(&dest,de,width,zero,neg,16,'a',va_arg(ap,unsigned int)); 00717 00718 break; 00719 00720 case 1: 00721 00722 myvsnprintf_uint(&dest,de,width,zero,neg,16,'a',va_arg(ap,unsigned long)); 00723 00724 break; 00725 00726 case 2: 00727 00728 myvsnprintf_uint(&dest,de,width,zero,neg,16,'a',va_arg(ap,ulonglong)); 00729 00730 break; 00731 00732 } 00733 00734 break; 00735 00736 case 'X': 00737 00738 switch (ll) { 00739 00740 case 0: 00741 00742 myvsnprintf_uint(&dest,de,width,zero,neg,16,'A',va_arg(ap,unsigned int)); 00743 00744 break; 00745 00746 case 1: 00747 00748 myvsnprintf_uint(&dest,de,width,zero,neg,16,'A',va_arg(ap,unsigned long)); 00749 00750 break; 00751 00752 case 2: 00753 00754 myvsnprintf_uint(&dest,de,width,zero,neg,16,'A',va_arg(ap,ulonglong)); 00755 00756 break; 00757 00758 } 00759 00760 break; 00761 00762 default: 00763 00764 break; 00765 00766 } 00767 00768 ++fmt; 00769 00770 state = 0; 00771 00772 break; 00773 00774 default: 00775 00776 state = 0; 00777 00778 break; 00779 00780 } 00781 00782 *dest = '\0'; 00783 00784 } 00785 00786 00787 00788 static void errorjmp(MatroskaFile *mf,const char *fmt, ...) { 00789 00790 va_list ap; 00791 00792 00793 00794 va_start(ap, fmt); 00795 00796 myvsnprintf(mf->errmsg,sizeof(mf->errmsg),fmt,ap); 00797 00798 va_end(ap); 00799 00800 00801 00802 mf->flags |= MPF_ERROR; 00803 00804 00805 00806 longjmp(mf->jb,1); 00807 00808 } 00809 00810 00811 00813 00814 // arrays 00815 00816 static void *ArrayAlloc(MatroskaFile *mf,void **base, 00817 00818 unsigned *cur,unsigned *max,unsigned elem_size) 00819 00820 { 00821 00822 if (*cur>=*max) { 00823 00824 void *np; 00825 00826 unsigned newsize = *max * 2; 00827 00828 if (newsize==0) 00829 00830 newsize = 1; 00831 00832 00833 00834 np = mf->cache->memrealloc(mf->cache,*base,newsize*elem_size); 00835 00836 if (np==NULL) 00837 00838 errorjmp(mf,"Out of memory in ArrayAlloc"); 00839 00840 00841 00842 *base = np; 00843 00844 *max = newsize; 00845 00846 } 00847 00848 00849 00850 return (char*)*base + elem_size * (*cur)++; 00851 00852 } 00853 00854 00855 00856 static void ArrayReleaseMemory(MatroskaFile *mf,void **base, 00857 00858 unsigned cur,unsigned *max,unsigned elem_size) 00859 00860 { 00861 00862 if (cur<*max) { 00863 00864 void *np = mf->cache->memrealloc(mf->cache,*base,cur*elem_size); 00865 00866 *base = np; 00867 00868 *max = cur; 00869 00870 } 00871 00872 } 00873 00874 00875 00876 00877 00878 #define ASGET(f,s,name) ArrayAlloc((f),(void**)&(s)->name,&(s)->n##name,&(s)->n##name##Size,sizeof(*((s)->name))) 00879 00880 #define AGET(f,name) ArrayAlloc((f),(void**)&(f)->name,&(f)->n##name,&(f)->n##name##Size,sizeof(*((f)->name))) 00881 00882 #define ARELEASE(f,s,name) ArrayReleaseMemory((f),(void**)&(s)->name,(s)->n##name,&(s)->n##name##Size,sizeof(*((s)->name))) 00883 00884 00885 00887 00888 // queues 00889 00890 static struct QueueEntry *QPut(struct Queue *q,struct QueueEntry *qe) { 00891 00892 if (q->tail) 00893 00894 q->tail->next = qe; 00895 00896 qe->next = NULL; 00897 00898 q->tail = qe; 00899 00900 if (q->head==NULL) 00901 00902 q->head = qe; 00903 00904 00905 00906 return qe; 00907 00908 } 00909 00910 00911 00912 static struct QueueEntry *QGet(struct Queue *q) { 00913 00914 struct QueueEntry *qe = q->head; 00915 00916 if (qe == NULL) 00917 00918 return NULL; 00919 00920 q->head = qe->next; 00921 00922 if (q->tail == qe) 00923 00924 q->tail = NULL; 00925 00926 return qe; 00927 00928 } 00929 00930 00931 00932 static struct QueueEntry *QAlloc(MatroskaFile *mf) { 00933 00934 struct QueueEntry *qe,**qep; 00935 00936 if (mf->QFreeList == NULL) { 00937 00938 unsigned i; 00939 00940 00941 00942 qep = AGET(mf,QBlocks); 00943 00944 00945 00946 *qep = mf->cache->memalloc(mf->cache,QSEGSIZE * sizeof(*qe)); 00947 00948 if (*qep == NULL) 00949 00950 errorjmp(mf,"Ouf of memory"); 00951 00952 00953 00954 qe = *qep; 00955 00956 00957 00958 for (i=0;i<QSEGSIZE-1;++i) 00959 00960 qe[i].next = qe+i+1; 00961 00962 qe[QSEGSIZE-1].next = NULL; 00963 00964 00965 00966 mf->QFreeList = qe; 00967 00968 } 00969 00970 00971 00972 qe = mf->QFreeList; 00973 00974 mf->QFreeList = qe->next; 00975 00976 00977 00978 return qe; 00979 00980 } 00981 00982 00983 00984 static inline void QFree(MatroskaFile *mf,struct QueueEntry *qe) { 00985 00986 qe->next = mf->QFreeList; 00987 00988 mf->QFreeList = qe; 00989 00990 } 00991 00992 00993 00994 // fill the buffer at current position 00995 00996 static void fillbuf(MatroskaFile *mf) { 00997 00998 int rd; 00999 01000 01001 01002 // advance buffer pointers 01003 01004 mf->bufbase += mf->buflen; 01005 01006 mf->buflen = mf->bufpos = 0; 01007 01008 01009 01010 // get the relevant page 01011 01012 rd = mf->cache->read(mf->cache, mf->bufbase, mf->inbuf, IBSZ); 01013 01014 if (rd<0) 01015 01016 errorjmp(mf,"I/O Error: %s",mf->cache->geterror(mf->cache)); 01017 01018 01019 01020 mf->buflen = rd; 01021 01022 } 01023 01024 01025 01026 // fill the buffer and return next char 01027 01028 static int nextbuf(MatroskaFile *mf) { 01029 01030 fillbuf(mf); 01031 01032 01033 01034 if (mf->bufpos < mf->buflen) 01035 01036 return (unsigned char)(mf->inbuf[mf->bufpos++]); 01037 01038 01039 01040 return EOF; 01041 01042 } 01043 01044 01045 01046 static inline int readch(MatroskaFile *mf) { 01047 01048 return mf->bufpos < mf->buflen ? (unsigned char)(mf->inbuf[mf->bufpos++]) : nextbuf(mf); 01049 01050 } 01051 01052 01053 01054 static inline ulonglong filepos(MatroskaFile *mf) { 01055 01056 return mf->bufbase + mf->bufpos; 01057 01058 } 01059 01060 01061 01062 static void readbytes(MatroskaFile *mf,void *buffer,int len) { 01063 01064 char *cp = buffer; 01065 01066 int nb = mf->buflen - mf->bufpos; 01067 01068 01069 01070 if (nb > len) 01071 01072 nb = len; 01073 01074 01075 01076 memcpy(cp, mf->inbuf + mf->bufpos, nb); 01077 01078 mf->bufpos += nb; 01079 01080 len -= nb; 01081 01082 cp += nb; 01083 01084 01085 01086 if (len>0) { 01087 01088 mf->bufbase += mf->buflen; 01089 01090 mf->bufpos = mf->buflen = 0; 01091 01092 01093 01094 nb = mf->cache->read(mf->cache, mf->bufbase, cp, len); 01095 01096 if (nb<0) 01097 01098 errorjmp(mf,"I/O Error: %s",mf->cache->geterror(mf->cache)); 01099 01100 if (nb != len) 01101 01102 errorjmp(mf,"Short read: got %d bytes of %d",nb,len); 01103 01104 mf->bufbase += len; 01105 01106 } 01107 01108 } 01109 01110 01111 01112 static void skipbytes(MatroskaFile *mf,ulonglong len) { 01113 01114 int nb = mf->buflen - mf->bufpos; 01115 01116 01117 01118 if (nb > len) 01119 01120 nb = (int)len; 01121 01122 01123 01124 mf->bufpos += nb; 01125 01126 len -= nb; 01127 01128 01129 01130 if (len>0) { 01131 01132 mf->bufbase += mf->buflen; 01133 01134 mf->bufpos = mf->buflen = 0; 01135 01136 01137 01138 mf->bufbase += len; 01139 01140 } 01141 01142 } 01143 01144 01145 01146 static void seek(MatroskaFile *mf,ulonglong pos) { 01147 01148 // see if pos is inside buffer 01149 01150 if (pos>=mf->bufbase && pos<mf->bufbase+mf->buflen) 01151 01152 mf->bufpos = (unsigned)(pos - mf->bufbase); 01153 01154 else { 01155 01156 // invalidate buffer and set pointer 01157 01158 mf->bufbase = pos; 01159 01160 mf->buflen = mf->bufpos = 0; 01161 01162 } 01163 01164 } 01165 01166 01167 01169 01170 // floating point 01171 01172 static inline MKFLOAT mkfi(int i) { 01173 01174 #ifdef MATROSKA_INTEGER_ONLY 01175 01176 MKFLOAT f; 01177 01178 f.v = (longlong)i << 32; 01179 01180 return f; 01181 01182 #else 01183 01184 return i; 01185 01186 #endif 01187 01188 } 01189 01190 01191 01192 static inline longlong mul3(MKFLOAT scale,longlong tc) { 01193 01194 #ifdef MATROSKA_INTEGER_ONLY 01195 01196 // x1 x0 01197 01198 // y1 y0 01199 01200 // -------------- 01201 01202 // x0*y0 01203 01204 // x1*y0 01205 01206 // x0*y1 01207 01208 // x1*y1 01209 01210 // -------------- 01211 01212 // .. r1 r0 .. 01213 01214 // 01215 01216 // r = ((x0*y0) >> 32) + (x1*y0) + (x0*y1) + ((x1*y1) << 32) 01217 01218 unsigned x0,x1,y0,y1; 01219 01220 ulonglong p; 01221 01222 char sign = 0; 01223 01224 01225 01226 if (scale.v < 0) 01227 01228 sign = !sign, scale.v = -scale.v; 01229 01230 if (tc < 0) 01231 01232 sign = !sign, tc = -tc; 01233 01234 01235 01236 x0 = (unsigned)scale.v; 01237 01238 x1 = (unsigned)((ulonglong)scale.v >> 32); 01239 01240 y0 = (unsigned)tc; 01241 01242 y1 = (unsigned)((ulonglong)tc >> 32); 01243 01244 01245 01246 p = (ulonglong)x0*y0 >> 32; 01247 01248 p += (ulonglong)x0*y1; 01249 01250 p += (ulonglong)x1*y0; 01251 01252 p += (ulonglong)(x1*y1) << 32; 01253 01254 01255 01256 return p; 01257 01258 #else 01259 01260 return (longlong)(scale * tc); 01261 01262 #endif 01263 01264 } 01265 01266 01267 01269 01270 // EBML support 01271 01272 static int readID(MatroskaFile *mf) { 01273 01274 int c1,c2,c3,c4; 01275 01276 01277 01278 c1 = readch(mf); 01279 01280 if (c1 == EOF) 01281 01282 return EOF; 01283 01284 01285 01286 if (c1 & 0x80) 01287 01288 return c1; 01289 01290 01291 01292 if ((c1 & 0xf0) == 0) 01293 01294 errorjmp(mf,"Invalid first byte of EBML ID: %02X",c1); 01295 01296 01297 01298 c2 = readch(mf); 01299 01300 if (c2 == EOF) 01301 01302 fail: 01303 01304 errorjmp(mf,"Got EOF while reading EBML ID"); 01305 01306 01307 01308 if ((c1 & 0xc0) == 0x40) 01309 01310 return (c1<<8) | c2; 01311 01312 01313 01314 c3 = readch(mf); 01315 01316 if (c3 == EOF) 01317 01318 goto fail; 01319 01320 01321 01322 if ((c1 & 0xe0) == 0x20) 01323 01324 return (c1<<16) | (c2<<8) | c3; 01325 01326 01327 01328 c4 = readch(mf); 01329 01330 if (c4 == EOF) 01331 01332 goto fail; 01333 01334 01335 01336 if ((c1 & 0xf0) == 0x10) 01337 01338 return (c1<<24) | (c2<<16) | (c3<<8) | c4; 01339 01340 01341 01342 return 0; // NOT REACHED 01343 01344 } 01345 01346 01347 01348 static ulonglong readVLUIntImp(MatroskaFile *mf,int *mask) { 01349 01350 int c,d,m; 01351 01352 ulonglong v = 0; 01353 01354 01355 01356 c = readch(mf); 01357 01358 if (c == EOF) 01359 01360 return EOF; 01361 01362 01363 01364 if (c == 0) 01365 01366 errorjmp(mf,"Invalid first byte of EBML integer: 0"); 01367 01368 01369 01370 for (m=0;;++m) { 01371 01372 if (c & (0x80 >> m)) { 01373 01374 c &= 0x7f >> m; 01375 01376 if (mask) 01377 01378 *mask = m; 01379 01380 return v | ((ulonglong)c << m*8); 01381 01382 } 01383 01384 d = readch(mf); 01385 01386 if (d == EOF) 01387 01388 errorjmp(mf,"Got EOF while reading EBML unsigned integer"); 01389 01390 v = (v<<8) | d; 01391 01392 } 01393 01394 // NOT REACHED 01395 01396 } 01397 01398 01399 01400 static inline ulonglong readVLUInt(MatroskaFile *mf) { 01401 01402 return readVLUIntImp(mf,NULL); 01403 01404 } 01405 01406 01407 01408 static ulonglong readSize(MatroskaFile *mf) { 01409 01410 int m; 01411 01412 ulonglong v = readVLUIntImp(mf,&m); 01413 01414 01415 01416 // see if it's unspecified 01417 01418 if (v == (MAXU64 >> (57-m*7))) 01419 01420 errorjmp(mf,"Unspecified element size is not supported here."); 01421 01422 01423 01424 return v; 01425 01426 } 01427 01428 01429 01430 static inline longlong readVLSInt(MatroskaFile *mf) { 01431 01432 static longlong bias[8] = { (ONE<<6)-1, (ONE<<13)-1, (ONE<<20)-1, (ONE<<27)-1, 01433 01434 (ONE<<34)-1, (ONE<<41)-1, (ONE<<48)-1, (ONE<<55)-1 }; 01435 01436 01437 01438 int m; 01439 01440 longlong v = readVLUIntImp(mf,&m); 01441 01442 01443 01444 return v - bias[m]; 01445 01446 } 01447 01448 01449 01450 static ulonglong readUInt(MatroskaFile *mf,unsigned int len) { 01451 01452 int c; 01453 01454 unsigned int m = len; 01455 01456 ulonglong v = 0; 01457 01458 01459 01460 if (len==0) 01461 01462 return v; 01463 01464 if (len>8) 01465 01466 errorjmp(mf,"Unsupported integer size in readUInt: %u",len); 01467 01468 01469 01470 do { 01471 01472 c = readch(mf); 01473 01474 if (c == EOF) 01475 01476 errorjmp(mf,"Got EOF while reading EBML unsigned integer"); 01477 01478 v = (v<<8) | c; 01479 01480 } while (--m); 01481 01482 01483 01484 return v; 01485 01486 } 01487 01488 01489 01490 static inline longlong readSInt(MatroskaFile *mf,unsigned int len) { 01491 01492 longlong v = readUInt(mf,(unsigned)len); 01493 01494 int s = 64 - (len<<3); 01495 01496 return (v << s) >> s; 01497 01498 } 01499 01500 01501 01502 static MKFLOAT readFloat(MatroskaFile *mf,unsigned int len) { 01503 01504 #ifdef MATROSKA_INTEGER_ONLY 01505 01506 MKFLOAT f; 01507 01508 int shift; 01509 01510 #else 01511 01512 union { 01513 01514 unsigned int ui; 01515 01516 ulonglong ull; 01517 01518 float f; 01519 01520 double d; 01521 01522 } u; 01523 01524 #endif 01525 01526 01527 01528 if (len!=4 && len!=8) 01529 01530 errorjmp(mf,"Invalid float size in readFloat: %u",len); 01531 01532 01533 01534 #ifdef MATROSKA_INTEGER_ONLY 01535 01536 if (len == 4) { 01537 01538 unsigned ui = (unsigned)readUInt(mf,(unsigned)len); 01539 01540 f.v = (ui & 0x7fffff) | 0x800000; 01541 01542 if (ui & 0x80000000) 01543 01544 f.v = -f.v; 01545 01546 shift = (ui >> 23) & 0xff; 01547 01548 if (shift == 0) // assume 0 01549 01550 zero: 01551 01552 shift = 0, f.v = 0; 01553 01554 else if (shift == 255) 01555 01556 inf: 01557 01558 if (ui & 0x80000000) 01559 01560 f.v = LL(0x8000000000000000); 01561 01562 else 01563 01564 f.v = LL(0x7fffffffffffffff); 01565 01566 else { 01567 01568 shift += -127 + 9; 01569 01570 if (shift > 39) 01571 01572 goto inf; 01573 01574 shift: 01575 01576 if (shift < 0) 01577 01578 f.v = f.v >> -shift; 01579 01580 else if (shift > 0) 01581 01582 f.v = f.v << shift; 01583 01584 } 01585 01586 } else if (len == 8) { 01587 01588 ulonglong ui = readUInt(mf,(unsigned)len); 01589 01590 f.v = (ui & LL(0xfffffffffffff)) | LL(0x10000000000000); 01591 01592 if (ui & 0x80000000) 01593 01594 f.v = -f.v; 01595 01596 shift = (int)((ui >> 52) & 0x7ff); 01597 01598 if (shift == 0) // assume 0 01599 01600 goto zero; 01601 01602 else if (shift == 2047) 01603 01604 goto inf; 01605 01606 else { 01607 01608 shift += -1023 - 20; 01609 01610 if (shift > 10) 01611 01612 goto inf; 01613 01614 goto shift; 01615 01616 } 01617 01618 } 01619 01620 01621 01622 return f; 01623 01624 #else 01625 01626 if (len==4) { 01627 01628 u.ui = (unsigned int)readUInt(mf,(unsigned)len); 01629 01630 return u.f; 01631 01632 } 01633 01634 01635 01636 if (len==8) { 01637 01638 u.ull = readUInt(mf,(unsigned)len); 01639 01640 return u.d; 01641 01642 } 01643 01644 01645 01646 return 0; 01647 01648 #endif 01649 01650 } 01651 01652 01653 01654 static void readString(MatroskaFile *mf,ulonglong len,char *buffer,int buflen) { 01655 01656 int nread; 01657 01658 01659 01660 if (buflen<1) 01661 01662 errorjmp(mf,"Invalid buffer size in readString: %d",buflen); 01663 01664 01665 01666 nread = buflen - 1; 01667 01668 01669 01670 if (nread > len) 01671 01672 nread = (int)len; 01673 01674 01675 01676 readbytes(mf,buffer,nread); 01677 01678 len -= nread; 01679 01680 01681 01682 if (len>0) 01683 01684 skipbytes(mf,len); 01685 01686 01687 01688 buffer[nread] = '\0'; 01689 01690 } 01691 01692 01693 01695 01696 // file parser 01697 01698 #define FOREACH(f,tl) \ 01699 { \ 01700 ulonglong tmplen = (tl); \ 01701 { \ 01702 ulonglong start = filepos(f); \ 01703 ulonglong cur,len; \ 01704 int id; \ 01705 for (;;) { \ 01706 cur = filepos(mf); \ 01707 if (cur == start + tmplen) \ 01708 break; \ 01709 id = readID(f); \ 01710 if (id==EOF) \ 01711 errorjmp(mf,"Unexpected EOF while reading EBML container"); \ 01712 len = readSize(mf); \ 01713 switch (id) { 01714 01715 01716 #define ENDFOR1(f) \ 01717 default: \ 01718 skipbytes(f,len); \ 01719 break; \ 01720 } 01721 01722 #define ENDFOR2() \ 01723 } \ 01724 } \ 01725 } 01726 01727 01728 01729 #define ENDFOR(f) ENDFOR1(f) ENDFOR2() 01730 01731 01732 01733 #define myalloca(f,c) alloca(c) 01734 01735 #define STRGETF(f,v,len,func) \ 01736 { \ 01737 char *TmpVal; \ 01738 unsigned TmpLen = (len)>MAX_STRING_LEN ? MAX_STRING_LEN : (unsigned)(len); \ 01739 TmpVal = func(f->cache,TmpLen+1); \ 01740 if (TmpVal == NULL) \ 01741 errorjmp(mf,"Out of memory"); \ 01742 readString(f,len,TmpVal,TmpLen+1); \ 01743 (v) = TmpVal; \ 01744 } 01745 01746 01747 01748 #define STRGETA(f,v,len) STRGETF(f,v,len,myalloca) 01749 01750 #define STRGETM(f,v,len) STRGETF(f,v,len,f->cache->memalloc) 01751 01752 01753 01754 static int IsWritingApp(MatroskaFile *mf,const char *str) { 01755 01756 const char *cp = mf->Seg.WritingApp; 01757 01758 if (!cp) 01759 01760 return 0; 01761 01762 01763 01764 while (*str && *str++==*cp++) ; 01765 01766 01767 01768 return !*str; 01769 01770 } 01771 01772 01773 01774 static void parseEBML(MatroskaFile *mf,ulonglong toplen) { 01775 01776 ulonglong v; 01777 01778 char buf[32]; 01779 01780 01781 01782 FOREACH(mf,toplen) 01783 01784 case 0x4286: // Version 01785 01786 v = readUInt(mf,(unsigned)len); 01787 01788 break; 01789 01790 case 0x42f7: // ReadVersion 01791 01792 v = readUInt(mf,(unsigned)len); 01793 01794 if (v > EBML_VERSION) 01795 01796 errorjmp(mf,"File requires version %d EBML parser",(int)v); 01797 01798 break; 01799 01800 case 0x42f2: // MaxIDLength 01801 01802 v = readUInt(mf,(unsigned)len); 01803 01804 if (v > EBML_MAX_ID_LENGTH) 01805 01806 errorjmp(mf,"File has identifiers longer than %d",(int)v); 01807 01808 break; 01809 01810 case 0x42f3: // MaxSizeLength 01811 01812 v = readUInt(mf,(unsigned)len); 01813 01814 if (v > EBML_MAX_SIZE_LENGTH) 01815 01816 errorjmp(mf,"File has integers longer than %d",(int)v); 01817 01818 break; 01819 01820 case 0x4282: // DocType 01821 01822 readString(mf,len,buf,sizeof(buf)); 01823 01824 if (strcmp(buf,MATROSKA_DOCTYPE)) 01825 01826 errorjmp(mf,"Unsupported DocType: %s",buf); 01827 01828 break; 01829 01830 case 0x4287: // DocTypeVersion 01831 01832 v = readUInt(mf,(unsigned)len); 01833 01834 break; 01835 01836 case 0x4285: // DocTypeReadVersion 01837 01838 v = readUInt(mf,(unsigned)len); 01839 01840 if (v > MATROSKA_VERSION) 01841 01842 errorjmp(mf,"File requires version %d Matroska parser",(int)v); 01843 01844 break; 01845 01846 ENDFOR(mf); 01847 01848 } 01849 01850 01851 01852 static void parseSeekEntry(MatroskaFile *mf,ulonglong toplen) { 01853 01854 int seekid = 0; 01855 01856 ulonglong pos = (ulonglong)-1; 01857 01858 01859 01860 FOREACH(mf,toplen) 01861 01862 case 0x53ab: // SeekID 01863 01864 if (len>EBML_MAX_ID_LENGTH) 01865 01866 errorjmp(mf,"Invalid ID size in parseSeekEntry: %d\n",(int)len); 01867 01868 seekid = (int)readUInt(mf,(unsigned)len); 01869 01870 break; 01871 01872 case 0x53ac: // SeekPos 01873 01874 pos = readUInt(mf,(unsigned)len); 01875 01876 break; 01877 01878 ENDFOR(mf); 01879 01880 01881 01882 if (pos == (ulonglong)-1) 01883 01884 errorjmp(mf,"Invalid element position in parseSeekEntry"); 01885 01886 01887 01888 pos += mf->pSegment; 01889 01890 switch (seekid) { 01891 01892 case 0x114d9b74: // next SeekHead 01893 01894 if (mf->pSeekHead) 01895 01896 errorjmp(mf,"SeekHead contains more than one SeekHead pointer"); 01897 01898 mf->pSeekHead = pos; 01899 01900 break; 01901 01902 case 0x1549a966: // SegmentInfo 01903 01904 mf->pSegmentInfo = pos; 01905 01906 break; 01907 01908 case 0x1f43b675: // Cluster 01909 01910 if (!mf->pCluster) 01911 01912 mf->pCluster = pos; 01913 01914 break; 01915 01916 case 0x1654ae6b: // Tracks 01917 01918 mf->pTracks = pos; 01919 01920 break; 01921 01922 case 0x1c53bb6b: // Cues 01923 01924 mf->pCues = pos; 01925 01926 break; 01927 01928 case 0x1941a469: // Attachments 01929 01930 mf->pAttachments = pos; 01931 01932 break; 01933 01934 case 0x1043a770: // Chapters 01935 01936 mf->pChapters = pos; 01937 01938 break; 01939 01940 case 0x1254c367: // tags 01941 01942 mf->pTags = pos; 01943 01944 break; 01945 01946 } 01947 01948 } 01949 01950 01951 01952 static void parseSeekHead(MatroskaFile *mf,ulonglong toplen) { 01953 01954 FOREACH(mf,toplen) 01955 01956 case 0x4dbb: 01957 01958 parseSeekEntry(mf,len); 01959 01960 break; 01961 01962 ENDFOR(mf); 01963 01964 } 01965 01966 01967 01968 static void parseSegmentInfo(MatroskaFile *mf,ulonglong toplen) { 01969 01970 MKFLOAT duration = mkfi(0); 01971 01972 01973 01974 if (mf->seen.SegmentInfo) { 01975 01976 skipbytes(mf,toplen); 01977 01978 return; 01979 01980 } 01981 01982 01983 01984 mf->seen.SegmentInfo = 1; 01985 01986 mf->Seg.TimecodeScale = 1000000; // Default value 01987 01988 01989 01990 FOREACH(mf,toplen) 01991 01992 case 0x73a4: // SegmentUID 01993 01994 if (len!=sizeof(mf->Seg.UID)) 01995 01996 errorjmp(mf,"SegmentUID size is not %d bytes",mf->Seg.UID); 01997 01998 readbytes(mf,mf->Seg.UID,sizeof(mf->Seg.UID)); 01999 02000 break; 02001 02002 case 0x7384: // SegmentFilename 02003 02004 STRGETM(mf,mf->Seg.Filename,len); 02005 02006 break; 02007 02008 case 0x3cb923: // PrevUID 02009 02010 if (len!=sizeof(mf->Seg.PrevUID)) 02011 02012 errorjmp(mf,"PrevUID size is not %d bytes",mf->Seg.PrevUID); 02013 02014 readbytes(mf,mf->Seg.PrevUID,sizeof(mf->Seg.PrevUID)); 02015 02016 break; 02017 02018 case 0x3c83ab: // PrevFilename 02019 02020 STRGETM(mf,mf->Seg.PrevFilename,len); 02021 02022 break; 02023 02024 case 0x3eb923: // NextUID 02025 02026 if (len!=sizeof(mf->Seg.NextUID)) 02027 02028 errorjmp(mf,"NextUID size is not %d bytes",mf->Seg.NextUID); 02029 02030 readbytes(mf,mf->Seg.NextUID,sizeof(mf->Seg.NextUID)); 02031 02032 break; 02033 02034 case 0x3e83bb: // NextFilename 02035 02036 STRGETM(mf,mf->Seg.NextFilename,len); 02037 02038 break; 02039 02040 case 0x2ad7b1: // TimecodeScale 02041 02042 mf->Seg.TimecodeScale = readUInt(mf,(unsigned)len); 02043 02044 if (mf->Seg.TimecodeScale == 0) 02045 02046 errorjmp(mf,"Segment timecode scale is zero"); 02047 02048 break; 02049 02050 case 0x4489: // Duration 02051 02052 duration = readFloat(mf,(unsigned)len); 02053 02054 break; 02055 02056 case 0x4461: // DateUTC 02057 02058 mf->Seg.DateUTC = readUInt(mf,(unsigned)len); 02059 02060 break; 02061 02062 case 0x7ba9: // Title 02063 02064 STRGETM(mf,mf->Seg.Title,len); 02065 02066 break; 02067 02068 case 0x4d80: // MuxingApp 02069 02070 STRGETM(mf,mf->Seg.MuxingApp,len); 02071 02072 break; 02073 02074 case 0x5741: // WritingApp 02075 02076 STRGETM(mf,mf->Seg.WritingApp,len); 02077 02078 break; 02079 02080 ENDFOR(mf); 02081 02082 02083 02084 mf->Seg.Duration = mul3(duration,mf->Seg.TimecodeScale); 02085 02086 } 02087 02088 02089 02090 static void parseFirstCluster(MatroskaFile *mf,ulonglong toplen) { 02091 02092 mf->seen.Cluster = 1; 02093 02094 mf->firstTimecode = 0; 02095 02096 02097 02098 FOREACH(mf,toplen) 02099 02100 case 0xe7: // Timecode 02101 02102 mf->firstTimecode += readUInt(mf,(unsigned)len); 02103 02104 break; 02105 02106 case 0xa3: // BlockEx 02107 02108 readVLUInt(mf); // track number 02109 02110 mf->firstTimecode += readSInt(mf, 2); 02111 02112 02113 02114 skipbytes(mf,start + toplen - filepos(mf)); 02115 02116 return; 02117 02118 case 0xa0: // BlockGroup 02119 02120 FOREACH(mf,len) 02121 02122 case 0xa1: // Block 02123 02124 readVLUInt(mf); // track number 02125 02126 mf->firstTimecode += readSInt(mf,2); 02127 02128 02129 02130 skipbytes(mf,start + toplen - filepos(mf)); 02131 02132 return; 02133 02134 ENDFOR(mf); 02135 02136 break; 02137 02138 ENDFOR(mf); 02139 02140 } 02141 02142 02143 02144 static void parseVideoInfo(MatroskaFile *mf,ulonglong toplen,struct TrackInfo *ti) { 02145 02146 ulonglong v; 02147 02148 char dW = 0, dH = 0; 02149 02150 02151 02152 FOREACH(mf,toplen) 02153 02154 case 0x9a: // FlagInterlaced 02155 02156 ti->Video.Interlaced = readUInt(mf,(unsigned)len)!=0; 02157 02158 break; 02159 02160 case 0x53b8: // StereoMode 02161 02162 v = readUInt(mf,(unsigned)len); 02163 02164 if (v>3) 02165 02166 errorjmp(mf,"Invalid stereo mode"); 02167 02168 ti->Video.StereoMode = (unsigned char)v; 02169 02170 break; 02171 02172 case 0xb0: // PixelWidth 02173 02174 v = readUInt(mf,(unsigned)len); 02175 02176 if (v>0xffffffff) 02177 02178 errorjmp(mf,"PixelWidth is too large"); 02179 02180 ti->Video.PixelWidth = (unsigned)v; 02181 02182 if (!dW) 02183 02184 ti->Video.DisplayWidth = ti->Video.PixelWidth; 02185 02186 break; 02187 02188 case 0xba: // PixelHeight 02189 02190 v = readUInt(mf,(unsigned)len); 02191 02192 if (v>0xffffffff) 02193 02194 errorjmp(mf,"PixelHeight is too large"); 02195 02196 ti->Video.PixelHeight = (unsigned)v; 02197 02198 if (!dH) 02199 02200 ti->Video.DisplayHeight = ti->Video.PixelHeight; 02201 02202 break; 02203 02204 case 0x54b0: // DisplayWidth 02205 02206 v = readUInt(mf,(unsigned)len); 02207 02208 if (v>0xffffffff) 02209 02210 errorjmp(mf,"DisplayWidth is too large"); 02211 02212 ti->Video.DisplayWidth = (unsigned)v; 02213 02214 dW = 1; 02215 02216 break; 02217 02218 case 0x54ba: // DisplayHeight 02219 02220 v = readUInt(mf,(unsigned)len); 02221 02222 if (v>0xffffffff) 02223 02224 errorjmp(mf,"DisplayHeight is too large"); 02225 02226 ti->Video.DisplayHeight = (unsigned)v; 02227 02228 dH = 1; 02229 02230 break; 02231 02232 case 0x54b2: // DisplayUnit 02233 02234 v = readUInt(mf,(unsigned)len); 02235 02236 if (v>2) 02237 02238 errorjmp(mf,"Invalid DisplayUnit: %d",(int)v); 02239 02240 ti->Video.DisplayUnit = (unsigned char)v; 02241 02242 break; 02243 02244 case 0x54b3: // AspectRatioType 02245 02246 v = readUInt(mf,(unsigned)len); 02247 02248 if (v>2) 02249 02250 errorjmp(mf,"Invalid AspectRatioType: %d",(int)v); 02251 02252 ti->Video.AspectRatioType = (unsigned char)v; 02253 02254 break; 02255 02256 case 0x54aa: // PixelCropBottom 02257 02258 v = readUInt(mf,(unsigned)len); 02259 02260 if (v>0xffffffff) 02261 02262 errorjmp(mf,"PixelCropBottom is too large"); 02263 02264 ti->Video.CropB = (unsigned)v; 02265 02266 break; 02267 02268 case 0x54bb: // PixelCropTop 02269 02270 v = readUInt(mf,(unsigned)len); 02271 02272 if (v>0xffffffff) 02273 02274 errorjmp(mf,"PixelCropTop is too large"); 02275 02276 ti->Video.CropT = (unsigned)v; 02277 02278 break; 02279 02280 case 0x54cc: // PixelCropLeft 02281 02282 v = readUInt(mf,(unsigned)len); 02283 02284 if (v>0xffffffff) 02285 02286 errorjmp(mf,"PixelCropLeft is too large"); 02287 02288 ti->Video.CropL = (unsigned)v; 02289 02290 break; 02291 02292 case 0x54dd: // PixelCropRight 02293 02294 v = readUInt(mf,(unsigned)len); 02295 02296 if (v>0xffffffff) 02297 02298 errorjmp(mf,"PixelCropRight is too large"); 02299 02300 ti->Video.CropR = (unsigned)v; 02301 02302 break; 02303 02304 case 0x2eb524: // ColourSpace 02305 02306 ti->Video.ColourSpace = (unsigned)readUInt(mf,4); 02307 02308 break; 02309 02310 case 0x2fb523: // GammaValue 02311 02312 ti->Video.GammaValue = readFloat(mf,(unsigned)len); 02313 02314 break; 02315 02316 ENDFOR(mf); 02317 02318 } 02319 02320 02321 02322 static void parseAudioInfo(MatroskaFile *mf,ulonglong toplen,struct TrackInfo *ti) { 02323 02324 ulonglong v; 02325 02326 02327 02328 FOREACH(mf,toplen) 02329 02330 case 0xb5: // SamplingFrequency 02331 02332 ti->Audio.SamplingFreq = readFloat(mf,(unsigned)len); 02333 02334 break; 02335 02336 case 0x78b5: // OutputSamplingFrequency 02337 02338 ti->Audio.OutputSamplingFreq = readFloat(mf,(unsigned)len); 02339 02340 break; 02341 02342 case 0x9f: // Channels 02343 02344 v = readUInt(mf,(unsigned)len); 02345 02346 if (v<1 || v>255) 02347 02348 errorjmp(mf,"Invalid Channels value"); 02349 02350 ti->Audio.Channels = (unsigned char)v; 02351 02352 break; 02353 02354 case 0x7d7b: // ChannelPositions 02355 02356 skipbytes(mf,len); 02357 02358 break; 02359 02360 case 0x6264: // BitDepth 02361 02362 v = readUInt(mf,(unsigned)len); 02363 02364 #if 0 02365 02366 if ((v<1 || v>255) && !IsWritingApp(mf,"AVI-Mux GUI")) 02367 02368 errorjmp(mf,"Invalid BitDepth: %d",(int)v); 02369 02370 #endif 02371 02372 ti->Audio.BitDepth = (unsigned char)v; 02373 02374 break; 02375 02376 ENDFOR(mf); 02377 02378 02379 02380 if (ti->Audio.Channels == 0) 02381 02382 ti->Audio.Channels = 1; 02383 02384 if (mkv_TruncFloat(ti->Audio.SamplingFreq) == 0) 02385 02386 ti->Audio.SamplingFreq = mkfi(8000); 02387 02388 if (mkv_TruncFloat(ti->Audio.OutputSamplingFreq)==0) 02389 02390 ti->Audio.OutputSamplingFreq = ti->Audio.SamplingFreq; 02391 02392 } 02393 02394 02395 02396 static void CopyStr(char **src,char **dst) { 02397 02398 size_t l; 02399 02400 02401 02402 if (!*src) 02403 02404 return; 02405 02406 02407 02408 l = strlen(*src)+1; 02409 02410 memcpy(*dst,*src,l); 02411 02412 *src = *dst; 02413 02414 *dst += l; 02415 02416 } 02417 02418 02419 02420 static void parseTrackEntry(MatroskaFile *mf,ulonglong toplen) { 02421 02422 struct TrackInfo t,*tp,**tpp; 02423 02424 ulonglong v; 02425 02426 char *cp = NULL, *cs = NULL; 02427 02428 size_t cplen = 0, cslen = 0, cpadd = 0; 02429 02430 unsigned CompScope, num_comp = 0; 02431 02432 02433 02434 if (mf->nTracks >= MAX_TRACKS) 02435 02436 errorjmp(mf,"Too many tracks."); 02437 02438 02439 02440 // clear track info 02441 02442 memset(&t,0,sizeof(t)); 02443 02444 02445 02446 // fill default values 02447 02448 t.Enabled = 1; 02449 02450 t.Default = 1; 02451 02452 t.Lacing = 1; 02453 02454 t.TimecodeScale = mkfi(1); 02455 02456 t.DecodeAll = 1; 02457 02458 02459 02460 FOREACH(mf,toplen) 02461 02462 case 0xd7: // TrackNumber 02463 02464 v = readUInt(mf,(unsigned)len); 02465 02466 if (v>255) 02467 02468 errorjmp(mf,"Track number is >255 (%d)",(int)v); 02469 02470 t.Number = (unsigned char)v; 02471 02472 break; 02473 02474 case 0x73c5: // TrackUID 02475 02476 t.UID = readUInt(mf,(unsigned)len); 02477 02478 break; 02479 02480 case 0x83: // TrackType 02481 02482 v = readUInt(mf,(unsigned)len); 02483 02484 if (v<1 || v>254) 02485 02486 errorjmp(mf,"Invalid track type: %d",(int)v); 02487 02488 t.Type = (unsigned char)v; 02489 02490 break; 02491 02492 case 0xb9: // Enabled 02493 02494 t.Enabled = readUInt(mf,(unsigned)len)!=0; 02495 02496 break; 02497 02498 case 0x88: // Default 02499 02500 t.Default = readUInt(mf,(unsigned)len)!=0; 02501 02502 break; 02503 02504 case 0x9c: // Lacing 02505 02506 t.Lacing = readUInt(mf,(unsigned)len)!=0; 02507 02508 break; 02509 02510 case 0x6de7: // MinCache 02511 02512 v = readUInt(mf,(unsigned)len); 02513 02514 if (v > 0xffffffff) 02515 02516 errorjmp(mf,"MinCache is too large"); 02517 02518 t.MinCache = (unsigned)v; 02519 02520 break; 02521 02522 case 0x6df8: // MaxCache 02523 02524 v = readUInt(mf,(unsigned)len); 02525 02526 if (v > 0xffffffff) 02527 02528 errorjmp(mf,"MaxCache is too large"); 02529 02530 t.MaxCache = (unsigned)v; 02531 02532 break; 02533 02534 case 0x23e383: // DefaultDuration 02535 02536 t.DefaultDuration = readUInt(mf,(unsigned)len); 02537 02538 break; 02539 02540 case 0x23314f: // TrackTimecodeScale 02541 02542 t.TimecodeScale = readFloat(mf,(unsigned)len); 02543 02544 break; 02545 02546 case 0x55ee: // MaxBlockAdditionID 02547 02548 t.MaxBlockAdditionID = (unsigned)readUInt(mf,(unsigned)len); 02549 02550 break; 02551 02552 case 0x536e: // Name 02553 02554 if (t.Name) 02555 02556 errorjmp(mf,"Duplicate Track Name"); 02557 02558 STRGETA(mf,t.Name,len); 02559 02560 break; 02561 02562 case 0x22b59c: // Language 02563 02564 if (t.Language) 02565 02566 errorjmp(mf,"Duplicate Track Language"); 02567 02568 STRGETA(mf,t.Language,len); 02569 02570 break; 02571 02572 case 0x86: // CodecID 02573 02574 if (t.CodecID) 02575 02576 errorjmp(mf,"Duplicate CodecID"); 02577 02578 STRGETA(mf,t.CodecID,len); 02579 02580 break; 02581 02582 case 0x63a2: // CodecPrivate 02583 02584 if (cp) 02585 02586 errorjmp(mf,"Duplicate CodecPrivate"); 02587 02588 if (len>262144) // 256KB 02589 02590 errorjmp(mf,"CodecPrivate is too large: %d",(int)len); 02591 02592 cplen = (unsigned)len; 02593 02594 cp = alloca(cplen); 02595 02596 readbytes(mf,cp,(int)cplen); 02597 02598 break; 02599 02600 case 0x258688: // CodecName 02601 02602 skipbytes(mf,len); 02603 02604 break; 02605 02606 case 0x3a9697: // CodecSettings 02607 02608 skipbytes(mf,len); 02609 02610 break; 02611 02612 case 0x3b4040: // CodecInfoURL 02613 02614 skipbytes(mf,len); 02615 02616 break; 02617 02618 case 0x26b240: // CodecDownloadURL 02619 02620 skipbytes(mf,len); 02621 02622 break; 02623 02624 case 0xaa: // CodecDecodeAll 02625 02626 t.DecodeAll = readUInt(mf,(unsigned)len)!=0; 02627 02628 break; 02629 02630 case 0x6fab: // TrackOverlay 02631 02632 v = readUInt(mf,(unsigned)len); 02633 02634 if (v>255) 02635 02636 errorjmp(mf,"Track number in TrackOverlay is too large: %d",(int)v); 02637 02638 t.TrackOverlay = (unsigned char)v; 02639 02640 break; 02641 02642 case 0xe0: // VideoInfo 02643 02644 parseVideoInfo(mf,len,&t); 02645 02646 break; 02647 02648 case 0xe1: // AudioInfo 02649 02650 parseAudioInfo(mf,len,&t); 02651 02652 break; 02653 02654 case 0x6d80: // ContentEncodings 02655 02656 FOREACH(mf,len) 02657 02658 case 0x6240: // ContentEncoding 02659 02660 // fill in defaults 02661 02662 t.CompEnabled = 1; 02663 02664 t.CompMethod = COMP_ZLIB; 02665 02666 CompScope = 1; 02667 02668 if (++num_comp > 1) 02669 02670 return; // only one compression layer supported 02671 02672 FOREACH(mf,len) 02673 02674 case 0x5031: // ContentEncodingOrder 02675 02676 readUInt(mf,(unsigned)len); 02677 02678 break; 02679 02680 case 0x5032: // ContentEncodingScope 02681 02682 CompScope = (unsigned)readUInt(mf,(unsigned)len); 02683 02684 break; 02685 02686 case 0x5033: // ContentEncodingType 02687 02688 if (readUInt(mf,(unsigned)len) != 0) 02689 02690 return; // encryption is not supported 02691 02692 break; 02693 02694 case 0x5034: // ContentCompression 02695 02696 FOREACH(mf,len) 02697 02698 case 0x4254: // ContentCompAlgo 02699 02700 v = readUInt(mf,(unsigned)len); 02701 02702 t.CompEnabled = 1; 02703 02704 switch (v) { 02705 02706 case 0: // Zlib 02707 02708 t.CompMethod = COMP_ZLIB; 02709 02710 break; 02711 02712 case 3: // prepend fixed data 02713 02714 t.CompMethod = COMP_PREPEND; 02715 02716 break; 02717 02718 default: 02719 02720 return; // unsupported compression, skip track 02721 02722 } 02723 02724 break; 02725 02726 case 0x4255: // ContentCompSettings 02727 02728 if (len > 256) 02729 02730 return; 02731 02732 cslen = (unsigned)len; 02733 02734 cs = alloca(cslen); 02735 02736 readbytes(mf, cs, (int)cslen); 02737 02738 break; 02739 02740 ENDFOR(mf); 02741 02742 break; 02743 02744 // TODO Implement Encryption/Signatures 02745 02746 ENDFOR(mf); 02747 02748 break; 02749 02750 ENDFOR(mf); 02751 02752 break; 02753 02754 ENDFOR(mf); 02755 02756 02757 02758 // validate track info 02759 02760 if (!t.CodecID) 02761 02762 errorjmp(mf,"Track has no Codec ID"); 02763 02764 02765 02766 if (t.UID != 0) { 02767 02768 unsigned i; 02769 02770 for (i = 0; i < mf->nTracks; ++i) 02771 02772 if (mf->Tracks[i]->UID == t.UID) // duplicate track entry 02773 02774 return; 02775 02776 } 02777 02778 02779 02780 #ifdef MATROSKA_COMPRESSION_SUPPORT 02781 02782 // handle compressed CodecPrivate 02783 02784 if (t.CompEnabled && t.CompMethod == COMP_ZLIB && (CompScope & 2) && cplen > 0) { 02785 02786 z_stream zs; 02787 02788 char tmp[64], *ncp; 02789 02790 int code; 02791 02792 uLong ncplen; 02793 02794 02795 02796 memset(&zs,0,sizeof(zs)); 02797 02798 if (inflateInit(&zs) != Z_OK) 02799 02800 errorjmp(mf, "inflateInit failed"); 02801 02802 02803 02804 zs.next_in = cp; 02805 02806 zs.avail_in = cplen; 02807 02808 02809 02810 do { 02811 02812 zs.next_out = tmp; 02813 02814 zs.avail_out = sizeof(tmp); 02815 02816 02817 02818 code = inflate(&zs, Z_NO_FLUSH); 02819 02820 } while (code == Z_OK); 02821 02822 02823 02824 if (code != Z_STREAM_END) 02825 02826 errorjmp(mf, "invalid compressed data in CodecPrivate"); 02827 02828 02829 02830 ncplen = zs.total_out; 02831 02832 ncp = alloca(ncplen); 02833 02834 02835 02836 inflateReset(&zs); 02837 02838 02839 02840 zs.next_in = cp; 02841 02842 zs.avail_in = cplen; 02843 02844 zs.next_out = ncp; 02845 02846 zs.avail_out = ncplen; 02847 02848 02849 02850 if (inflate(&zs, Z_FINISH) != Z_STREAM_END) 02851 02852 errorjmp(mf, "inflate failed"); 02853 02854 02855 02856 inflateEnd(&zs); 02857 02858 02859 02860 cp = ncp; 02861 02862 cplen = ncplen; 02863 02864 } 02865 02866 #endif 02867 02868 02869 02870 if (t.CompEnabled && !(CompScope & 1)) { 02871 02872 t.CompEnabled = 0; 02873 02874 cslen = 0; 02875 02876 } 02877 02878 02879 02880 // allocate new track 02881 02882 tpp = AGET(mf,Tracks); 02883 02884 02885 02886 // copy strings 02887 02888 if (t.Name) 02889 02890 cpadd += strlen(t.Name)+1; 02891 02892 if (t.Language) 02893 02894 cpadd += strlen(t.Language)+1; 02895 02896 if (t.CodecID) 02897 02898 cpadd += strlen(t.CodecID)+1; 02899 02900 02901 02902 tp = mf->cache->memalloc(mf->cache,sizeof(*tp) + cplen + cslen + cpadd); 02903 02904 if (tp == NULL) 02905 02906 errorjmp(mf,"Out of memory"); 02907 02908 02909 02910 memcpy(tp,&t,sizeof(*tp)); 02911 02912 if (cplen) { 02913 02914 tp->CodecPrivate = tp+1; 02915 02916 tp->CodecPrivateSize = (unsigned)cplen; 02917 02918 memcpy(tp->CodecPrivate,cp,cplen); 02919 02920 } 02921 02922 if (cslen) { 02923 02924 tp->CompMethodPrivate = (char *)(tp+1) + cplen; 02925 02926 tp->CompMethodPrivateSize = cslen; 02927 02928 memcpy(tp->CompMethodPrivate, cs, cslen); 02929 02930 } 02931 02932 02933 02934 cp = (char*)(tp+1) + cplen + cslen; 02935 02936 CopyStr(&tp->Name,&cp); 02937 02938 CopyStr(&tp->Language,&cp); 02939 02940 CopyStr(&tp->CodecID,&cp); 02941 02942 02943 02944 // set default language 02945 02946 if (!tp->Language) 02947 02948 tp->Language="eng"; 02949 02950 02951 02952 *tpp = tp; 02953 02954 } 02955 02956 02957 02958 static void parseTracks(MatroskaFile *mf,ulonglong toplen) { 02959 02960 mf->seen.Tracks = 1; 02961 02962 FOREACH(mf,toplen) 02963 02964 case 0xae: // TrackEntry 02965 02966 parseTrackEntry(mf,len); 02967 02968 break; 02969 02970 ENDFOR(mf); 02971 02972 } 02973 02974 02975 02976 static void addCue(MatroskaFile *mf,ulonglong pos,ulonglong timecode) { 02977 02978 struct Cue *cc = AGET(mf,Cues); 02979 02980 cc->Time = timecode; 02981 02982 cc->Position = pos; 02983 02984 cc->Track = 0; 02985 02986 cc->Block = 0; 02987 02988 } 02989 02990 02991 02992 static void fixupCues(MatroskaFile *mf) { 02993 02994 // adjust cues, shift cues if file does not start at 0 02995 02996 unsigned i; 02997 02998 longlong adjust = mf->firstTimecode * mf->Seg.TimecodeScale; 02999 03000 03001 03002 for (i=0;i<mf->nCues;++i) { 03003 03004 mf->Cues[i].Time *= mf->Seg.TimecodeScale; 03005 03006 mf->Cues[i].Time -= adjust; 03007 03008 } 03009 03010 } 03011 03012 03013 03014 static void parseCues(MatroskaFile *mf,ulonglong toplen) { 03015 03016 jmp_buf jb; 03017 03018 ulonglong v; 03019 03020 struct Cue cc; 03021 03022 unsigned i,j,k; 03023 03024 03025 03026 mf->seen.Cues = 1; 03027 03028 mf->nCues = 0; 03029 03030 cc.Block = 0; 03031 03032 03033 03034 memcpy(&jb,&mf->jb,sizeof(jb)); 03035 03036 03037 03038 if (setjmp(mf->jb)) { 03039 03040 memcpy(&mf->jb,&jb,sizeof(jb)); 03041 03042 mf->nCues = 0; 03043 03044 mf->seen.Cues = 0; 03045 03046 return; 03047 03048 } 03049 03050 03051 03052 FOREACH(mf,toplen) 03053 03054 case 0xbb: // CuePoint 03055 03056 FOREACH(mf,len) 03057 03058 case 0xb3: // CueTime 03059 03060 cc.Time = readUInt(mf,(unsigned)len); 03061 03062 break; 03063 03064 case 0xb7: // CueTrackPositions 03065 03066 FOREACH(mf,len) 03067 03068 case 0xf7: // CueTrack 03069 03070 v = readUInt(mf,(unsigned)len); 03071 03072 if (v>255) 03073 03074 errorjmp(mf,"CueTrack points to an invalid track: %d",(int)v); 03075 03076 cc.Track = (unsigned char)v; 03077 03078 break; 03079 03080 case 0xf1: // CueClusterPosition 03081 03082 cc.Position = readUInt(mf,(unsigned)len); 03083 03084 break; 03085 03086 case 0x5378: // CueBlockNumber 03087 03088 cc.Block = readUInt(mf,(unsigned)len); 03089 03090 break; 03091 03092 case 0xea: // CodecState 03093 03094 readUInt(mf,(unsigned)len); 03095 03096 break; 03097 03098 case 0xdb: // CueReference 03099 03100 FOREACH(mf,len) 03101 03102 case 0x96: // CueRefTime 03103 03104 readUInt(mf,(unsigned)len); 03105 03106 break; 03107 03108 case 0x97: // CueRefCluster 03109 03110 readUInt(mf,(unsigned)len); 03111 03112 break; 03113 03114 case 0x535f: // CueRefNumber 03115 03116 readUInt(mf,(unsigned)len); 03117 03118 break; 03119 03120 case 0xeb: // CueRefCodecState 03121 03122 readUInt(mf,(unsigned)len); 03123 03124 break; 03125 03126 ENDFOR(mf); 03127 03128 break; 03129 03130 ENDFOR(mf); 03131 03132 break; 03133 03134 ENDFOR(mf); 03135 03136 03137 03138 if (mf->nCues == 0 && mf->pCluster - mf->pSegment != cc.Position) 03139 03140 addCue(mf,mf->pCluster - mf->pSegment,mf->firstTimecode); 03141 03142 03143 03144 memcpy(AGET(mf,Cues),&cc,sizeof(cc)); 03145 03146 break; 03147 03148 ENDFOR(mf); 03149 03150 03151 03152 memcpy(&mf->jb,&jb,sizeof(jb)); 03153 03154 03155 03156 ARELEASE(mf,mf,Cues); 03157 03158 03159 03160 // bubble sort the cues and fuck the losers that write unordered cues 03161 03162 if (mf->nCues > 0) 03163 03164 for (i = mf->nCues - 1, k = 1; i > 0 && k > 0; --i) 03165 03166 for (j = k = 0; j < i; ++j) 03167 03168 if (mf->Cues[j].Time > mf->Cues[j+1].Time) { 03169 03170 struct Cue tmp = mf->Cues[j+1]; 03171 03172 mf->Cues[j+1] = mf->Cues[j]; 03173 03174 mf->Cues[j] = tmp; 03175 03176 ++k; 03177 03178 } 03179 03180 } 03181 03182 03183 03184 static void parseAttachment(MatroskaFile *mf,ulonglong toplen) { 03185 03186 struct Attachment a,*pa; 03187 03188 03189 03190 memset(&a,0,sizeof(a)); 03191 03192 FOREACH(mf,toplen) 03193 03194 case 0x467e: // Description 03195 03196 STRGETA(mf,a.Description,len); 03197 03198 break; 03199 03200 case 0x466e: // Name 03201 03202 STRGETA(mf,a.Name,len); 03203 03204 break; 03205 03206 case 0x4660: // MimeType 03207 03208 STRGETA(mf,a.MimeType,len); 03209 03210 break; 03211 03212 case 0x46ae: // UID 03213 03214 a.UID = readUInt(mf,(unsigned)len); 03215 03216 break; 03217 03218 case 0x465c: // Data 03219 03220 a.Position = filepos(mf); 03221 03222 a.Length = len; 03223 03224 skipbytes(mf,len); 03225 03226 break; 03227 03228 ENDFOR(mf); 03229 03230 03231 03232 if (!a.Position) 03233 03234 return; 03235 03236 03237 03238 pa = AGET(mf,Attachments); 03239 03240 memcpy(pa,&a,sizeof(a)); 03241 03242 03243 03244 if (a.Description) 03245 03246 pa->Description = mystrdup(mf->cache,a.Description); 03247 03248 if (a.Name) 03249 03250 pa->Name = mystrdup(mf->cache,a.Name); 03251 03252 if (a.MimeType) 03253 03254 pa->MimeType = mystrdup(mf->cache,a.MimeType); 03255 03256 } 03257 03258 03259 03260 static void parseAttachments(MatroskaFile *mf,ulonglong toplen) { 03261 03262 mf->seen.Attachments = 1; 03263 03264 03265 03266 FOREACH(mf,toplen) 03267 03268 case 0x61a7: // AttachedFile 03269 03270 parseAttachment(mf,len); 03271 03272 break; 03273 03274 ENDFOR(mf); 03275 03276 } 03277 03278 03279 03280 static void parseChapter(MatroskaFile *mf,ulonglong toplen,struct Chapter *parent) { 03281 03282 struct ChapterDisplay *disp; 03283 03284 struct ChapterProcess *proc; 03285 03286 struct ChapterCommand *cmd; 03287 03288 struct Chapter *ch = ASGET(mf,parent,Children); 03289 03290 03291 03292 memset(ch,0,sizeof(*ch)); 03293 03294 03295 03296 ch->Enabled = 1; 03297 03298 03299 03300 FOREACH(mf,toplen) 03301 03302 case 0x73c4: // ChapterUID 03303 03304 ch->UID = readUInt(mf,(unsigned)len); 03305 03306 break; 03307 03308 case 0x6e67: // ChapterSegmentUID 03309 03310 if (len != sizeof(ch->SegmentUID)) 03311 03312 skipbytes(mf, len); 03313 03314 else 03315 03316 readbytes(mf, ch->SegmentUID, sizeof(ch->SegmentUID)); 03317 03318 break; 03319 03320 case 0x91: // ChapterTimeStart 03321 03322 ch->Start = readUInt(mf,(unsigned)len); 03323 03324 break; 03325 03326 case 0x92: // ChapterTimeEnd 03327 03328 ch->End = readUInt(mf,(unsigned)len); 03329 03330 break; 03331 03332 case 0x98: // ChapterFlagHidden 03333 03334 ch->Hidden = readUInt(mf,(unsigned)len)!=0; 03335 03336 break; 03337 03338 case 0x4598: // ChapterFlagEnabled 03339 03340 ch->Enabled = readUInt(mf,(unsigned)len)!=0; 03341 03342 break; 03343 03344 case 0x8f: // ChapterTrack 03345 03346 FOREACH(mf,len) 03347 03348 case 0x89: // ChapterTrackNumber 03349 03350 *(ulonglong*)(ASGET(mf,ch,Tracks)) = readUInt(mf,(unsigned)len); 03351 03352 break; 03353 03354 ENDFOR(mf); 03355 03356 break; 03357 03358 case 0x80: // ChapterDisplay 03359 03360 disp = NULL; 03361 03362 03363 03364 FOREACH(mf,len) 03365 03366 case 0x85: // ChapterString 03367 03368 if (disp==NULL) { 03369 03370 disp = ASGET(mf,ch,Display); 03371 03372 memset(disp, 0, sizeof(*disp)); 03373 03374 } 03375 03376 if (disp->String) 03377 03378 skipbytes(mf,len); // Ignore duplicate string 03379 03380 else 03381 03382 STRGETM(mf,disp->String,len); 03383 03384 break; 03385 03386 case 0x437c: // ChapterLanguage 03387 03388 if (disp==NULL) { 03389 03390 disp = ASGET(mf,ch,Display); 03391 03392 memset(disp, 0, sizeof(*disp)); 03393 03394 } 03395 03396 if (disp->Language) 03397 03398 skipbytes(mf,len); 03399 03400 else 03401 03402 STRGETM(mf,disp->Language,len); 03403 03404 break; 03405 03406 case 0x437e: // ChapterCountry 03407 03408 if (disp==NULL) { 03409 03410 disp = ASGET(mf,ch,Display); 03411 03412 memset(disp, 0, sizeof(*disp)); 03413 03414 } 03415 03416 if (disp->Country) 03417 03418 skipbytes(mf,len); 03419 03420 else 03421 03422 STRGETM(mf,disp->Country,len); 03423 03424 break; 03425 03426 ENDFOR(mf); 03427 03428 03429 03430 if (disp && !disp->String) { 03431 03432 mf->cache->memfree(mf->cache,disp->Language); 03433 03434 mf->cache->memfree(mf->cache,disp->Country); 03435 03436 --ch->nDisplay; 03437 03438 } 03439 03440 break; 03441 03442 case 0x6944: // ChapProcess 03443 03444 proc = NULL; 03445 03446 03447 03448 FOREACH(mf,len) 03449 03450 case 0x6955: // ChapProcessCodecID 03451 03452 if (proc == NULL) { 03453 03454 proc = ASGET(mf, ch, Process); 03455 03456 memset(proc, 0, sizeof(*proc)); 03457 03458 } 03459 03460 proc->CodecID = (unsigned)readUInt(mf,(unsigned)len); 03461 03462 break; 03463 03464 case 0x450d: // ChapProcessPrivate 03465 03466 if (proc == NULL) { 03467 03468 proc = ASGET(mf, ch, Process); 03469 03470 memset(proc, 0, sizeof(*proc)); 03471 03472 } 03473 03474 if (proc->CodecPrivate) 03475 03476 skipbytes(mf, len); 03477 03478 else { 03479 03480 proc->CodecPrivateLength = (unsigned)len; 03481 03482 STRGETM(mf,proc->CodecPrivate,len); 03483 03484 } 03485 03486 break; 03487 03488 case 0x6911: // ChapProcessCommand 03489 03490 if (proc == NULL) { 03491 03492 proc = ASGET(mf, ch, Process); 03493 03494 memset(proc, 0, sizeof(*proc)); 03495 03496 } 03497 03498 03499 03500 cmd = NULL; 03501 03502 03503 03504 FOREACH(mf,len) 03505 03506 case 0x6922: // ChapterCommandTime 03507 03508 if (cmd == NULL) { 03509 03510 cmd = ASGET(mf,proc,Commands); 03511 03512 memset(cmd, 0, sizeof(*cmd)); 03513 03514 } 03515 03516 cmd->Time = (unsigned)readUInt(mf,(unsigned)len); 03517 03518 break; 03519 03520 case 0x6933: // ChapterCommandString 03521 03522 if (cmd == NULL) { 03523 03524 cmd = ASGET(mf,proc,Commands); 03525 03526 memset(cmd, 0, sizeof(*cmd)); 03527 03528 } 03529 03530 if (cmd->Command) 03531 03532 skipbytes(mf,len); 03533 03534 else { 03535 03536 cmd->CommandLength = (unsigned)len; 03537 03538 STRGETM(mf,cmd->Command,len); 03539 03540 } 03541 03542 break; 03543 03544 ENDFOR(mf); 03545 03546 03547 03548 if (cmd && !cmd->Command) 03549 03550 --proc->nCommands; 03551 03552 break; 03553 03554 ENDFOR(mf); 03555 03556 03557 03558 if (proc && !proc->nCommands) 03559 03560 --ch->nProcess; 03561 03562 break; 03563 03564 case 0xb6: // Nested ChapterAtom 03565 03566 parseChapter(mf,len,ch); 03567 03568 break; 03569 03570 ENDFOR(mf); 03571 03572 03573 03574 ARELEASE(mf,ch,Tracks); 03575 03576 ARELEASE(mf,ch,Display); 03577 03578 ARELEASE(mf,ch,Children); 03579 03580 } 03581 03582 03583 03584 static void parseChapters(MatroskaFile *mf,ulonglong toplen) { 03585 03586 struct Chapter *ch; 03587 03588 03589 03590 mf->seen.Chapters = 1; 03591 03592 03593 03594 FOREACH(mf,toplen) 03595 03596 case 0x45b9: // EditionEntry 03597 03598 ch = AGET(mf,Chapters); 03599 03600 memset(ch, 0, sizeof(*ch)); 03601 03602 FOREACH(mf,len) 03603 03604 case 0x45bc: // EditionUID 03605 03606 ch->UID = readUInt(mf,(unsigned)len); 03607 03608 break; 03609 03610 case 0x45bd: // EditionFlagHidden 03611 03612 ch->Hidden = readUInt(mf,(unsigned)len)!=0; 03613 03614 break; 03615 03616 case 0x45db: // EditionFlagDefault 03617 03618 ch->Default = readUInt(mf,(unsigned)len)!=0; 03619 03620 break; 03621 03622 case 0x45dd: // EditionFlagOrdered 03623 03624 ch->Ordered = readUInt(mf,(unsigned)len)!=0; 03625 03626 break; 03627 03628 case 0xb6: // ChapterAtom 03629 03630 parseChapter(mf,len,ch); 03631 03632 break; 03633 03634 ENDFOR(mf); 03635 03636 break; 03637 03638 ENDFOR(mf); 03639 03640 } 03641 03642 03643 03644 static void parseTags(MatroskaFile *mf,ulonglong toplen) { 03645 03646 struct Tag *tag; 03647 03648 struct Target *target; 03649 03650 struct SimpleTag *st; 03651 03652 03653 03654 mf->seen.Tags = 1; 03655 03656 03657 03658 FOREACH(mf,toplen) 03659 03660 case 0x7373: // Tag 03661 03662 tag = AGET(mf,Tags); 03663 03664 memset(tag,0,sizeof(*tag)); 03665 03666 03667 03668 FOREACH(mf,len) 03669 03670 case 0x63c0: // Targets 03671 03672 FOREACH(mf,len) 03673 03674 case 0x63c5: // TrackUID 03675 03676 target = ASGET(mf,tag,Targets); 03677 03678 target->UID = readUInt(mf,(unsigned)len); 03679 03680 target->Type = TARGET_TRACK; 03681 03682 break; 03683 03684 case 0x63c4: // ChapterUID 03685 03686 target = ASGET(mf,tag,Targets); 03687 03688 target->UID = readUInt(mf,(unsigned)len); 03689 03690 target->Type = TARGET_CHAPTER; 03691 03692 break; 03693 03694 case 0x63c6: // AttachmentUID 03695 03696 target = ASGET(mf,tag,Targets); 03697 03698 target->UID = readUInt(mf,(unsigned)len); 03699 03700 target->Type = TARGET_ATTACHMENT; 03701 03702 break; 03703 03704 case 0x63c9: // EditionUID 03705 03706 target = ASGET(mf,tag,Targets); 03707 03708 target->UID = readUInt(mf,(unsigned)len); 03709 03710 target->Type = TARGET_EDITION; 03711 03712 break; 03713 03714 ENDFOR(mf); 03715 03716 break; 03717 03718 case 0x67c8: // SimpleTag 03719 03720 st = ASGET(mf,tag,SimpleTags); 03721 03722 memset(st,0,sizeof(*st)); 03723 03724 03725 03726 FOREACH(mf,len) 03727 03728 case 0x45a3: // TagName 03729 03730 if (st->Name) 03731 03732 skipbytes(mf,len); 03733 03734 else 03735 03736 STRGETM(mf,st->Name,len); 03737 03738 break; 03739 03740 case 0x4487: // TagString 03741 03742 if (st->Value) 03743 03744 skipbytes(mf,len); 03745 03746 else 03747 03748 STRGETM(mf,st->Value,len); 03749 03750 break; 03751 03752 case 0x447a: // TagLanguage 03753 03754 if (st->Language) 03755 03756 skipbytes(mf,len); 03757 03758 else 03759 03760 STRGETM(mf,st->Language,len); 03761 03762 break; 03763 03764 case 0x4484: // TagDefault 03765 03766 st->Default = readUInt(mf,(unsigned)len)!=0; 03767 03768 break; 03769 03770 ENDFOR(mf); 03771 03772 03773 03774 if (!st->Name || !st->Value) { 03775 03776 mf->cache->memfree(mf->cache,st->Name); 03777 03778 mf->cache->memfree(mf->cache,st->Value); 03779 03780 --tag->nSimpleTags; 03781 03782 } 03783 03784 break; 03785 03786 ENDFOR(mf); 03787 03788 break; 03789 03790 ENDFOR(mf); 03791 03792 } 03793 03794 03795 03796 static void parseContainer(MatroskaFile *mf) { 03797 03798 ulonglong len; 03799 03800 int id = readID(mf); 03801 03802 if (id==EOF) 03803 03804 errorjmp(mf,"Unexpected EOF in parseContainer"); 03805 03806 03807 03808 len = readSize(mf); 03809 03810 03811 03812 switch (id) { 03813 03814 case 0x1549a966: // SegmentInfo 03815 03816 parseSegmentInfo(mf,len); 03817 03818 break; 03819 03820 case 0x1f43b675: // Cluster 03821 03822 parseFirstCluster(mf,len); 03823 03824 break; 03825 03826 case 0x1654ae6b: // Tracks 03827 03828 parseTracks(mf,len); 03829 03830 break; 03831 03832 case 0x1c53bb6b: // Cues 03833 03834 parseCues(mf,len); 03835 03836 break; 03837 03838 case 0x1941a469: // Attachments 03839 03840 parseAttachments(mf,len); 03841 03842 break; 03843 03844 case 0x1043a770: // Chapters 03845 03846 parseChapters(mf,len); 03847 03848 break; 03849 03850 case 0x1254c367: // Tags 03851 03852 parseTags(mf,len); 03853 03854 break; 03855 03856 } 03857 03858 } 03859 03860 03861 03862 static void parseContainerPos(MatroskaFile *mf,ulonglong pos) { 03863 03864 seek(mf,pos); 03865 03866 parseContainer(mf); 03867 03868 } 03869 03870 03871 03872 static void parsePointers(MatroskaFile *mf) { 03873 03874 jmp_buf jb; 03875 03876 03877 03878 if (mf->pSegmentInfo && !mf->seen.SegmentInfo) 03879 03880 parseContainerPos(mf,mf->pSegmentInfo); 03881 03882 if (mf->pCluster && !mf->seen.Cluster) 03883 03884 parseContainerPos(mf,mf->pCluster); 03885 03886 if (mf->pTracks && !mf->seen.Tracks) 03887 03888 parseContainerPos(mf,mf->pTracks); 03889 03890 03891 03892 memcpy(&jb,&mf->jb,sizeof(jb)); 03893 03894 03895 03896 if (setjmp(mf->jb)) 03897 03898 mf->flags &= ~MPF_ERROR; // ignore errors 03899 03900 else { 03901 03902 if (mf->pCues && !mf->seen.Cues) 03903 03904 parseContainerPos(mf,mf->pCues); 03905 03906 if (mf->pAttachments && !mf->seen.Attachments) 03907 03908 parseContainerPos(mf,mf->pAttachments); 03909 03910 if (mf->pChapters && !mf->seen.Chapters) 03911 03912 parseContainerPos(mf,mf->pChapters); 03913 03914 if (mf->pTags && !mf->seen.Tags) 03915 03916 parseContainerPos(mf,mf->pTags); 03917 03918 } 03919 03920 03921 03922 memcpy(&mf->jb,&jb,sizeof(jb)); 03923 03924 } 03925 03926 03927 03928 static void parseSegment(MatroskaFile *mf,ulonglong toplen) { 03929 03930 ulonglong nextpos; 03931 03932 unsigned nSeekHeads = 0, dontstop = 0; 03933 03934 03935 03936 // we want to read data until we find a seekhead or a trackinfo 03937 03938 FOREACH(mf,toplen) 03939 03940 case 0x114d9b74: // SeekHead 03941 03942 if (mf->flags & MKVF_AVOID_SEEKS) { 03943 03944 skipbytes(mf,len); 03945 03946 break; 03947 03948 } 03949 03950 03951 03952 nextpos = filepos(mf) + len; 03953 03954 do { 03955 03956 mf->pSeekHead = 0; 03957 03958 parseSeekHead(mf,len); 03959 03960 ++nSeekHeads; 03961 03962 if (mf->pSeekHead) { // this is possibly a chained SeekHead 03963 03964 seek(mf,mf->pSeekHead); 03965 03966 id = readID(mf); 03967 03968 if (id==EOF) // chained SeekHead points to EOF? 03969 03970 break; 03971 03972 if (id != 0x114d9b74) // chained SeekHead doesnt point to a SeekHead? 03973 03974 break; 03975 03976 len = readSize(mf); 03977 03978 } else if (mf->pSegmentInfo && mf->pTracks && mf->pCues && mf->pCluster) { // we have pointers to all key elements 03979 03980 // XXX EVIL HACK 03981 03982 // Some software doesnt index tags via SeekHead, so we continue 03983 03984 // reading the segment after the second SeekHead 03985 03986 if (mf->pTags || nSeekHeads<2 || filepos(mf)>=start+toplen) { 03987 03988 parsePointers(mf); 03989 03990 return; 03991 03992 } 03993 03994 // reset nextpos pointer to current position 03995 03996 nextpos = filepos(mf); 03997 03998 dontstop = 1; 03999 04000 } 04001 04002 } while (mf->pSeekHead); 04003 04004 seek(mf,nextpos); // resume reading segment 04005 04006 break; 04007 04008 case 0x1549a966: // SegmentInfo 04009 04010 mf->pSegmentInfo = cur; 04011 04012 parseSegmentInfo(mf,len); 04013 04014 break; 04015 04016 case 0x1f43b675: // Cluster 04017 04018 if (!mf->pCluster) 04019 04020 mf->pCluster = cur; 04021 04022 if (mf->seen.Cluster) 04023 04024 skipbytes(mf,len); 04025 04026 else 04027 04028 parseFirstCluster(mf,len); 04029 04030 break; 04031 04032 case 0x1654ae6b: // Tracks 04033 04034 mf->pTracks = cur; 04035 04036 parseTracks(mf,len); 04037 04038 break; 04039 04040 case 0x1c53bb6b: // Cues 04041 04042 mf->pCues = cur; 04043 04044 parseCues(mf,len); 04045 04046 break; 04047 04048 case 0x1941a469: // Attachments 04049 04050 mf->pAttachments = cur; 04051 04052 parseAttachments(mf,len); 04053 04054 break; 04055 04056 case 0x1043a770: // Chapters 04057 04058 mf->pChapters = cur; 04059 04060 parseChapters(mf,len); 04061 04062 break; 04063 04064 case 0x1254c367: // Tags 04065 04066 mf->pTags = cur; 04067 04068 parseTags(mf,len); 04069 04070 break; 04071 04072 ENDFOR1(mf); 04073 04074 // if we have pointers to all key elements 04075 04076 if (!dontstop && mf->pSegmentInfo && mf->pTracks && mf->pCluster) 04077 04078 break; 04079 04080 ENDFOR2(); 04081 04082 parsePointers(mf); 04083 04084 } 04085 04086 04087 04088 static void parseBlockAdditions(MatroskaFile *mf, ulonglong toplen, ulonglong timecode, unsigned track) { 04089 04090 ulonglong add_id = 1, add_pos, add_len; 04091 04092 unsigned char have_add; 04093 04094 04095 04096 FOREACH(mf, toplen) 04097 04098 case 0xa6: // BlockMore 04099 04100 have_add = 0; 04101 04102 FOREACH(mf, len) 04103 04104 case 0xee: // BlockAddId 04105 04106 add_id = readUInt(mf, (unsigned)len); 04107 04108 break; 04109 04110 case 0xa5: // BlockAddition 04111 04112 add_pos = filepos(mf); 04113 04114 add_len = len; 04115 04116 skipbytes(mf, len); 04117 04118 ++have_add; 04119 04120 break; 04121 04122 ENDFOR(mf); 04123 04124 if (have_add == 1 && id > 0 && id < 255) { 04125 04126 struct QueueEntry *qe = QAlloc(mf); 04127 04128 qe->Start = qe->End = timecode; 04129 04130 qe->Position = add_pos; 04131 04132 qe->Length = (unsigned)add_len; 04133 04134 qe->flags = FRAME_UNKNOWN_START | FRAME_UNKNOWN_END | 04135 04136 (((unsigned)add_id << FRAME_STREAM_SHIFT) & FRAME_STREAM_MASK); 04137 04138 04139 04140 QPut(&mf->Queues[track],qe); 04141 04142 } 04143 04144 break; 04145 04146 ENDFOR(mf); 04147 04148 } 04149 04150 04151 04152 static void parseBlockGroup(MatroskaFile *mf,ulonglong toplen,ulonglong timecode, int blockex) { 04153 04154 ulonglong v; 04155 04156 ulonglong duration = 0; 04157 04158 ulonglong dpos; 04159 04160 unsigned add_id = 0; 04161 04162 struct QueueEntry *qe,*qf = NULL; 04163 04164 unsigned char have_duration = 0, have_block = 0; 04165 04166 unsigned char gap = 0; 04167 04168 unsigned char lacing = 0; 04169 04170 unsigned char ref = 0; 04171 04172 unsigned char trackid; 04173 04174 unsigned tracknum = 0; 04175 04176 int c; 04177 04178 unsigned nframes = 0,i; 04179 04180 unsigned *sizes; 04181 04182 signed short block_timecode; 04183 04184 04185 04186 if (blockex) 04187 04188 goto blockex; 04189 04190 04191 04192 FOREACH(mf,toplen) 04193 04194 case 0xfb: // ReferenceBlock 04195 04196 readSInt(mf,(unsigned)len); 04197 04198 ref = 1; 04199 04200 break; 04201 04202 blockex: 04203 04204 cur = start = filepos(mf); 04205 04206 len = tmplen = toplen; 04207 04208 case 0xa1: // Block 04209 04210 have_block = 1; 04211 04212 04213 04214 dpos = filepos(mf); 04215 04216 04217 04218 v = readVLUInt(mf); 04219 04220 if (v>255) 04221 04222 errorjmp(mf,"Invalid track number in Block: %d",(int)v); 04223 04224 trackid = (unsigned char)v; 04225 04226 04227 04228 for (tracknum=0;tracknum<mf->nTracks;++tracknum) 04229 04230 if (mf->Tracks[tracknum]->Number == trackid) { 04231 04232 if (mf->trackMask & (1<<tracknum)) // ignore this block 04233 04234 break; 04235 04236 goto found; 04237 04238 } 04239 04240 04241 04242 // bad trackid/unsupported track 04243 04244 skipbytes(mf,start + tmplen - filepos(mf)); // shortcut 04245 04246 return; 04247 04248 found: 04249 04250 04251 04252 block_timecode = (signed short)readSInt(mf,2); 04253 04254 04255 04256 // recalculate this block's timecode to final timecode in ns 04257 04258 timecode = mul3(mf->Tracks[tracknum]->TimecodeScale, 04259 04260 (timecode - mf->firstTimecode + block_timecode) * mf->Seg.TimecodeScale); 04261 04262 04263 04264 c = readch(mf); 04265 04266 if (c==EOF) 04267 04268 errorjmp(mf,"Unexpected EOF while reading Block flags"); 04269 04270 04271 04272 if (blockex) 04273 04274 ref = !(c & 0x80); 04275 04276 04277 04278 gap = c & 0x1; 04279 04280 lacing = (c >> 1) & 3; 04281 04282 04283 04284 if (lacing) { 04285 04286 c = readch(mf); 04287 04288 if (c == EOF) 04289 04290 errorjmp(mf,"Unexpected EOF while reading lacing data"); 04291 04292 nframes = c+1; 04293 04294 } else 04295 04296 nframes = 1; 04297 04298 sizes = alloca(nframes*sizeof(*sizes)); 04299 04300 04301 04302 switch (lacing) { 04303 04304 case 0: // No lacing 04305 04306 sizes[0] = (unsigned)(len - filepos(mf) + dpos); 04307 04308 break; 04309 04310 case 1: // Xiph lacing 04311 04312 sizes[nframes-1] = 0; 04313 04314 for (i=0;i<nframes-1;++i) { 04315 04316 sizes[i] = 0; 04317 04318 do { 04319 04320 c = readch(mf); 04321 04322 if (c==EOF) 04323 04324 errorjmp(mf,"Unexpected EOF while reading lacing data"); 04325 04326 sizes[i] += c; 04327 04328 } while (c==255); 04329 04330 sizes[nframes-1] += sizes[i]; 04331 04332 } 04333 04334 sizes[nframes-1] = (unsigned)(len - filepos(mf) + dpos) - sizes[nframes-1]; 04335 04336 break; 04337 04338 case 3: // EBML lacing 04339 04340 sizes[nframes-1] = 0; 04341 04342 sizes[0] = (unsigned)readVLUInt(mf); 04343 04344 for (i=1;i<nframes-1;++i) { 04345 04346 sizes[i] = sizes[i-1] + (int)readVLSInt(mf); 04347 04348 sizes[nframes-1] += sizes[i]; 04349 04350 } 04351 04352 if (nframes>1) 04353 04354 sizes[nframes-1] = (unsigned)(len - filepos(mf) + dpos) - sizes[0] - sizes[nframes-1]; 04355 04356 break; 04357 04358 case 2: // Fixed lacing 04359 04360 sizes[0] = (unsigned)(len - filepos(mf) + dpos)/nframes; 04361 04362 for (i=1;i<nframes;++i) 04363 04364 sizes[i] = sizes[0]; 04365 04366 break; 04367 04368 } 04369 04370 04371 04372 v = filepos(mf); 04373 04374 qf = NULL; 04375 04376 for (i=0;i<nframes;++i) { 04377 04378 qe = QAlloc(mf); 04379 04380 if (!qf) 04381 04382 qf = qe; 04383 04384 04385 04386 qe->Start = timecode; 04387 04388 qe->End = timecode; 04389 04390 qe->Position = v; 04391 04392 qe->Length = sizes[i]; 04393 04394 qe->flags = FRAME_UNKNOWN_END | FRAME_KF; 04395 04396 if (i == nframes-1 && gap) 04397 04398 qe->flags |= FRAME_GAP; 04399 04400 if (i > 0) 04401 04402 qe->flags |= FRAME_UNKNOWN_START; 04403 04404 04405 04406 QPut(&mf->Queues[tracknum],qe); 04407 04408 04409 04410 v += sizes[i]; 04411 04412 } 04413 04414 04415 04416 // we want to still load these bytes into cache 04417 04418 for (v = filepos(mf) & ~0x3fff; v < len + dpos; v += 0x4000) 04419 04420 mf->cache->read(mf->cache,v,NULL,0); // touch page 04421 04422 04423 04424 skipbytes(mf,len - filepos(mf) + dpos); 04425 04426 04427 04428 if (blockex) 04429 04430 goto out; 04431 04432 break; 04433 04434 case 0x9b: // BlockDuration 04435 04436 duration = readUInt(mf,(unsigned)len); 04437 04438 have_duration = 1; 04439 04440 break; 04441 04442 case 0x75a1: // BlockAdditions 04443 04444 if (nframes > 0) // have some frames 04445 04446 parseBlockAdditions(mf, len, timecode, tracknum); 04447 04448 else 04449 04450 skipbytes(mf, len); 04451 04452 break; 04453 04454 ENDFOR(mf); 04455 04456 04457 04458 out: 04459 04460 if (!have_block) 04461 04462 errorjmp(mf,"Found a BlockGroup without Block"); 04463 04464 04465 04466 if (nframes > 1) { 04467 04468 if (have_duration) { 04469 04470 duration = mul3(mf->Tracks[tracknum]->TimecodeScale, 04471 04472 duration * mf->Seg.TimecodeScale); 04473 04474 04475 04476 for (qe = qf; nframes > 1; --nframes, qe = qe->next) { 04477 04478 qe->Start = v; 04479 04480 v += dpos; 04481 04482 duration -= dpos; 04483 04484 qe->End = v; 04485 04486 #if 0 04487 04488 qe->flags &= ~(FRAME_UNKNOWN_START|FRAME_UNKNOWN_END); 04489 04490 #endif 04491 04492 } 04493 04494 qe->Start = v; 04495 04496 qe->End = v + duration; 04497 04498 qe->flags &= ~FRAME_UNKNOWN_END; 04499 04500 } else if (mf->Tracks[tracknum]->DefaultDuration) { 04501 04502 dpos = mf->Tracks[tracknum]->DefaultDuration; 04503 04504 v = qf->Start; 04505 04506 for (qe = qf; nframes > 0; --nframes, qe = qe->next) { 04507 04508 qe->Start = v; 04509 04510 v += dpos; 04511 04512 qe->End = v; 04513 04514 qe->flags &= ~(FRAME_UNKNOWN_START|FRAME_UNKNOWN_END); 04515 04516 } 04517 04518 } 04519 04520 } else if (nframes == 1) { 04521 04522 if (have_duration) { 04523 04524 qf->End = qf->Start + mul3(mf->Tracks[tracknum]->TimecodeScale, 04525 04526 duration * mf->Seg.TimecodeScale); 04527 04528 qf->flags &= ~FRAME_UNKNOWN_END; 04529 04530 } else if (mf->Tracks[tracknum]->DefaultDuration) { 04531 04532 qf->End = qf->Start + mf->Tracks[tracknum]->DefaultDuration; 04533 04534 qf->flags &= ~FRAME_UNKNOWN_END; 04535 04536 } 04537 04538 } 04539 04540 04541 04542 if (ref) 04543 04544 while (qf) { 04545 04546 qf->flags &= ~FRAME_KF; 04547 04548 qf = qf->next; 04549 04550 } 04551 04552 } 04553 04554 04555 04556 static void ClearQueue(MatroskaFile *mf,struct Queue *q) { 04557 04558 struct QueueEntry *qe,*qn; 04559 04560 04561 04562 for (qe=q->head;qe;qe=qn) { 04563 04564 qn = qe->next; 04565 04566 qe->next = mf->QFreeList; 04567 04568 mf->QFreeList = qe; 04569 04570 } 04571 04572 04573 04574 q->head = NULL; 04575 04576 q->tail = NULL; 04577 04578 } 04579 04580 04581 04582 static void EmptyQueues(MatroskaFile *mf) { 04583 04584 unsigned i; 04585 04586 04587 04588 for (i=0;i<mf->nTracks;++i) 04589 04590 ClearQueue(mf,&mf->Queues[i]); 04591 04592 } 04593 04594 04595 04596 static int readMoreBlocks(MatroskaFile *mf) { 04597 04598 ulonglong toplen, cstop; 04599 04600 longlong cp; 04601 04602 int cid, ret = 0; 04603 04604 jmp_buf jb; 04605 04606 volatile unsigned retries = 0; 04607 04608 04609 04610 if (mf->readPosition >= mf->pSegmentTop) 04611 04612 return EOF; 04613 04614 04615 04616 memcpy(&jb,&mf->jb,sizeof(jb)); 04617 04618 04619 04620 if (setjmp(mf->jb)) { // something evil happened here, try to resync 04621 04622 // always advance read position no matter what so 04623 04624 // we don't get caught in an endless loop 04625 04626 mf->readPosition = filepos(mf); 04627 04628 04629 04630 ret = EOF; 04631 04632 04633 04634 if (++retries > 3) // don't try too hard 04635 04636 goto ex; 04637 04638 04639 04640 for (;;) { 04641 04642 if (filepos(mf) >= mf->pSegmentTop) 04643 04644 goto ex; 04645 04646 04647 04648 cp = mf->cache->scan(mf->cache,filepos(mf),0x1f43b675); // cluster 04649 04650 04651 04652 if (cp < 0 || (ulonglong)cp >= mf->pSegmentTop) 04653 04654 goto ex; 04655 04656 04657 04658 seek(mf,cp); 04659 04660 04661 04662 cid = readID(mf); 04663 04664 if (cid == EOF) 04665 04666 goto ex; 04667 04668 if (cid == 0x1f43b675) { 04669 04670 toplen = readSize(mf); 04671 04672 if (toplen < MAXCLUSTER) { 04673 04674 // reset error flags 04675 04676 mf->flags &= ~MPF_ERROR; 04677 04678 ret = RBRESYNC; 04679 04680 break; 04681 04682 } 04683 04684 } 04685 04686 } 04687 04688 04689 04690 mf->readPosition = cp; 04691 04692 } 04693 04694 04695 04696 cstop = mf->cache->getcachesize(mf->cache)>>1; 04697 04698 if (cstop > MAX_READAHEAD) 04699 04700 cstop = MAX_READAHEAD; 04701 04702 cstop += mf->readPosition; 04703 04704 04705 04706 seek(mf,mf->readPosition); 04707 04708 04709 04710 while (filepos(mf) < mf->pSegmentTop) { 04711 04712 cid = readID(mf); 04713 04714 if (cid == EOF) { 04715 04716 ret = EOF; 04717 04718 break; 04719 04720 } 04721 04722 toplen = readSize(mf); 04723 04724 04725 04726 if (cid == 0x1f43b675) { // Cluster 04727 04728 unsigned char have_timecode = 0; 04729 04730 04731 04732 FOREACH(mf,toplen) 04733 04734 case 0xe7: // Timecode 04735 04736 mf->tcCluster = readUInt(mf,(unsigned)len); 04737 04738 have_timecode = 1; 04739 04740 break; 04741 04742 case 0xa7: // Position 04743 04744 readUInt(mf,(unsigned)len); 04745 04746 break; 04747 04748 case 0xab: // PrevSize 04749 04750 readUInt(mf,(unsigned)len); 04751 04752 break; 04753 04754 case 0x5854: { // SilentTracks 04755 04756 unsigned stmask = 0, i, trk; 04757 04758 FOREACH(mf, len) 04759 04760 case 0x58d7: // SilentTrackNumber 04761 04762 trk = (unsigned)readUInt(mf, (unsigned)len); 04763 04764 for (i = 0; i < mf->nTracks; ++i) 04765 04766 if (mf->Tracks[i]->Number == trk) { 04767 04768 stmask |= 1 << i; 04769 04770 break; 04771 04772 } 04773 04774 break; 04775 04776 ENDFOR(mf); 04777 04778 // TODO pass stmask to reading app 04779 04780 break; } 04781 04782 case 0xa0: // BlockGroup 04783 04784 if (!have_timecode) 04785 04786 errorjmp(mf,"Found BlockGroup before cluster TimeCode"); 04787 04788 parseBlockGroup(mf,len,mf->tcCluster, 0); 04789 04790 goto out; 04791 04792 case 0xa3: // BlockEx 04793 04794 if (!have_timecode) 04795 04796 errorjmp(mf,"Found BlockGroup before cluster TimeCode"); 04797 04798 parseBlockGroup(mf, len, mf->tcCluster, 1); 04799 04800 goto out; 04801 04802 ENDFOR(mf); 04803 04804 out:; 04805 04806 } else { 04807 04808 if (toplen > MAXFRAME) 04809 04810 errorjmp(mf,"Element in a cluster is too large around %llu, %X [%u]",filepos(mf),cid,(unsigned)toplen); 04811 04812 if (cid == 0xa0) // BlockGroup 04813 04814 parseBlockGroup(mf,toplen,mf->tcCluster, 0); 04815 04816 else if (cid == 0xa3) // BlockEx 04817 04818 parseBlockGroup(mf, toplen, mf->tcCluster, 1); 04819 04820 else 04821 04822 skipbytes(mf,toplen); 04823 04824 } 04825 04826 04827 04828 if ((mf->readPosition = filepos(mf)) > cstop) 04829 04830 break; 04831 04832 } 04833 04834 04835 04836 mf->readPosition = filepos(mf); 04837 04838 04839 04840 ex: 04841 04842 memcpy(&mf->jb,&jb,sizeof(jb)); 04843 04844 04845 04846 return ret; 04847 04848 } 04849 04850 04851 04852 // this is almost the same as readMoreBlocks, except it ensures 04853 04854 // there are no partial frames queued, however empty queues are ok 04855 04856 static int fillQueues(MatroskaFile *mf,unsigned int mask) { 04857 04858 unsigned i,j; 04859 04860 int ret = 0; 04861 04862 04863 04864 for (;;) { 04865 04866 j = 0; 04867 04868 04869 04870 for (i=0;i<mf->nTracks;++i) 04871 04872 if (mf->Queues[i].head && !(mask & (1<<i))) 04873 04874 ++j; 04875 04876 04877 04878 if (j>0) // have at least some frames 04879 04880 return ret; 04881 04882 04883 04884 if ((ret = readMoreBlocks(mf)) < 0) { 04885 04886 j = 0; 04887 04888 for (i=0;i<mf->nTracks;++i) 04889 04890 if (mf->Queues[i].head && !(mask & (1<<i))) 04891 04892 ++j; 04893 04894 if (j) // we adjusted some blocks 04895 04896 return 0; 04897 04898 return EOF; 04899 04900 } 04901 04902 } 04903 04904 } 04905 04906 04907 04908 static void reindex(MatroskaFile *mf) { 04909 04910 jmp_buf jb; 04911 04912 ulonglong pos = mf->pCluster; 04913 04914 ulonglong step = 10*1024*1024; 04915 04916 ulonglong size, tc, isize; 04917 04918 longlong next_cluster; 04919 04920 int id, have_tc, bad; 04921 04922 struct Cue *cue; 04923 04924 04925 04926 if (pos >= mf->pSegmentTop) 04927 04928 return; 04929 04930 04931 04932 if (pos + step * 10 > mf->pSegmentTop) 04933 04934 step = (mf->pSegmentTop - pos) / 10; 04935 04936 if (step == 0) 04937 04938 step = 1; 04939 04940 04941 04942 memcpy(&jb,&mf->jb,sizeof(jb)); 04943 04944 04945 04946 // remove all cues 04947 04948 mf->nCues = 0; 04949 04950 04951 04952 bad = 0; 04953 04954 04955 04956 while (pos < mf->pSegmentTop) { 04957 04958 if (!mf->cache->progress(mf->cache,pos,mf->pSegmentTop)) 04959 04960 break; 04961 04962 04963 04964 if (++bad > 50) { 04965 04966 pos += step; 04967 04968 bad = 0; 04969 04970 continue; 04971 04972 } 04973 04974 04975 04976 // find next cluster header 04977 04978 next_cluster = mf->cache->scan(mf->cache,pos,0x1f43b675); // cluster 04979 04980 if (next_cluster < 0 || (ulonglong)next_cluster >= mf->pSegmentTop) 04981 04982 break; 04983 04984 04985 04986 pos = next_cluster + 4; // prevent endless loops 04987 04988 04989 04990 if (setjmp(mf->jb)) // something evil happened while reindexing 04991 04992 continue; 04993 04994 04995 04996 seek(mf,next_cluster); 04997 04998 04999 05000 id = readID(mf); 05001 05002 if (id == EOF) 05003 05004 break; 05005 05006 if (id != 0x1f43b675) // shouldn't happen 05007 05008 continue; 05009 05010 05011 05012 size = readVLUInt(mf); 05013 05014 if (size >= MAXCLUSTER || size < 1024) 05015 05016 continue; 05017 05018 05019 05020 have_tc = 0; 05021 05022 size += filepos(mf); 05023 05024 05025 05026 while (filepos(mf) < (ulonglong)next_cluster + 1024) { 05027 05028 id = readID(mf); 05029 05030 if (id == EOF) 05031 05032 break; 05033 05034 05035 05036 isize = readVLUInt(mf); 05037 05038 05039 05040 if (id == 0xe7) { // cluster timecode 05041 05042 tc = readUInt(mf,(unsigned)isize); 05043 05044 have_tc = 1; 05045 05046 break; 05047 05048 } 05049 05050 05051 05052 skipbytes(mf,isize); 05053 05054 } 05055 05056 05057 05058 if (!have_tc) 05059 05060 continue; 05061 05062 05063 05064 seek(mf,size); 05065 05066 id = readID(mf); 05067 05068 05069 05070 if (id == EOF) 05071 05072 break; 05073 05074 05075 05076 if (id != 0x1f43b675) // cluster 05077 05078 continue; 05079 05080 05081 05082 // good cluster, remember it 05083 05084 cue = AGET(mf,Cues); 05085 05086 cue->Time = tc; 05087 05088 cue->Position = next_cluster - mf->pSegment; 05089 05090 cue->Block = 0; 05091 05092 cue->Track = 0; 05093 05094 05095 05096 // advance to the next point 05097 05098 pos = next_cluster + step; 05099 05100 if (pos < size) 05101 05102 pos = size; 05103 05104 05105 05106 bad = 0; 05107 05108 } 05109 05110 05111 05112 fixupCues(mf); 05113 05114 05115 05116 if (mf->nCues == 0) { 05117 05118 cue = AGET(mf,Cues); 05119 05120 cue->Time = mf->firstTimecode; 05121 05122 cue->Position = mf->pCluster - mf->pSegment; 05123 05124 cue->Block = 0; 05125 05126 cue->Track = 0; 05127 05128 } 05129 05130 05131 05132 mf->cache->progress(mf->cache,0,0); 05133 05134 05135 05136 memcpy(&mf->jb,&jb,sizeof(jb)); 05137 05138 } 05139 05140 05141 05142 static void fixupChapter(ulonglong adj, struct Chapter *ch) { 05143 05144 unsigned i; 05145 05146 05147 05148 if (ch->Start != 0) 05149 05150 ch->Start -= adj; 05151 05152 if (ch->End != 0) 05153 05154 ch->End -= adj; 05155 05156 05157 05158 for (i=0;i<ch->nChildren;++i) 05159 05160 fixupChapter(adj,&ch->Children[i]); 05161 05162 } 05163 05164 05165 05166 static longlong findLastTimecode(MatroskaFile *mf) { 05167 05168 ulonglong nd = 0; 05169 05170 unsigned n,vtrack; 05171 05172 05173 05174 if (mf->nTracks == 0) 05175 05176 return -1; 05177 05178 05179 05180 for (n=vtrack=0;n<mf->nTracks;++n) 05181 05182 if (mf->Tracks[n]->Type == TT_VIDEO) { 05183 05184 vtrack = n; 05185 05186 goto ok; 05187 05188 } 05189 05190 05191 05192 return -1; 05193 05194 ok: 05195 05196 05197 05198 EmptyQueues(mf); 05199 05200 05201 05202 if (mf->nCues == 0) { 05203 05204 mf->readPosition = mf->pCluster + 13000000 > mf->pSegmentTop ? mf->pCluster : mf->pSegmentTop - 13000000; 05205 05206 mf->tcCluster = 0; 05207 05208 } else { 05209 05210 mf->readPosition = mf->Cues[mf->nCues - 1].Position + mf->pSegment; 05211 05212 mf->tcCluster = mf->Cues[mf->nCues - 1].Time / mf->Seg.TimecodeScale; 05213 05214 } 05215 05216 mf->trackMask = ~(1 << vtrack); 05217 05218 05219 05220 do 05221 05222 while (mf->Queues[vtrack].head) 05223 05224 { 05225 05226 ulonglong tc = mf->Queues[vtrack].head->flags & FRAME_UNKNOWN_END ? 05227 05228 mf->Queues[vtrack].head->Start : mf->Queues[vtrack].head->End; 05229 05230 if (nd < tc) 05231 05232 nd = tc; 05233 05234 QFree(mf,QGet(&mf->Queues[vtrack])); 05235 05236 } 05237 05238 while (fillQueues(mf,0) != EOF); 05239 05240 05241 05242 mf->trackMask = 0; 05243 05244 05245 05246 EmptyQueues(mf); 05247 05248 05249 05250 // there may have been an error, but at this point we will ignore it 05251 05252 if (mf->flags & MPF_ERROR) { 05253 05254 mf->flags &= ~MPF_ERROR; 05255 05256 if (nd == 0) 05257 05258 return -1; 05259 05260 } 05261 05262 05263 05264 return nd; 05265 05266 } 05267 05268 05269 05270 static void parseFile(MatroskaFile *mf) { 05271 05272 ulonglong len = filepos(mf), adjust; 05273 05274 unsigned i; 05275 05276 int id = readID(mf); 05277 05278 int m; 05279 05280 05281 05282 if (id==EOF) 05283 05284 errorjmp(mf,"Unexpected EOF at start of file"); 05285 05286 05287 05288 // files with multiple concatenated segments can have only 05289 05290 // one EBML prolog 05291 05292 if (len > 0 && id == 0x18538067) 05293 05294 goto segment; 05295 05296 05297 05298 if (id!=0x1a45dfa3) 05299 05300 errorjmp(mf,"First element in file is not EBML"); 05301 05302 05303 05304 parseEBML(mf,readSize(mf)); 05305 05306 05307 05308 // next we need to find the first segment 05309 05310 for (;;) { 05311 05312 id = readID(mf); 05313 05314 if (id==EOF) 05315 05316 errorjmp(mf,"No segments found in the file"); 05317 05318 segment: 05319 05320 len = readVLUIntImp(mf,&m); 05321 05322 // see if it's unspecified 05323 05324 if (len == (MAXU64 >> (57-m*7))) 05325 05326 len = MAXU64; 05327 05328 if (id == 0x18538067) // Segment 05329 05330 break; 05331 05332 skipbytes(mf,len); 05333 05334 } 05335 05336 05337 05338 // found it 05339 05340 mf->pSegment = filepos(mf); 05341 05342 if (len == MAXU64) { 05343 05344 mf->pSegmentTop = MAXU64; 05345 05346 if (mf->cache->getfilesize) { 05347 05348 longlong seglen = mf->cache->getfilesize(mf->cache); 05349 05350 if (seglen > 0) 05351 05352 mf->pSegmentTop = seglen; 05353 05354 } 05355 05356 } else 05357 05358 mf->pSegmentTop = mf->pSegment + len; 05359 05360 parseSegment(mf,len); 05361 05362 05363 05364 // check if we got all data 05365 05366 if (!mf->seen.SegmentInfo) 05367 05368 errorjmp(mf,"Couldn't find SegmentInfo"); 05369 05370 if (!mf->seen.Cluster) 05371 05372 mf->pCluster = mf->pSegmentTop; 05373 05374 05375 05376 adjust = mf->firstTimecode * mf->Seg.TimecodeScale; 05377 05378 05379 05380 for (i=0;i<mf->nChapters;++i) 05381 05382 fixupChapter(adjust, &mf->Chapters[i]); 05383 05384 05385 05386 fixupCues(mf); 05387 05388 05389 05390 // release extra memory 05391 05392 ARELEASE(mf,mf,Tracks); 05393 05394 05395 05396 // initialize reader 05397 05398 mf->Queues = mf->cache->memalloc(mf->cache,mf->nTracks * sizeof(*mf->Queues)); 05399 05400 if (mf->Queues == NULL) 05401 05402 errorjmp(mf, "Ouf of memory"); 05403 05404 memset(mf->Queues, 0, mf->nTracks * sizeof(*mf->Queues)); 05405 05406 05407 05408 // try to detect real duration 05409 05410 if (!(mf->flags & MKVF_AVOID_SEEKS)) { 05411 05412 longlong nd = findLastTimecode(mf); 05413 05414 if (nd > 0) 05415 05416 mf->Seg.Duration = nd; 05417 05418 } 05419 05420 05421 05422 // move to first frame 05423 05424 mf->readPosition = mf->pCluster; 05425 05426 mf->tcCluster = mf->firstTimecode; 05427 05428 } 05429 05430 05431 05432 static void DeleteChapter(MatroskaFile *mf,struct Chapter *ch) { 05433 05434 unsigned i,j; 05435 05436 05437 05438 for (i=0;i<ch->nDisplay;++i) { 05439 05440 mf->cache->memfree(mf->cache,ch->Display[i].String); 05441 05442 mf->cache->memfree(mf->cache,ch->Display[i].Language); 05443 05444 mf->cache->memfree(mf->cache,ch->Display[i].Country); 05445 05446 } 05447 05448 mf->cache->memfree(mf->cache,ch->Display); 05449 05450 mf->cache->memfree(mf->cache,ch->Tracks); 05451 05452 05453 05454 for (i=0;i<ch->nProcess;++i) { 05455 05456 for (j=0;j<ch->Process[i].nCommands;++j) 05457 05458 mf->cache->memfree(mf->cache,ch->Process[i].Commands[j].Command); 05459 05460 mf->cache->memfree(mf->cache,ch->Process[i].Commands); 05461 05462 mf->cache->memfree(mf->cache,ch->Process[i].CodecPrivate); 05463 05464 } 05465 05466 mf->cache->memfree(mf->cache,ch->Process); 05467 05468 05469 05470 for (i=0;i<ch->nChildren;++i) 05471 05472 DeleteChapter(mf,&ch->Children[i]); 05473 05474 mf->cache->memfree(mf->cache,ch->Children); 05475 05476 } 05477 05478 05479 05481 05482 // public interface 05483 05484 MatroskaFile *mkv_OpenEx(InputStream *io, 05485 05486 ulonglong base, 05487 05488 unsigned flags, 05489 05490 char *err_msg,unsigned msgsize) 05491 05492 { 05493 05494 MatroskaFile *mf = io->memalloc(io,sizeof(*mf)); 05495 05496 if (mf == NULL) { 05497 05498 strncpy(err_msg,"Out of memory",msgsize); 05499 05500 return NULL; 05501 05502 } 05503 05504 05505 05506 memset(mf,0,sizeof(*mf)); 05507 05508 05509 05510 mf->cache = io; 05511 05512 mf->flags = flags; 05513 05514 io->progress(io,0,0); 05515 05516 05517 05518 if (setjmp(mf->jb)==0) { 05519 05520 seek(mf,base); 05521 05522 parseFile(mf); 05523 05524 } else { // parser error 05525 05526 strncpy(err_msg,mf->errmsg,msgsize); 05527 05528 mkv_Close(mf); 05529 05530 return NULL; 05531 05532 } 05533 05534 05535 05536 return mf; 05537 05538 } 05539 05540 05541 05542 MatroskaFile *mkv_Open(InputStream *io, 05543 05544 char *err_msg,unsigned msgsize) 05545 05546 { 05547 05548 return mkv_OpenEx(io,0,0,err_msg,msgsize); 05549 05550 } 05551 05552 05553 05554 void mkv_Close(MatroskaFile *mf) { 05555 05556 unsigned i,j; 05557 05558 05559 05560 if (mf==NULL) 05561 05562 return; 05563 05564 05565 05566 for (i=0;i<mf->nTracks;++i) 05567 05568 mf->cache->memfree(mf->cache,mf->Tracks[i]); 05569 05570 mf->cache->memfree(mf->cache,mf->Tracks); 05571 05572 05573 05574 for (i=0;i<mf->nQBlocks;++i) 05575 05576 mf->cache->memfree(mf->cache,mf->QBlocks[i]); 05577 05578 mf->cache->memfree(mf->cache,mf->QBlocks); 05579 05580 05581 05582 mf->cache->memfree(mf->cache,mf->Queues); 05583 05584 05585 05586 mf->cache->memfree(mf->cache,mf->Seg.Title); 05587 05588 mf->cache->memfree(mf->cache,mf->Seg.MuxingApp); 05589 05590 mf->cache->memfree(mf->cache,mf->Seg.WritingApp); 05591 05592 mf->cache->memfree(mf->cache,mf->Seg.Filename); 05593 05594 mf->cache->memfree(mf->cache,mf->Seg.NextFilename); 05595 05596 mf->cache->memfree(mf->cache,mf->Seg.PrevFilename); 05597 05598 05599 05600 mf->cache->memfree(mf->cache,mf->Cues); 05601 05602 05603 05604 for (i=0;i<mf->nAttachments;++i) { 05605 05606 mf->cache->memfree(mf->cache,mf->Attachments[i].Description); 05607 05608 mf->cache->memfree(mf->cache,mf->Attachments[i].Name); 05609 05610 mf->cache->memfree(mf->cache,mf->Attachments[i].MimeType); 05611 05612 } 05613 05614 mf->cache->memfree(mf->cache,mf->Attachments); 05615 05616 05617 05618 for (i=0;i<mf->nChapters;++i) 05619 05620 DeleteChapter(mf,&mf->Chapters[i]); 05621 05622 mf->cache->memfree(mf->cache,mf->Chapters); 05623 05624 05625 05626 for (i=0;i<mf->nTags;++i) { 05627 05628 for (j=0;j<mf->Tags[i].nSimpleTags;++j) { 05629 05630 mf->cache->memfree(mf->cache,mf->Tags[i].SimpleTags[j].Name); 05631 05632 mf->cache->memfree(mf->cache,mf->Tags[i].SimpleTags[j].Value); 05633 05634 } 05635 05636 mf->cache->memfree(mf->cache,mf->Tags[i].Targets); 05637 05638 mf->cache->memfree(mf->cache,mf->Tags[i].SimpleTags); 05639 05640 } 05641 05642 mf->cache->memfree(mf->cache,mf->Tags); 05643 05644 05645 05646 mf->cache->memfree(mf->cache,mf); 05647 05648 } 05649 05650 05651 05652 const char *mkv_GetLastError(MatroskaFile *mf) { 05653 05654 return mf->errmsg[0] ? mf->errmsg : NULL; 05655 05656 } 05657 05658 05659 05660 SegmentInfo *mkv_GetFileInfo(MatroskaFile *mf) { 05661 05662 return &mf->Seg; 05663 05664 } 05665 05666 05667 05668 unsigned int mkv_GetNumTracks(MatroskaFile *mf) { 05669 05670 return mf->nTracks; 05671 05672 } 05673 05674 05675 05676 TrackInfo *mkv_GetTrackInfo(MatroskaFile *mf,unsigned track) { 05677 05678 if (track>mf->nTracks) 05679 05680 return NULL; 05681 05682 05683 05684 return mf->Tracks[track]; 05685 05686 } 05687 05688 05689 05690 void mkv_GetAttachments(MatroskaFile *mf,Attachment **at,unsigned *count) { 05691 05692 *at = mf->Attachments; 05693 05694 *count = mf->nAttachments; 05695 05696 } 05697 05698 05699 05700 void mkv_GetChapters(MatroskaFile *mf,Chapter **ch,unsigned *count) { 05701 05702 *ch = mf->Chapters; 05703 05704 *count = mf->nChapters; 05705 05706 } 05707 05708 05709 05710 void mkv_GetTags(MatroskaFile *mf,Tag **tag,unsigned *count) { 05711 05712 *tag = mf->Tags; 05713 05714 *count = mf->nTags; 05715 05716 } 05717 05718 05719 05720 ulonglong mkv_GetSegmentTop(MatroskaFile *mf) { 05721 05722 return mf->pSegmentTop; 05723 05724 } 05725 05726 05727 05728 #define IS_DELTA(f) (!((f)->flags & FRAME_KF) || ((f)->flags & FRAME_UNKNOWN_START)) 05729 05730 05731 05732 void mkv_Seek(MatroskaFile *mf,ulonglong timecode,unsigned flags) { 05733 05734 int i,j,m,ret; 05735 05736 unsigned n,z,mask; 05737 05738 ulonglong m_kftime[MAX_TRACKS]; 05739 05740 unsigned char m_seendf[MAX_TRACKS]; 05741 05742 05743 05744 if (mf->flags & MKVF_AVOID_SEEKS) 05745 05746 return; 05747 05748 05749 05750 if (timecode == 0) { 05751 05752 EmptyQueues(mf); 05753 05754 mf->readPosition = mf->pCluster; 05755 05756 mf->tcCluster = mf->firstTimecode; 05757 05758 mf->flags &= ~MPF_ERROR; 05759 05760 05761 05762 return; 05763 05764 } 05765 05766 05767 05768 if (mf->nCues==0) 05769 05770 reindex(mf); 05771 05772 05773 05774 if (mf->nCues==0) 05775 05776 return; 05777 05778 05779 05780 mf->flags &= ~MPF_ERROR; 05781 05782 05783 05784 i = 0; 05785 05786 j = mf->nCues - 1; 05787 05788 05789 05790 for (;;) { 05791 05792 if (i>j) { 05793 05794 j = j>=0 ? j : 0; 05795 05796 05797 05798 if (setjmp(mf->jb)!=0) 05799 05800 return; 05801 05802 05803 05804 mkv_SetTrackMask(mf,mf->trackMask); 05805 05806 05807 05808 if (flags & MKVF_SEEK_TO_PREV_KEYFRAME) { 05809 05810 // we do this in two stages 05811 05812 // a. find the last keyframes before the require position 05813 05814 // b. seek to them 05815 05816 05817 05818 // pass 1 05819 05820 for (;;) { 05821 05822 for (n=0;n<mf->nTracks;++n) { 05823 05824 m_kftime[n] = MAXU64; 05825 05826 m_seendf[n] = 0; 05827 05828 } 05829 05830 05831 05832 EmptyQueues(mf); 05833 05834 05835 05836 mf->readPosition = mf->Cues[j].Position + mf->pSegment; 05837 05838 mf->tcCluster = mf->Cues[j].Time / mf->Seg.TimecodeScale; 05839 05840 05841 05842 for (;;) { 05843 05844 if ((ret = fillQueues(mf,0)) < 0 || ret == RBRESYNC) 05845 05846 return; 05847 05848 05849 05850 // drain queues until we get to the required timecode 05851 05852 for (n=0;n<mf->nTracks;++n) { 05853 05854 if (mf->Queues[n].head && mf->Queues[n].head->Start<timecode) { 05855 05856 if (IS_DELTA(mf->Queues[n].head)) 05857 05858 m_seendf[n] = 1; 05859 05860 else 05861 05862 m_kftime[n] = mf->Queues[n].head->Start; 05863 05864 } 05865 05866 05867 05868 while (mf->Queues[n].head && mf->Queues[n].head->Start<timecode) 05869 05870 { 05871 05872 if (IS_DELTA(mf->Queues[n].head)) 05873 05874 m_seendf[n] = 1; 05875 05876 else 05877 05878 m_kftime[n] = mf->Queues[n].head->Start; 05879 05880 QFree(mf,QGet(&mf->Queues[n])); 05881 05882 } 05883 05884 05885 05886 if (mf->Queues[n].head && (mf->Tracks[n]->Type != TT_AUDIO || mf->Queues[n].head->Start<=timecode)) 05887 05888 if (!IS_DELTA(mf->Queues[n].head)) 05889 05890 m_kftime[n] = mf->Queues[n].head->Start; 05891 05892 } 05893 05894 05895 05896 for (n=0;n<mf->nTracks;++n) 05897 05898 if (mf->Queues[n].head && mf->Queues[n].head->Start>=timecode) 05899 05900 goto found; 05901 05902 } 05903 05904 found: 05905 05906 05907 05908 for (n=0;n<mf->nTracks;++n) 05909 05910 if (!(mf->trackMask & (1<<n)) && m_kftime[n]==MAXU64 && 05911 05912 m_seendf[n] && j>0) 05913 05914 { 05915 05916 // we need to restart the search from prev cue 05917 05918 --j; 05919 05920 goto again; 05921 05922 } 05923 05924 05925 05926 break; 05927 05928 again:; 05929 05930 } 05931 05932 } else 05933 05934 for (n=0;n<mf->nTracks;++n) 05935 05936 m_kftime[n] = timecode; 05937 05938 05939 05940 // now seek to this timecode 05941 05942 EmptyQueues(mf); 05943 05944 05945 05946 mf->readPosition = mf->Cues[j].Position + mf->pSegment; 05947 05948 mf->tcCluster = mf->Cues[j].Time / mf->Seg.TimecodeScale; 05949 05950 05951 05952 for (mask=0;;) { 05953 05954 if ((ret = fillQueues(mf,mask)) < 0 || ret == RBRESYNC) 05955 05956 return; 05957 05958 05959 05960 // drain queues until we get to the required timecode 05961 05962 for (n=0;n<mf->nTracks;++n) { 05963 05964 struct QueueEntry *qe; 05965 05966 for (qe = mf->Queues[n].head;qe && qe->Start<m_kftime[n];qe = mf->Queues[n].head) 05967 05968 QFree(mf,QGet(&mf->Queues[n])); 05969 05970 } 05971 05972 05973 05974 for (n=z=0;n<mf->nTracks;++n) 05975 05976 if (m_kftime[n]==MAXU64 || (mf->Queues[n].head && mf->Queues[n].head->Start>=m_kftime[n])) { 05977 05978 ++z; 05979 05980 mask |= 1<<n; 05981 05982 } 05983 05984 05985 05986 if (z==mf->nTracks) 05987 05988 return; 05989 05990 } 05991 05992 } 05993 05994 05995 05996 m = (i+j)>>1; 05997 05998 05999 06000 if (timecode < mf->Cues[m].Time) 06001 06002 j = m-1; 06003 06004 else 06005 06006 i = m+1; 06007 06008 } 06009 06010 } 06011 06012 06013 06014 void mkv_SkipToKeyframe(MatroskaFile *mf) { 06015 06016 unsigned n,wait; 06017 06018 ulonglong ht; 06019 06020 06021 06022 if (setjmp(mf->jb)!=0) 06023 06024 return; 06025 06026 06027 06028 // remove delta frames from queues 06029 06030 do { 06031 06032 wait = 0; 06033 06034 06035 06036 if (fillQueues(mf,0)<0) 06037 06038 return; 06039 06040 06041 06042 for (n=0;n<mf->nTracks;++n) 06043 06044 if (mf->Queues[n].head && !(mf->Queues[n].head->flags & FRAME_KF)) { 06045 06046 ++wait; 06047 06048 QFree(mf,QGet(&mf->Queues[n])); 06049 06050 } 06051 06052 } while (wait); 06053 06054 06055 06056 // find highest queued time 06057 06058 for (n=0,ht=0;n<mf->nTracks;++n) 06059 06060 if (mf->Queues[n].head && ht<mf->Queues[n].head->Start) 06061 06062 ht = mf->Queues[n].head->Start; 06063 06064 06065 06066 // ensure the time difference is less than 100ms 06067 06068 do { 06069 06070 wait = 0; 06071 06072 06073 06074 if (fillQueues(mf,0)<0) 06075 06076 return; 06077 06078 06079 06080 for (n=0;n<mf->nTracks;++n) 06081 06082 while (mf->Queues[n].head && mf->Queues[n].head->next && 06083 06084 (mf->Queues[n].head->next->flags & FRAME_KF) && 06085 06086 ht - mf->Queues[n].head->Start > 100000000) 06087 06088 { 06089 06090 ++wait; 06091 06092 QFree(mf,QGet(&mf->Queues[n])); 06093 06094 } 06095 06096 06097 06098 } while (wait); 06099 06100 } 06101 06102 06103 06104 ulonglong mkv_GetLowestQTimecode(MatroskaFile *mf) { 06105 06106 unsigned n,seen; 06107 06108 ulonglong t; 06109 06110 06111 06112 // find the lowest queued timecode 06113 06114 for (n=seen=0,t=0;n<mf->nTracks;++n) 06115 06116 if (mf->Queues[n].head && (!seen || t > mf->Queues[n].head->Start)) 06117 06118 t = mf->Queues[n].head->Start, seen=1; 06119 06120 06121 06122 return seen ? t : (ulonglong)LL(-1); 06123 06124 } 06125 06126 06127 06128 int mkv_TruncFloat(MKFLOAT f) { 06129 06130 #ifdef MATROSKA_INTEGER_ONLY 06131 06132 return (int)(f.v >> 32); 06133 06134 #else 06135 06136 return (int)f; 06137 06138 #endif 06139 06140 } 06141 06142 06143 06144 #define FTRACK 0xffffffff 06145 06146 06147 06148 void mkv_SetTrackMask(MatroskaFile *mf,unsigned int mask) { 06149 06150 unsigned int i; 06151 06152 06153 06154 if (mf->flags & MPF_ERROR) 06155 06156 return; 06157 06158 06159 06160 mf->trackMask = mask; 06161 06162 06163 06164 for (i=0;i<mf->nTracks;++i) 06165 06166 if (mask & (1<<i)) 06167 06168 ClearQueue(mf,&mf->Queues[i]); 06169 06170 } 06171 06172 06173 06174 int mkv_ReadFrame(MatroskaFile *mf, 06175 06176 unsigned int mask,unsigned int *track, 06177 06178 ulonglong *StartTime,ulonglong *EndTime, 06179 06180 ulonglong *FilePos,unsigned int *FrameSize, 06181 06182 unsigned int *FrameFlags) 06183 06184 { 06185 06186 unsigned int i,j; 06187 06188 struct QueueEntry *qe; 06189 06190 06191 06192 if (setjmp(mf->jb)!=0) 06193 06194 return -1; 06195 06196 06197 06198 do { 06199 06200 // extract required frame, use block with the lowest timecode 06201 06202 for (j=FTRACK,i=0;i<mf->nTracks;++i) 06203 06204 if (!(mask & (1<<i)) && mf->Queues[i].head) { 06205 06206 j = i; 06207 06208 ++i; 06209 06210 break; 06211 06212 } 06213 06214 06215 06216 for (;i<mf->nTracks;++i) 06217 06218 if (!(mask & (1<<i)) && mf->Queues[i].head && 06219 06220 mf->Queues[j].head->Start > mf->Queues[i].head->Start) 06221 06222 j = i; 06223 06224 06225 06226 if (j != FTRACK) { 06227 06228 qe = QGet(&mf->Queues[j]); 06229 06230 06231 06232 *track = j; 06233 06234 *StartTime = qe->Start; 06235 06236 *EndTime = qe->End; 06237 06238 *FilePos = qe->Position; 06239 06240 *FrameSize = qe->Length; 06241 06242 *FrameFlags = qe->flags; 06243 06244 06245 06246 QFree(mf,qe); 06247 06248 06249 06250 return 0; 06251 06252 } 06253 06254 06255 06256 if (mf->flags & MPF_ERROR) 06257 06258 return -1; 06259 06260 06261 06262 } while (fillQueues(mf,mask)>=0); 06263 06264 06265 06266 return EOF; 06267 06268 } 06269 06270 06271 06272 #ifdef MATROSKA_COMPRESSION_SUPPORT 06273 06274 /************************************************************************* 06275 06276 * Compressed streams support 06277 06278 ************************************************************************/ 06279 06280 struct CompressedStream { 06281 06282 MatroskaFile *mf; 06283 06284 z_stream zs; 06285 06286 06287 06288 /* current compressed frame */ 06289 06290 ulonglong frame_pos; 06291 06292 unsigned frame_size; 06293 06294 char frame_buffer[2048]; 06295 06296 06297 06298 /* decoded data buffer */ 06299 06300 char decoded_buffer[2048]; 06301 06302 unsigned decoded_ptr; 06303 06304 unsigned decoded_size; 06305 06306 06307 06308 /* error handling */ 06309 06310 char errmsg[128]; 06311 06312 }; 06313 06314 06315 06316 CompressedStream *cs_Create(/* in */ MatroskaFile *mf, 06317 06318 /* in */ unsigned tracknum, 06319 06320 /* out */ char *errormsg, 06321 06322 /* in */ unsigned msgsize) 06323 06324 { 06325 06326 CompressedStream *cs; 06327 06328 TrackInfo *ti; 06329 06330 int code; 06331 06332 06333 06334 ti = mkv_GetTrackInfo(mf, tracknum); 06335 06336 if (ti == NULL) { 06337 06338 strncpy(errormsg, "No such track.", msgsize); 06339 06340 return NULL; 06341 06342 } 06343 06344 06345 06346 if (!ti->CompEnabled) { 06347 06348 strncpy(errormsg, "Track is not compressed.", msgsize); 06349 06350 return NULL; 06351 06352 } 06353 06354 06355 06356 if (ti->CompMethod != COMP_ZLIB) { 06357 06358 strncpy(errormsg, "Unsupported compression method.", msgsize); 06359 06360 return NULL; 06361 06362 } 06363 06364 06365 06366 cs = mf->cache->memalloc(mf->cache,sizeof(*cs)); 06367 06368 if (cs == NULL) { 06369 06370 strncpy(errormsg, "Ouf of memory.", msgsize); 06371 06372 return NULL; 06373 06374 } 06375 06376 06377 06378 memset(&cs->zs,0,sizeof(cs->zs)); 06379 06380 code = inflateInit(&cs->zs); 06381 06382 if (code != Z_OK) { 06383 06384 strncpy(errormsg, "ZLib error.", msgsize); 06385 06386 mf->cache->memfree(mf->cache,cs); 06387 06388 return NULL; 06389 06390 } 06391 06392 06393 06394 cs->frame_size = 0; 06395 06396 cs->decoded_ptr = cs->decoded_size = 0; 06397 06398 cs->mf = mf; 06399 06400 06401 06402 return cs; 06403 06404 } 06405 06406 06407 06408 void cs_Destroy(/* in */ CompressedStream *cs) { 06409 06410 if (cs == NULL) 06411 06412 return; 06413 06414 06415 06416 inflateEnd(&cs->zs); 06417 06418 cs->mf->cache->memfree(cs->mf->cache,cs); 06419 06420 } 06421 06422 06423 06424 /* advance to the next frame in matroska stream, you need to pass values returned 06425 06426 * by mkv_ReadFrame */ 06427 06428 void cs_NextFrame(/* in */ CompressedStream *cs, 06429 06430 /* in */ ulonglong pos, 06431 06432 /* in */ unsigned size) 06433 06434 { 06435 06436 cs->zs.avail_in = 0; 06437 06438 inflateReset(&cs->zs); 06439 06440 cs->frame_pos = pos; 06441 06442 cs->frame_size = size; 06443 06444 cs->decoded_ptr = cs->decoded_size = 0; 06445 06446 } 06447 06448 06449 06450 /* read and decode more data from current frame, return number of bytes decoded, 06451 06452 * 0 on end of frame, or -1 on error */ 06453 06454 int cs_ReadData(CompressedStream *cs,char *buffer,unsigned bufsize) 06455 06456 { 06457 06458 char *cp = buffer; 06459 06460 unsigned rd = 0; 06461 06462 unsigned todo; 06463 06464 int code; 06465 06466 06467 06468 do { 06469 06470 /* try to copy data from decoded buffer */ 06471 06472 if (cs->decoded_ptr < cs->decoded_size) { 06473 06474 todo = cs->decoded_size - cs->decoded_ptr;; 06475 06476 if (todo > bufsize - rd) 06477 06478 todo = bufsize - rd; 06479 06480 06481 06482 memcpy(cp, cs->decoded_buffer + cs->decoded_ptr, todo); 06483 06484 06485 06486 rd += todo; 06487 06488 cp += todo; 06489 06490 cs->decoded_ptr += todo; 06491 06492 } else { 06493 06494 /* setup output buffer */ 06495 06496 cs->zs.next_out = cs->decoded_buffer; 06497 06498 cs->zs.avail_out = sizeof(cs->decoded_buffer); 06499 06500 06501 06502 /* try to read more data */ 06503 06504 if (cs->zs.avail_in == 0 && cs->frame_size > 0) { 06505 06506 todo = cs->frame_size; 06507 06508 if (todo > sizeof(cs->frame_buffer)) 06509 06510 todo = sizeof(cs->frame_buffer); 06511 06512 06513 06514 if (cs->mf->cache->read(cs->mf->cache, cs->frame_pos, cs->frame_buffer, todo) != (int)todo) { 06515 06516 strncpy(cs->errmsg, "File read failed", sizeof(cs->errmsg)); 06517 06518 return -1; 06519 06520 } 06521 06522 06523 06524 cs->zs.next_in = cs->frame_buffer; 06525 06526 cs->zs.avail_in = todo; 06527 06528 06529 06530 cs->frame_pos += todo; 06531 06532 cs->frame_size -= todo; 06533 06534 } 06535 06536 06537 06538 /* try to decode more data */ 06539 06540 code = inflate(&cs->zs,Z_NO_FLUSH); 06541 06542 if (code != Z_OK && code != Z_STREAM_END) { 06543 06544 strncpy(cs->errmsg, "ZLib error.", sizeof(cs->errmsg)); 06545 06546 return -1; 06547 06548 } 06549 06550 06551 06552 /* handle decoded data */ 06553 06554 if (cs->zs.avail_out == sizeof(cs->decoded_buffer)) /* EOF */ 06555 06556 break; 06557 06558 06559 06560 cs->decoded_ptr = 0; 06561 06562 cs->decoded_size = sizeof(cs->decoded_buffer) - cs->zs.avail_out; 06563 06564 } 06565 06566 } while (rd < bufsize); 06567 06568 06569 06570 return rd; 06571 06572 } 06573 06574 06575 06576 /* return error message for the last error */ 06577 06578 const char *cs_GetLastError(CompressedStream *cs) 06579 06580 { 06581 06582 if (!cs->errmsg[0]) 06583 06584 return NULL; 06585 06586 return cs->errmsg; 06587 06588 } 06589 06590 #endif 06591 06592 06593 #endif