dumptrack.c
Upload User: wstnjxml
Upload Date: 2014-04-03
Package Size: 7248k
Code Size: 8k
Category:

Windows CE

Development Platform:

C/C++

  1. /*
  2.  * Copyright (c) 2004-2005 Mike Matsnev.  All Rights Reserved.
  3.  *
  4.  * Redistribution and use in source and binary forms, with or without
  5.  * modification, are permitted provided that the following conditions
  6.  * are met:
  7.  *
  8.  * 1. Redistributions of source code must retain the above copyright
  9.  *    notice immediately at the beginning of the file, without modification,
  10.  *    this list of conditions, and the following disclaimer.
  11.  * 2. Redistributions in binary form must reproduce the above copyright
  12.  *    notice, this list of conditions and the following disclaimer in the
  13.  *    documentation and/or other materials provided with the distribution.
  14.  * 3. Absolutely no warranty of function or purpose is made by the author
  15.  *    Mike Matsnev.
  16.  *
  17.  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
  18.  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
  19.  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
  20.  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
  21.  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
  22.  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
  23.  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
  24.  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
  25.  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
  26.  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  27.  * 
  28.  * $Id: dumptrack.c,v 1.3 2005/03/07 11:24:21 mike Exp $
  29.  * 
  30.  */
  31. /*
  32.  * This is a complete sample of MatroskaParser usage. The program will dump
  33.  * one of source file tracks to stdout.
  34.  */
  35. #include <stdlib.h>
  36. #include <stdio.h>
  37. #include <errno.h>
  38. #include <string.h>
  39. #include <fcntl.h>
  40. /* windows-specific */
  41. #ifdef WIN32
  42. #include <io.h>
  43. #endif
  44. #include "../MatroskaParser/MatroskaParser.h"
  45. /* first we need to create an I/O object that the parser will use to read the
  46.  * source file
  47.  */
  48. struct StdIoStream {
  49.   struct InputStream  base;
  50.   FILE       *fp;
  51.   int       error;
  52. };
  53. typedef struct StdIoStream StdIoStream;
  54. #define CACHESIZE     65536
  55. /* StdIoStream methods */
  56. /* read count bytes into buffer starting at file position pos
  57.  * return the number of bytes read, -1 on error or 0 on EOF
  58.  */
  59. int   StdIoRead(StdIoStream *st, ulonglong pos, void *buffer, int count) {
  60.   size_t  rd;
  61.   if (fseek(st->fp, pos, SEEK_SET)) {
  62.     st->error = errno;
  63.     return -1;
  64.   }
  65.   rd = fread(buffer, 1, count, st->fp);
  66.   if (rd == 0) {
  67.     if (feof(st->fp))
  68.       return 0;
  69.     st->error = errno;
  70.     return -1;
  71.   }
  72.   return rd;
  73. }
  74. /* scan for a signature sig(big-endian) starting at file position pos
  75.  * return position of the first byte of signature or -1 if error/not found
  76.  */
  77. longlong StdIoScan(StdIoStream *st, ulonglong start, unsigned signature) {
  78.   int       c;
  79.   unsigned    cmp = 0;
  80.   FILE       *fp = st->fp;
  81.   if (fseek(fp, start, SEEK_SET))
  82.     return -1;
  83.   while ((c = getc(fp)) != EOF) {
  84.     cmp = ((cmp << 8) | c) & 0xffffffff;
  85.     if (cmp == signature)
  86.       return ftell(fp) - 4;
  87.   }
  88.   return -1;
  89. }
  90. /* return cache size, this is used to limit readahead */
  91. unsigned StdIoGetCacheSize(StdIoStream *st) {
  92.   return CACHESIZE;
  93. }
  94. /* return last error message */
  95. const char *StdIoGetLastError(StdIoStream *st) {
  96.   return strerror(st->error);
  97. }
  98. /* memory allocation, this is done via stdlib */
  99. void  *StdIoMalloc(StdIoStream *st, size_t size) {
  100.   return malloc(size);
  101. }
  102. void  *StdIoRealloc(StdIoStream *st, void *mem, size_t size) {
  103.   return realloc(mem,size);
  104. }
  105. void  StdIoFree(StdIoStream *st, void *mem) {
  106.   free(mem);
  107. }
  108. /* progress report handler for lengthy operations
  109.  * returns 0 to abort operation, nonzero to continue
  110.  */
  111. int   StdIoProgress(StdIoStream *st, ulonglong cur, ulonglong max) {
  112.   return 1;
  113. }
  114. /* main program */
  115. int   main(int argc,char **argv) {
  116.   StdIoStream st;
  117.   MatroskaFile *mf;
  118.   char err_msg[256];
  119.   unsigned i;
  120.   int track;
  121.   FILE *out = stdout;
  122.   if (argc < 2 || argc > 3) {
  123.     fprintf(stderr,"Usage: %s filename.mkv [track_num]n",argv[0]);
  124.     return 1;
  125.   }
  126. #ifdef WIN32
  127.   { /* windows-specific, turn off text translation */
  128.     int nfd = dup(fileno(stdout));
  129.     _setmode(nfd, _O_BINARY);
  130.     out = _fdopen(nfd,"wb");
  131.   }
  132. #endif
  133.   /* fill in I/O object */
  134.   memset(&st,0,sizeof(st));
  135.   st.base.read = StdIoRead;
  136.   st.base.scan = StdIoScan;
  137.   st.base.getsize = StdIoGetCacheSize;
  138.   st.base.geterror = StdIoGetLastError;
  139.   st.base.memalloc = StdIoMalloc;
  140.   st.base.memrealloc = StdIoRealloc;
  141.   st.base.memfree = StdIoFree;
  142.   st.base.progress = StdIoProgress;
  143.   /* open source file */
  144.   st.fp = fopen(argv[1],"rb");
  145.   if (st.fp == NULL) {
  146.     fprintf(stderr,"Can't open '%s': %sn",argv[1],strerror(errno));
  147.     return 1;
  148.   }
  149.   setvbuf(st.fp, NULL, _IOFBF, CACHESIZE);
  150.   /* initialize matroska parser */
  151.   mf = mkv_OpenEx(&st.base, /* pointer to I/O object */
  152.     0, /* starting position in the file */
  153.     0, /* flags, you can set MKVF_AVOID_SEEKS if this is a non-seekable stream */
  154.     err_msg, sizeof(err_msg)); /* error message is returned here */
  155.   if (mf == NULL) {
  156.     fclose(st.fp);
  157.     fprintf(stderr,"Can't parse Matroska file: %sn", err_msg);
  158.     return 1;
  159.   }
  160.   /* if track_num was not specified, then list tracks */
  161.   if (argc == 2) {
  162.     for (i = 0; i < mkv_GetNumTracks(mf); ++i) {
  163.       TrackInfo *ti = mkv_GetTrackInfo(mf, i);
  164.       printf("Track %u: %sn", i, ti->CodecID);
  165.     }
  166.   } else {
  167.     ulonglong       StartTime, EndTime, FilePos;
  168.     unsigned       rt, FrameSize, FrameFlags;
  169.     unsigned       fb = 0;
  170.     void       *frame = NULL;
  171.     CompressedStream  *cs = NULL;
  172.     /* extract track */
  173.     track = atoi(argv[2]);
  174.     if (track < 0 || (unsigned)track >= mkv_GetNumTracks(mf)) {
  175.       fprintf(stderr,"Invalid track number: %dn", track);
  176.       goto done;
  177.     }
  178.     /* mask other tracks because we don't need them */
  179.     mkv_SetTrackMask(mf, ~(1 << track));
  180.     /* init zlib decompressor if needed */
  181.     if (mkv_GetTrackInfo(mf,track)->CompEnabled) {
  182.       cs = cs_Create(mf, track, err_msg, sizeof(err_msg));
  183.       if (cs == NULL) {
  184. fprintf(stderr,"Can't create decompressor: %sn",err_msg);
  185. goto done;
  186.       }
  187.     }
  188.     /* read frames from file */
  189.     while (mkv_ReadFrame(mf, 0, &rt, &StartTime, &EndTime, &FilePos, &FrameSize, &FrameFlags) == 0)
  190.     {
  191.       if (cs) {
  192. char buffer[1024];
  193. cs_NextFrame(cs,FilePos,FrameSize);
  194. for (;;) {
  195.   int rd = cs_ReadData(cs,buffer,sizeof(buffer));
  196.   if (rd < 0) {
  197.     fprintf(stderr,"Error decompressing data: %sn",cs_GetLastError(cs));
  198.     goto done;
  199.   }
  200.   if (rd == 0)
  201.     break;
  202.   fwrite(buffer,1,rd,out);
  203. }
  204.       } else {
  205. size_t   rd;
  206. if (fseek(st.fp, FilePos, SEEK_SET)) {
  207.   fprintf(stderr,"fseek(): %sn", strerror(errno));
  208.   goto done;
  209. }
  210. if (fb < FrameSize) {
  211.   fb = FrameSize;
  212.   frame = realloc(frame, fb);
  213.   if (frame == NULL) {
  214.     fprintf(stderr,"Out of memoryn");
  215.     goto done;
  216.   }
  217. }
  218. rd = fread(frame,1,FrameSize,st.fp);
  219. if (rd != FrameSize) {
  220.   if (rd == 0) {
  221.     if (feof(st.fp))
  222.       fprintf(stderr,"Unexpected EOF while reading framen");
  223.     else
  224.       fprintf(stderr,"Error reading frame: %sn",strerror(errno));
  225.   } else
  226.     fprintf(stderr,"Short read while reading framen");
  227.   goto done;
  228. }
  229. fwrite(frame,1,FrameSize,out);
  230.       }
  231.     }
  232.   }
  233. done:
  234.   /* close matroska parser */
  235.   mkv_Close(mf);
  236.   /* close file */
  237.   fclose(st.fp);
  238.   return 0;
  239. }