Re: [PATCH] bin/cue-support

Fabian Franz <[email protected]>
Newsgroups gmane.comp.video.mplayer.g2.devel
Message-ID <[email protected]>
Am Freitag, 23. Mai 2003 16:49 schrieb Arpi:
> Hi,
>
> > > > It could also be backported to main as the g2-specific stuff is easy
> > > > to see
> > > >
> > > > :-)
> > > >
> > > > Btw. I love this new stream-architecture. It is sooo nice to use :-))
> > >
> > > and it could be ever more nice :)
> > >
> > > static int driver_fill(stream_t *s){
> > >   return cue_vcd_read((cue_priv_t*)s->priv,s->buffer);
> > > }
> > >
> > > i see no sence of such wrappers, the actual code could go into the
> > > actual function.
> >
> > I did that to be backward-compatible. (and you did it in your old
> > stream_vcd too. Heh, I'm taking exisitng code as my base :) )
>
> my stream_vcd.c was a quick hack, with strong 'TODO: cleanup!!!' in head
> and TODO.

ok :)

>
> see stream_SAMPLE.c for sample :)

already did, but it was sooo basic ;)

>
> > > also, if you rename cue_priv_t to struct stream_priv_s, you will
> > > get casting for free, ie you can access priv vars via
> > > stream->priv->something, without extra typecasting!
> >
> > Sorry, I don't understand. Example ?
>
> define priv struct the beginning of teh .c file:
>
> struct stream_priv_s {
>   struct cdrom_tocentry vcd_entry;
>   int xyz;
>   ...
> };

ah, got it now 

> > > also the buffer is still a static global, should be moved into the
> > > priv.
> >
> > where ? It uses the buffer provided by the stream_t like stream_vcd did
> > and does.
>
> static char vcd_buf[VCD_SECTOR_SIZE];
>
> dunno if it's used but it is there in your patch :)

yep, who the f* does define globals all over the place in a file ?

changed :)

New file attached, that should solve all "problems", you spoke of.

cu

Fabian
>
>
> A'rpi / Astral & ESP-team
>
> --
> Developer of MPlayer G2, the Movie Framework for all -
> http://www.MPlayerHQ.hu
>
> _______________________________________________
> MPlayer-G2-dev mailing list
> [email protected]
> http://mplayerhq.hu/mailman/listinfo/mplayer-g2-dev

_______________________________________________
MPlayer-G2-dev mailing list
[email protected]
http://mplayerhq.hu/mailman/listinfo/mplayer-g2-dev
stream_cue.c (text/x-csrc, 15.1 KB)
//=================== VideoCD BinCue ==========================

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

#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
#include <fcntl.h>

#include "../config.h"
#include "../mp_msg.h"
#include "../help_mp.h"

#include "stream.h"

//#include "cue_read.h"

#define byte    unsigned char
#define SIZERAW 2352
#define SIZEISO_MODE1 2048
#define SIZEISO_MODE2_RAW 2352
#define SIZEISO_MODE2_FORM1 2048
#define SIZEISO_MODE2_FORM2 2336
#define AUDIO 0
#define MODE1 1
#define MODE2 2
#define MODE1_2352 10
#define MODE2_2352 20
#define MODE1_2048 30
#define MODE2_2336 40
#define UNKNOWN -1

//static int fd_bin = 0;

typedef struct track
{
   unsigned short mode;
   unsigned short minute;
   unsigned short second;
   unsigned short frame;

   /* (min*60 + sec) * 75 + fps   */

   unsigned long start_sector;

   /* = the sizes in bytes off all tracks bevor this one */
   /* its needed if there are mode1 tracks befor the mpeg tracks */
   unsigned long start_offset;

   /*   unsigned char num[3]; */
} tTrack;

/* max 99 tracks on a cd */
//static tTrack tracks[100];

static struct cue_track_pos {
  int track;
  unsigned short mode;
  unsigned short minute;
  unsigned short second;
  unsigned short frame;
} cue_curr_pos;//cue_current_pos;

typedef struct stream_priv_s
{
  int fd_bin;
  /* max 99 tracks on a cd */
  tTrack tracks[100];
  
  struct cue_track_pos cue_current_pos;
  /* number of tracks on the cd */
  int nTracks;
  char vcd_buf[VCD_SECTOR_SIZE];
} cue_priv_t;

/* number of tracks on the cd */
//static int nTracks = 0;

/* presumes Line is preloaded with the "current" line of the file */
static int cue_getTrackinfo(char *Line, tTrack *track, FILE* fd_cue)
{
  char inum[3];
  char min;
  char sec;
  char fps;
  int already_set = 0;

  /* Get the 'mode' */
  if (strncmp(&Line[2], "TRACK ", 6)==0)
  {
/*    strncpy(track->num, &Line[8], 2); track->num[2] = '\0'; */

    track->mode = UNKNOWN;
    if(strncmp(&Line[11], "AUDIO", 5)==0) track->mode = AUDIO;
    if(strncmp(&Line[11], "MODE1/2352", 10)==0) track->mode = MODE1_2352;
    if(strncmp(&Line[11], "MODE1/2048", 10)==0) track->mode = MODE1_2048;
    if(strncmp(&Line[11], "MODE2/2352", 10)==0) track->mode = MODE2_2352;
    if(strncmp(&Line[11], "MODE2/2336", 10)==0) track->mode = MODE2_2336;
  }
  else return(1);

  /* Get the track indexes */
  while(1) {
    if(! fgets( Line, 256, fd_cue ) ) { break;}

    if (strncmp(&Line[2], "TRACK ", 6)==0)
    {
      /* next track starting */
      break;
    }

    /* Track 0 or 1, take the first an get fill the values*/
    if (strncmp(&Line[4], "INDEX ", 6)==0)
    {
      /* check stuff here so if the answer is false the else stuff below won't be executed */
      strncpy(inum, &Line[10], 2); inum[2] = '\0';
      if ((already_set == 0) &&
          ((strcmp(inum, "00")==0) || (strcmp(inum, "01")==0)))
      {
        already_set = 1;

        min = ((Line[13]-'0')<<4) | (Line[14]-'0');
        sec = ((Line[16]-'0')<<4) | (Line[17]-'0');
        fps = ((Line[19]-'0')<<4) | (Line[20]-'0');

        track->minute = (((min>>4)*10) + (min&0xf));
        track->second = (((sec>>4)*10) + (sec&0xf));
        track->frame  = (((fps>>4)*10) + (fps&0xf));
      }
    }
    else if (strncmp(&Line[4], "PREGAP ", 7)==0) { ; /* ignore */ }
    else if (strncmp(&Line[4], "FLAGS ", 6)==0)  { ; /* ignore */ }
    else mp_msg (MSGT_OPEN,MSGL_INFO,
                 "[bincue] Unexpected cuefile line: %s\n", Line);
  }
  return(0);
}



static int cue_find_bin (char *firstline, char* cue_filename, char* bincue_path) {
  int i,j;
  char s[256];
  char t[256];
  char bin_filename[256];
  int fd_bin;

  /* get the filename out of that */
  /*                      12345 6  */
  if (strncmp(firstline, "FILE \"",6)==0)
  {
    i = 0;
    j = 0;
    while ( firstline[6 + i] != '"')
    {
      bin_filename[j] = firstline[6 + i];

      /* if I found a path info, than delete all bevor it */
      switch (bin_filename[j])
      {
        case '\\':
          j = 0;
          break;

        case '/':
          j = 0;
          break;

        default:
          j++;
      }
      i++;
    }
    bin_filename[j+1] = '\0';

  }

  /* now try to open that file, without path */
  fd_bin = open (bin_filename, O_RDONLY);
  if (fd_bin == -1)
  {
    mp_msg(MSGT_OPEN,MSGL_STATUS, "[bincue] bin filename tested: %s\n",
           bin_filename);

    /* now try to find it with the path of the cue file */
    sprintf(s,"%s/%s",bincue_path, bin_filename);
    fd_bin = open (s, O_RDONLY);
    if (fd_bin == -1)
    {
      mp_msg(MSGT_OPEN,MSGL_STATUS,
             "[bincue] bin filename tested: %s\n", s);
      /* now I would say the whole filename is shit, build our own */
      strncpy(s, cue_filename, strlen(cue_filename) - 3 );
      s[strlen(cue_filename) - 3] = '\0';
      strcat(s, "bin");
      fd_bin = open (s, O_RDONLY);
      if (fd_bin == -1)
      {
        mp_msg(MSGT_OPEN,MSGL_STATUS,
               "[bincue] bin filename tested: %s\n", s);

        /* ok try it with path */
        sprintf(t,"%s/%s",bincue_path, s);
        fd_bin = open (t, O_RDONLY);
        if (fd_bin == -1)
        {
          mp_msg(MSGT_OPEN,MSGL_STATUS,
                 "[bincue] bin filename tested: %s\n",t);
          /* now I would say the whole filename is shit, build our own */
          strncpy(s, cue_filename, strlen(cue_filename) - 3 );
          s[strlen(cue_filename) - 3] = '\0';
          strcat(s, "img");
          fd_bin = open (s, O_RDONLY);
          if (fd_bin == -1)
          {
            mp_msg(MSGT_OPEN,MSGL_STATUS,
                   "[bincue] bin filename tested: %s \n", s);
            /* ok try it with path */
            sprintf(t,"%s/%s",bincue_path, s);
            fd_bin = open (t, O_RDONLY);
            if (fd_bin == -1)
            {
              mp_msg(MSGT_OPEN,MSGL_STATUS,
                     "[bincue] bin filename tested: %s\n", s);

              /* I'll give up */
              mp_msg(MSGT_OPEN,MSGL_ERR,
                     "[bincue] couldn't find the bin file - giving up\n");
              return -1;
            }
          }
        } else strcpy(bin_filename, t);

      } else strcpy(bin_filename, s);

    } else strcpy(bin_filename, s);

  }

  mp_msg(MSGT_OPEN,MSGL_INFO,
         "[bincue] using bin file %s\n", bin_filename);
  return fd_bin;
}

static inline int cue_msf_2_sector(int minute, int second, int frame) {
 return frame + (second + minute * 60 ) * 75;
}

static inline int cue_get_msf(cue_priv_t* cue) {
  return cue_msf_2_sector (cue->cue_current_pos.minute,
                           cue->cue_current_pos.second,
                           cue->cue_current_pos.frame);
}

static inline void cue_set_msf(cue_priv_t* cue, unsigned int sect){
  cue->cue_current_pos.frame=sect%75;
  sect=sect/75;
  cue->cue_current_pos.second=sect%60;
  sect=sect/60;
  cue->cue_current_pos.minute=sect;
}

static inline int cue_mode_2_sector_size(int mode)
{
  switch (mode)
  {
    case AUDIO:      return AUDIO;
    case MODE1_2352: return SIZERAW;
    case MODE1_2048: return SIZEISO_MODE1;
    case MODE2_2352: return SIZEISO_MODE2_RAW;
    case MODE2_2336: return SIZEISO_MODE2_FORM2;

    default:
      mp_msg(MSGT_OPEN,MSGL_FATAL,
             "[bincue] unknown mode for binfile. should not happen. aborting\n");
      abort();
  }

}


static cue_priv_t* cue_read_cue (char *in_cue_filename)
{
  struct stat filestat;
  char sLine[256];
  char cue_filename[256];
  char bincue_path[256];
  unsigned int sect;
  char *s,*t;
  int i;
  FILE* fd_cue;
  cue_priv_t cue; 
  cue_priv_t* cue_p=NULL; 

  /* we have no tracks at the beginning */
  cue.nTracks = 0;

  cue.fd_bin = 0;

  /* split the filename into a path and filename part */
  s = strdup(in_cue_filename);
  t = strrchr(s, '/');
  if (t == (char *)NULL)
     t = ".";
  else {
     *t = '\0';
     t = s;
     if (*t == '\0')
       strcpy(t, "/");
  }
  printf ("dirname: %s\n", t);
  strcpy(bincue_path,t);


  /* no path at all? */
  if (strcmp(bincue_path, ".") == 0) {
    //printf ("bincue_path: %s\n", bincue_path); //FF: unneccessary printf - should imho be removed in main too
    strcpy(cue_filename,in_cue_filename);
  } else {
    strcpy(cue_filename,in_cue_filename + strlen(bincue_path) + 1);
  }



  /* open the cue file */
  fd_cue = fopen (in_cue_filename, "r");
  if (fd_cue == NULL)
  {
    mp_msg(MSGT_OPEN,MSGL_ERR,
           "[bincue] cannot open %s\n", in_cue_filename);
    return 0;
  }

  /* read the first line and hand it to find_bin, which will
     test more than one possible name of the file */

  if(! fgets( sLine, 256, fd_cue ) )
  {
    mp_msg(MSGT_OPEN,MSGL_ERR,
           "[bincue] error reading from  %s\n", in_cue_filename);
    fclose (fd_cue);
    return 0;
  }
  cue.fd_bin=cue_find_bin(sLine, cue_filename, bincue_path);
  if (cue.fd_bin < 0) {
    fclose (fd_cue);
    return 0;
  }


  /* now build the track list */
  /* red the next line and call our track finder */
  if(! fgets( sLine, 256, fd_cue ) )
  {
    mp_msg(MSGT_OPEN,MSGL_ERR,
           "[bincue] error reading from  %s\n", in_cue_filename);
    fclose (fd_cue);
    return 0;
  }

  while(!feof(fd_cue))
  {
    if (cue_getTrackinfo(sLine, &cue.tracks[cue.nTracks++], fd_cue) != 0)
    {
      mp_msg(MSGT_OPEN,MSGL_ERR,
             "[bincue] error reading from  %s\n", in_cue_filename);
      fclose (fd_cue);
      return 0;
    }
  }

  /* make a fake track with stands for the Lead out */
  if (fstat (cue.fd_bin, &filestat) == -1) {
    mp_msg(MSGT_OPEN,MSGL_ERR,
           "[bincue] error getting size of bin file\n");
    fclose (fd_cue);
    return 0;
  }

  sect = filestat.st_size / 2352;

  cue.tracks[cue.nTracks].frame = sect%75;
  sect=sect/75;
  cue.tracks[cue.nTracks].second = sect%60;
  sect=sect/60;
  cue.tracks[cue.nTracks].minute = sect;


  /* lets calculate the start sectors and offsets */
  for(i = 0; i <= cue.nTracks; i++)
  {
    cue.tracks[i].start_sector = cue_msf_2_sector(cue.tracks[i].minute,
                                              cue.tracks[cue.nTracks].second,
                                              cue.tracks[cue.nTracks].frame);

    /* if we're the first track we don't need to offset of the one befor */
    if (i == 0)
    {
      /* was always 0 on my svcds, but who knows */
      cue.tracks[0].start_offset = cue.tracks[0].start_sector *
        cue_mode_2_sector_size(cue.tracks[0].mode);
    } else
    {
      cue.tracks[i].start_offset = cue.tracks[i-1].start_offset +
        (cue.tracks[i].start_sector - cue.tracks[i-1].start_sector) *
        cue_mode_2_sector_size(cue.tracks[i-1].mode);
    }
  }

  fclose (fd_cue);

  cue_p = malloc(sizeof(cue_priv_t));
  memcpy(cue_p, &cue, sizeof(cue_priv_t));

  return cue_p;
}




static int cue_read_toc_entry(cue_priv_t* cue) {

  int track = cue->cue_current_pos.track - 1;

  /* check if its a valid track, if not return -1 */
  if (track >= cue->nTracks)
    return -1;


  switch (cue->tracks[track].mode)
  {
    case AUDIO:
      cue->cue_current_pos.mode = AUDIO;
      break;
    case MODE1_2352:
      cue->cue_current_pos.mode = MODE1;
      break;
    case MODE1_2048:
      cue->cue_current_pos.mode = MODE1;
      break;
    default: /* MODE2_2352 and MODE2_2336 */
      cue->cue_current_pos.mode = MODE2;
  }
  cue->cue_current_pos.minute = cue->tracks[track].minute;
  cue->cue_current_pos.second = cue->tracks[track].second;
  cue->cue_current_pos.frame = cue->tracks[track].frame;

  return 0;
}

static int cue_read_raw(cue_priv_t* cue,char *buf) {
  int position;
  int track = cue->cue_current_pos.track - 1;

  /* get the mode of the bin file part and calc the positon */
  position = cue->tracks[track].start_offset +
             (cue_msf_2_sector(cue->cue_current_pos.minute,
                               cue->cue_current_pos.second,
                               cue->cue_current_pos.frame) -
              cue->tracks[track].start_sector)
             * cue_mode_2_sector_size(cue->tracks[track].mode);

  /* check if the track is at its end*/
  if (position >= cue->tracks[track+1].start_offset)
    return -1;

  if (lseek (cue->fd_bin, position, SEEK_SET) == -1) {
    mp_msg(MSGT_OPEN,MSGL_ERR,
           "[bincue] unexpected end of bin file\n");
    return -1;
  }

  if (!read (cue->fd_bin, buf, VCD_SECTOR_SIZE))
    return -1;
  else
    return VCD_SECTOR_DATA;
}



static int cue_vcd_seek_to_track (cue_priv_t* cue,int track){
  cue->cue_current_pos.track  = track;

  if (cue_read_toc_entry (cue))
    return -1;

  return VCD_SECTOR_DATA * cue_get_msf(cue);
}

static int cue_vcd_get_track_end (cue_priv_t* cue,int track){
  cue->cue_current_pos.frame = cue->tracks[track].frame;
  cue->cue_current_pos.second = cue->tracks[track].second;
  cue->cue_current_pos.minute = cue->tracks[track].minute;

  return VCD_SECTOR_DATA * cue_get_msf(cue);
}

static void cue_vcd_read_toc(cue_priv_t* cue){
  int i;
  for (i = 0; i < cue->nTracks; ++i) {

    mp_msg(MSGT_OPEN,MSGL_INFO,
           "track %02d:  format=%d  %02d:%02d:%02d\n",
           i,
           cue->tracks[i].mode,
           cue->tracks[i].minute,
           cue->tracks[i].second,
           cue->tracks[i].frame
           );
  }
}


//static int cue_vcd_read(cue_priv_t* cue,char *mem){
static int driver_fill(stream_t* stream){

  cue_priv_t* cue=stream->priv;
  char *mem=stream->buffer;

  if (cue_read_raw(cue,cue->vcd_buf)==-1) return 0; // EOF?

  memcpy(mem,&cue->vcd_buf[VCD_SECTOR_OFFS],VCD_SECTOR_DATA);

  cue->cue_current_pos.frame++;
  if (cue->cue_current_pos.frame==75){
    cue->cue_current_pos.frame=0;
    cue->cue_current_pos.second++;
    if (cue->cue_current_pos.second==60){
      cue->cue_current_pos.second=0;
      cue->cue_current_pos.minute++;
    }
  }

  return VCD_SECTOR_DATA;
}

// Driver dependent part
//

static int driver_open(stream_t *stream) {
  int vcd_track;
  int vcd_last_track;
  int ret,ret2,f;
  cue_priv_t* cue;
  
  url_parse_range(stream->url, &vcd_track, &vcd_last_track, &cdrom_device);
  if(!vcd_track) vcd_track=1;

  cue=cue_read_cue (stream->url->url+6); // cue://
  if(cue==NULL){ 
    return 0;
  }

  cue_vcd_read_toc(cue);
  f=cue->fd_bin;
  
  ret2=cue_vcd_get_track_end(cue,vcd_last_track ? vcd_last_track : vcd_track); // FF: So Right ?
  if(ret2<0){
    mp_msg(MSGT_OPEN,MSGL_ERR,MSGTR_ErrTrackSelect " (get)\n");
    close(f);
    free(cue);
    return 0;
  }
  ret=cue_vcd_seek_to_track(cue,vcd_track);
  if(ret<0){
    mp_msg(MSGT_OPEN,MSGL_ERR,MSGTR_ErrTrackSelect " (seek)\n");
    close(f);
    free(cue);
    return 0;
  }
  mp_msg(MSGT_OPEN,MSGL_V,"VCD start byte position: 0x%X  end: 0x%X\n",ret,ret2);

  stream->fd = f;
  stream->buf_size = VCD_SECTOR_DATA;
  stream->start_pos=ret;
  stream->end_pos=ret2;
  stream->priv = cue;

  return 1;
}

/*static int driver_fill(stream_t *s){
  return cue_vcd_read(s->priv,s->buffer);
}*/

static int driver_seek(stream_t *s,off_t pos) {
  s->pos=(pos/VCD_SECTOR_DATA)*VCD_SECTOR_DATA;
  cue_set_msf(s->priv,s->pos/VCD_SECTOR_DATA);
  return 1;
}

static int driver_free(stream_t *stream) {
  if (stream->priv)
    free(stream->priv);
  return 1;
}

stream_driver_t stream_driver_cue = {
    "cue",
    "VideoCD/SVCD/XCD driver for cue/bin-files",
    "ported from main + cleanup by Fabian Franz",
    driver_open,
    NULL, //reset,
    driver_fill,
    driver_seek,
    driver_free
};
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.