User Tools

Site Tools


tech:multimedia:rmvb

This is an old revision of the document!


#include <stdio.h> #include <stdlib.h>

#define MKTAG(a,b,c,d) (d | (c « 8) | (b « 16) | (a « 24)) #define ERROR do {printf(“Error Detected\n”); exit(0);} while(0)

#define REALAUDIO_MIME_TYPE “audio/x-pn-realaudio” #define REALVIDEO_MIME_TYPE “video/x-pn-realvideo”

static int audio_stream = -1; static int video_stream = -1;

int rmvb_unpack32(FILE *fp, unsigned int *pVal) {

  unsigned char buf[4];

if (fread(buf, 1, 4, fp) != 4)

  {
      return -1;
  }
  • pVal = (buf[0] « 24)|(buf[1] « 16)|(buf[2] « 8)|buf[3];

return 0; }

int rmvb_unpack16(FILE *fp, unsigned short *pVal) {

  unsigned char buf[2];

if (fread(buf, 1, 2, fp) != 2)

  {
      return -1;
  }
  • pVal = (buf[0] « 8)|buf[1];

return 0;

}

int rmvb_unpack8(FILE *fp, unsigned char *pVal) {

  • pVal = (unsigned char) fgetc(fp);

if (feof(fp))

      return -1;
  else 
      return 0;

}

int rmvb_unpack14or30(FILE *fp, unsigned int *pval, unsigned int *len) {

  unsigned short tmp1;
  unsigned int tmp2;

if (rmvb_unpack16(fp, &tmp1)) return -1;

  if (tmp1&0x4000)
  {
      *pval = tmp1&0x3fff;
      *len = 2;
  }
  else
  {
      fseek(fp, -2, SEEK_CUR);
      if (rmvb_unpack32(fp, &tmp2)) return -1;
      *pval = tmp2&0x3ffffff;
      *len = 4;
  }   

return 0; }

int parse_basic(FILE *fp, unsigned int *pId, unsigned int *pSize, unsigned short *pVersion) {

  unsigned int size;
  unsigned short version;

if (rmvb_unpack32(fp, pId))

      return -1;
  if (rmvb_unpack32(fp, pSize))
      return -1;
  if (rmvb_unpack16(fp, pVersion))
      return -1;

return 0; }

int parse_indx(FILE *fp, unsigned int size, unsigned short version) {

  unsigned int pos = ftell(fp) - 10;

printf(“\nINDX Detected @0x%x, size=%u, version = %d\n”, pos, size, version);

fseek(fp, pos+size, SEEK_SET);

return 0; }

int parse_frame(FILE *fp, int size) {

  unsigned int pos = ftell(fp);
  unsigned short tmp1;
  unsigned char type, seq, tmp2;
  unsigned int size2, time, len, off;
  unsigned char packets, packet;
  if (rmvb_unpack16(fp, &tmp1)) return -1;
  type = tmp1 >> 14;
  fseek(fp, -2, SEEK_CUR);

switch(type)

  {
    /* partial frame */
      case 0:
      case 2:
          if (rmvb_unpack16(fp, &tmp1)) return -1;
          if (rmvb_unpack14or30(fp, &len, &size2)) return -1;
          if (rmvb_unpack14or30(fp, &off, &size2)) return -1;
          if (rmvb_unpack8(fp, &seq)) return -1;
          packets = ((tmp1 & 0x3F80) >> 7);
          packet = (tmp1 & 0x007F);
          printf("\t\t");
          if (packet == 1) putchar('{');
          else putchar('+');
          printf("No.%d (%d-%d), %d@%d", seq, packets, packet, off, len);
          if (packet == packets) putchar('}');
          else putchar('+');
          putchar('\n');
          break;
      case 1:
          if (rmvb_unpack8(fp, &tmp2)) return -1;
          if (rmvb_unpack8(fp, &seq)) return -1;
          printf("\t\t{No.%d}\n", seq);
          break;
      case 3:
          while (size > 0)
          {
              putchar('\t');
              putchar('\t');
              len = 0;
              if (rmvb_unpack8(fp, &tmp2)) return -1;
              if (rmvb_unpack14or30(fp, &size2, &len)) return -1;
              size -= len;
              if (rmvb_unpack14or30(fp, &time, &len)) return -1;
              size -= len;
              if (rmvb_unpack8(fp, &seq)) return -1;
              size -=2;
              printf("{No.%d, size: %d, time: %d},\n", seq, size2, time);
              fseek(fp, size2, SEEK_CUR);
              size -= size2;
		}
          break;
      default:
          break;
  }

fseek(fp, pos+size, SEEK_SET);

  return 0;

}

int parse_packet(FILE *fp) {

  unsigned short version;
  unsigned short size;
  unsigned short stream;
  unsigned int time;
  unsigned char pkt_grp, flags;
  unsigned short asm_rule;
  unsigned int pos = ftell(fp);

if (rmvb_unpack16(fp, &version)) return -1;

  if (rmvb_unpack16(fp, &size)) return -1;
  if (rmvb_unpack16(fp, &stream)) return -1;
  if (rmvb_unpack32(fp, &time)) return -1;
  if (version == 0)
  {
      if (rmvb_unpack8(fp, &pkt_grp)) return -1;
      if (rmvb_unpack8(fp, &flags)) return -1;
  }
  else
  {
      if (rmvb_unpack16(fp, &asm_rule)) return -1;
      if (rmvb_unpack8(fp, &flags)) return -1;   
  }
  printf("stream#%d, size=%d, time:%d\n", stream, size, time);

if (stream == video_stream)

{
      if (parse_frame(fp, size-12-version)) return -1;
  }
  fseek(fp, pos+size, SEEK_SET);
  return 0;

}

int parse_data(FILE *fp, unsigned int size, unsigned short version) {

  unsigned int packets;
  unsigned int next;
  unsigned int pos = ftell(fp) - 10;
  int i;

printf(“\nDATA Detected @0x%x, size=%u, version = %d\n”, pos, size, version);

if (rmvb_unpack32(fp, &packets)) return -1;

  if (rmvb_unpack32(fp, &next)) return -1;

for (i = 0; i < packets; i++)

  {
      putchar('\t');
      printf("Packet %d: ", i);
      if (parse_packet(fp)) return -1;
  }

if (next)

      fseek(fp, next, SEEK_SET);
  else
      fseek(fp, pos+size, SEEK_SET);

return 0; }

int parse_prop(FILE *fp, unsigned int size, unsigned short version) {

  unsigned int pos = ftell(fp)-10;
  unsigned int v32;
  unsigned short v16;

printf(“\nPROP Detected @0x%x, size=%u, version = %d\n”, pos, size, version);

  putchar('\t');
  if (version == 0)
  {
      putchar('{');
      putchar(0x20);
      if (rmvb_unpack32(fp, &v32)) return -1;
      printf("bitrate: %u/", v32);
      if (rmvb_unpack32(fp, &v32)) return -1;
      printf("%u; ", v32);
      if (rmvb_unpack32(fp, &v32)) return -1;
      printf("packet size: %u/", v32);
      if (rmvb_unpack32(fp, &v32)) return -1;
      printf("%u; ", v32);
      if (rmvb_unpack32(fp, &v32)) return -1;
      printf("%u packets; ", v32);
      if (rmvb_unpack32(fp, &v32)) return -1;
      printf("duartion=%u ms; ", v32);
      if (rmvb_unpack32(fp, &v32)) return -1;
      if (rmvb_unpack32(fp, &v32)) return -1;
      printf("INDX@0x%x; ", v32);
      if (rmvb_unpack32(fp, &v32)) return -1;
      printf("DATA@0x%x; ", v32);
      if (rmvb_unpack16(fp, &v16)) return -1;
      printf("%u streams; ", v16);
      putchar('}');
  }
  putchar('\n');

fseek(fp, pos+size, SEEK_SET);

return 0; }

int parse_mdpr(FILE *fp, unsigned int size, unsigned short version) {

  unsigned int pos = ftell(fp) - 10;
  unsigned int v32;
  unsigned short v16;
  unsigned char v8;
  char pStr[256];
int stream_nbr = -1;

printf(“\nMDPR Detected @0x%x, size=%u, version = %d\n”, pos, size, version);

  putchar('\t');
  if (version == 0)
  {
      putchar('{');
      putchar(0x20);
      if (rmvb_unpack16(fp, &v16)) return -1;
      printf("stream#%d; ", v16);
	stream_nbr = v16;
      if (rmvb_unpack32(fp, &v32)) return -1;
      printf("bitrate: %u/", v32);
      if (rmvb_unpack32(fp, &v32)) return -1;
      printf("%u; ", v32);
      if (rmvb_unpack32(fp, &v32)) return -1;
      printf("packet size: %u/", v32);
      if (rmvb_unpack32(fp, &v32)) return -1;
      printf("%u; ", v32);
      if (rmvb_unpack32(fp, &v32)) return -1;
      printf("time: %u+", v32);
      if (rmvb_unpack32(fp, &v32)) return -1;
      if (rmvb_unpack32(fp, &v32)) return -1;
      printf("%u ms; ", v32);
      if (rmvb_unpack8(fp, &v8) || fread(pStr, 1, v8, fp) != v8) return -1;
      pStr[v8]=0;
      printf("%s; ", pStr);
      if (rmvb_unpack8(fp, &v8) || fread(pStr, 1, v8, fp) != v8) return -1;
      pStr[v8]=0;
      printf("%s; ", pStr);
	if (!strcmp(pStr, REALAUDIO_MIME_TYPE)) audio_stream = stream_nbr;
	if (!strcmp(pStr, REALVIDEO_MIME_TYPE)) video_stream = stream_nbr;

putchar('}');

  }
  putchar('\n');

fseek(fp, pos+size, SEEK_SET);

return 0; }

int parse_cont(FILE *fp, unsigned int size, unsigned short version) {

  unsigned int pos = ftell(fp) - 10;
  unsigned short len;
  char *pStr;
  int i;

printf(“\nCONT Detected @0x%x, size=%u, version = %d\n”, pos, size, version);

  putchar('\t');
  if (version == 0)
  {    
      putchar('{');
      putchar(0x20);
      for (i = 0; i < 4; i++)
      {
          if (rmvb_unpack16(fp, &len)) return -1;
          if (len)
          {
              pStr = (char *)malloc(len+1);
              if (pStr == NULL || fread(pStr, 1, len, fp) != len) return -1;
              pStr[len] = 0;
              printf("%s; ", pStr); 
              free(pStr);
          }
      }
      putchar('}');
  }
  putchar('\n');

fseek(fp, pos+size, SEEK_SET);

return 0; }

int parse_rmmd(FILE *fp, unsigned int size, unsigned short version) {

  unsigned int pos = ftell(fp) - 10;

printf(“\nRMMD Detected @0x%x, size=%u, version = %d\n”, pos, size, version);

fseek(fp, pos+size, SEEK_SET);

return 0; }

void parse_rmvb(FILE *fp) {

  unsigned int id;
  unsigned int size;
  unsigned short version;
  int val;

for (;;)

  {
      if (parse_basic(fp, &id, &size, &version) != 0)
          break;
      switch (id)
      {
          case MKTAG('.', 'R', 'M', 'F'):
              printf("Real Media File Detected: size=%u, version = %d\n", size, version);
              if (rmvb_unpack32(fp, &val)) ERROR;
              printf("File Version: %d\n", val);
              if (rmvb_unpack32(fp, &val)) ERROR;
              printf("number of headers: %d\n", val);
              break;
          case MKTAG('P', 'R', 'O', 'P'):
              if (parse_prop(fp, size, version)) ERROR;
              break;
          case MKTAG('M', 'D', 'P', 'R'):
              if (parse_mdpr(fp, size, version)) ERROR;
              break;
          case MKTAG('C', 'O', 'N', 'T'):
              if (parse_cont(fp, size, version)) ERROR;
              break;
          case MKTAG('D', 'A', 'T', 'A'):
              if (parse_data(fp, size, version)) ERROR;
              break;   
          case MKTAG('I', 'N', 'D', 'X'):
              if (parse_indx(fp, size, version)) ERROR;
              break;    
          case MKTAG('R', 'M', 'M', 'D'):
              if (parse_rmmd(fp, size, version)) ERROR;
              break;                    
          default:
              printf("undefined tag found\n");
              fseek(fp, size-2, SEEK_CUR);
              break;
      }
  }

}

int main(int argc, char** argv) {

  FILE *fp;
  long offset;

if (argc < 2)

  {
      printf("please input file name\n");
      return 0;
  }

fp = fopen(argv[1], “rb”);

  if (fp == NULL)
  {
      printf("error in openning file");
      return 0;
  }
  parse_rmvb(fp);
  fclose(fp);	

return 0; }

tech/multimedia/rmvb.1294817898.txt.gz · Last modified: 2014/11/10 08:35 (external edit)