⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 nrg.c

📁 linux下的MPEG1
💻 C
📖 第 1 页 / 共 3 页
字号:
/*    $Id: nrg.c,v 1.3 2005/05/07 22:07:27 rockyb Exp $    Copyright (C) 2003, 2004 Rocky Bernstein <rocky@panix.com>    Copyright (C) 2001, 2003 Herbert Valerio Riedel <hvr@gnu.org>    This program is free software; you can redistribute it and/or modify    it under the terms of the GNU General Public License as published by    the Free Software Foundation; either version 2 of the License, or    (at your option) any later version.    This program is distributed in the hope that it will be useful,    but WITHOUT ANY WARRANTY; without even the implied warranty of    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the    GNU General Public License for more details.    You should have received a copy of the GNU General Public License    along with this program; if not, write to the Free Software    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA*//*! This code implements low-level access functions for the Nero native   CD-image format residing inside a disk file (*.nrg).*/#include "image.h"#ifdef HAVE_STDIO_H#include <stdio.h>#endif#ifdef HAVE_STDLIB_H#include <stdlib.h>#endif#ifdef HAVE_STRING_H#include <string.h>#endif#ifdef HAVE_GLOB_H#include <glob.h>#endif#include <cdio/bytesex.h>#include <cdio/ds.h>#include <cdio/logging.h>#include <cdio/util.h>#include <cdio/version.h>#include "cdio_assert.h"#include "_cdio_stdio.h"#include "nrg.h"static const char _rcsid[] = "$Id: nrg.c,v 1.3 2005/05/07 22:07:27 rockyb Exp $";/* reader */#define DEFAULT_CDIO_DEVICE "image.nrg"/*    Link element of track structure as a linked list.   Possibly redundant with above track_info_t */typedef struct {  uint32_t start_lsn;  uint32_t sec_count;     /* Number of sectors in track. Does not 			     include pregap before next entry. */  uint64_t img_offset;    /* Bytes offset from beginning of disk image file.*/  uint32_t blocksize;     /* Number of bytes in a block */  int      flags;         /* don't copy, 4 channel, pre-emphasis */} _mapping_t;typedef struct {  /* Things common to all drivers like this.      This must be first. */  generic_img_private_t gen;   internal_position_t pos;   /* This is common to all image drivers... */  char         *psz_cue_name;  char         *psz_mcn;         /* Media Catalog Number (5.22.3) */  track_info_t  tocent[CDIO_CD_MAX_TRACKS+1]; /* entry info for each track 					         add 1 for leadout. */  discmode_t    disc_mode;  /* Nero Specific stuff. Note: for the image_free to work, this *must*     be last. */  bool          is_dao;          /* True if some of disk at once. False				    if some sort of track at once. */  uint32_t      mtyp;            /* Value of MTYP (media type?) tag */  uint8_t       dtyp;            /* Value of DAOX media type tag */  /* This is a hack because I don't really understnad NERO better. */  bool            is_cues;  CdioList     *mapping;         /* List of track information */  uint32_t      size;} _img_private_t;static bool     parse_nrg (_img_private_t *env, const char *psz_cue_name);static uint32_t _stat_size_nrg (void *user_data);#include "image_common.h"/* Updates internal track TOC, so we can later    simulate ioctl(CDROMREADTOCENTRY). */static void_register_mapping (_img_private_t *env, lsn_t start_lsn, uint32_t sec_count,		   uint64_t img_offset, uint32_t blocksize,		   track_format_t track_format, bool track_green,		   int flags){  const int track_num=env->gen.i_tracks;  track_info_t  *this_track=&(env->tocent[env->gen.i_tracks]);  _mapping_t *_map = _cdio_malloc (sizeof (_mapping_t));  _map->start_lsn  = start_lsn;  _map->sec_count  = sec_count;  _map->img_offset = img_offset;  _map->blocksize  = blocksize;  _map->flags      = flags;  if (!env->mapping) env->mapping = _cdio_list_new ();  _cdio_list_append (env->mapping, _map);  env->size = MAX (env->size, (start_lsn + sec_count));  /* Update *this_track and track_num. These structures are     in a sense redundant witht the obj->mapping list. Perhaps one     or the other can be eliminated.   */  cdio_lba_to_msf (cdio_lsn_to_lba(start_lsn), &(this_track->start_msf));  this_track->start_lba = cdio_msf_to_lba(&this_track->start_msf);  this_track->track_num = track_num+1;  this_track->blocksize = blocksize;  if (env->is_cues)     this_track->datastart = img_offset;  else     this_track->datastart = 0;  if (track_green)     this_track->datastart += CDIO_CD_SUBHEADER_SIZE;        this_track->sec_count = sec_count;  this_track->track_format= track_format;  this_track->track_green = track_green;  switch (this_track->track_format) {  case TRACK_FORMAT_AUDIO:    this_track->blocksize   = CDIO_CD_FRAMESIZE_RAW;    this_track->datasize    = CDIO_CD_FRAMESIZE_RAW;    /*this_track->datastart   = 0;*/    this_track->endsize     = 0;    break;  case TRACK_FORMAT_CDI:    this_track->datasize=CDIO_CD_FRAMESIZE;    break;  case TRACK_FORMAT_XA:    if (track_green) {      this_track->blocksize = CDIO_CD_FRAMESIZE;      /*this_track->datastart = CDIO_CD_SYNC_SIZE + CDIO_CD_HEADER_SIZE;*/      this_track->datasize  = M2RAW_SECTOR_SIZE;      this_track->endsize   = 0;    } else {      /*this_track->datastart = CDIO_CD_SYNC_SIZE + CDIO_CD_HEADER_SIZE +	CDIO_CD_SUBHEADER_SIZE;*/      this_track->datasize  = CDIO_CD_FRAMESIZE;      this_track->endsize   = CDIO_CD_SYNC_SIZE + CDIO_CD_ECC_SIZE;    }    break;  case TRACK_FORMAT_DATA:    if (track_green) {      /*this_track->datastart = CDIO_CD_SYNC_SIZE + CDIO_CD_HEADER_SIZE;*/      this_track->datasize  = CDIO_CD_FRAMESIZE;      this_track->endsize   = CDIO_CD_EDC_SIZE + CDIO_CD_M1F1_ZERO_SIZE 	  + CDIO_CD_ECC_SIZE;    } else {      /* Is the below correct? */      /*this_track->datastart = 0;*/      this_track->datasize  = CDIO_CD_FRAMESIZE;      this_track->endsize   = 0;      }    break;  default:    /*this_track->datasize=CDIO_CD_FRAMESIZE_RAW;*/    cdio_warn ("track %d has unknown format %d",	       env->gen.i_tracks, this_track->track_format);  }    env->gen.i_tracks++;  cdio_debug ("start lsn: %lu sector count: %0lu -> %8ld (%08lx)", 	      (long unsigned int) start_lsn, 	      (long unsigned int) sec_count, 	      (long unsigned int) img_offset,	      (long unsigned int) img_offset);}/*    Disk and track information for a Nero file are located at the end   of the file. This routine extracts that information.   FIXME: right now psz_nrg_name is not used. It will be in the future. */static boolparse_nrg (_img_private_t *env, const char *psz_nrg_name){  long unsigned int footer_start;  long unsigned int size;  char *footer_buf = NULL;  cdio_log_level_t log_level = (NULL == env) ? CDIO_LOG_INFO : CDIO_LOG_WARN;  size = cdio_stream_stat (env->gen.data_source);  if (-1 == size) return false;  {    _footer_t buf;    cdio_assert (sizeof (buf) == 12);     cdio_stream_seek (env->gen.data_source, size - sizeof (buf), SEEK_SET);    cdio_stream_read (env->gen.data_source, (void *) &buf, sizeof (buf), 1);        if (buf.v50.ID == UINT32_TO_BE (NERO_ID)) {      cdio_info ("detected Nero version 5.0 (32-bit offsets) NRG magic");      footer_start = uint32_to_be (buf.v50.footer_ofs);     } else if (buf.v55.ID == UINT32_TO_BE (NER5_ID)) {      cdio_info ("detected Nero version 5.5.x (64-bit offsets) NRG magic");      footer_start = uint64_from_be (buf.v55.footer_ofs);    } else {      cdio_log (log_level, "Image not recognized as either version 5.0 or "		"version 5.5.x-6.x type NRG");      return false;    }    cdio_debug (".NRG footer start = %ld, length = %ld", 	       (long) footer_start, (long) (size - footer_start));    cdio_assert (IN ((size - footer_start), 0, 4096));    footer_buf = _cdio_malloc (size - footer_start);    cdio_stream_seek (env->gen.data_source, footer_start, SEEK_SET);    cdio_stream_read (env->gen.data_source, footer_buf, 		      size - footer_start, 1);  }  {    int pos = 0;    while (pos < size - footer_start) {      _chunk_t *chunk = (void *) (footer_buf + pos);      uint32_t opcode = UINT32_FROM_BE (chunk->id);            bool break_out = false;            switch (opcode) {      case CUES_ID: /* "CUES" Seems to have sector size 2336 and 150 sector		       pregap seems to be included at beginning of image.		       */      case CUEX_ID: /* "CUEX" */ 	{	  unsigned entries = UINT32_FROM_BE (chunk->len);	  _cuex_array_t *_entries = (void *) chunk->data;	  	  cdio_assert (env->mapping == NULL);	  	  cdio_assert ( sizeof (_cuex_array_t) == 8 );	  cdio_assert ( UINT32_FROM_BE (chunk->len) % sizeof(_cuex_array_t) 			== 0 );	  	  entries /= sizeof (_cuex_array_t);	  	  if (CUES_ID == opcode) {	    lsn_t lsn = UINT32_FROM_BE (_entries[0].lsn);	    int idx;	    	    cdio_info ("CUES type image detected" );	    /* CUES LSN has 150 pregap include at beginning? -/	       cdio_assert (lsn == 0?);	    */	    	    env->is_cues       = true; /* HACK alert. */	    env->gen.i_tracks      = 0;	    env->gen.i_first_track = 1;	    for (idx = 1; idx < entries-1; idx += 2) {	      lsn_t sec_count;	      int addrtype = _entries[idx].addr_ctrl / 16;	      int control  = _entries[idx].addr_ctrl % 16;	      int flags = 0;	      if ( 1 == control )  		     flags &= ~CDIO_TRACK_FLAG_COPY_PERMITTED;	      cdio_assert (_entries[idx].track == _entries[idx + 1].track);	      	      /* lsn and sec_count*2 aren't correct, but it comes closer on the		 single example I have: svcdgs.nrg		 We are picking up the wrong fields and/or not interpreting		 them correctly.	      */	      switch (addrtype) {	      case 0:		lsn = UINT32_FROM_BE (_entries[idx].lsn);		break;	      case 1: 		{#if 0		  msf_t msf = (msf_t) _entries[idx].lsn;		  lsn = cdio_msf_to_lsn(&msf);#else		  lsn = CDIO_INVALID_LSN;#endif		  		  cdio_warn ("untested (i.e. probably wrong) CUE MSF code");		  break;		}	      default:		lsn = CDIO_INVALID_LSN;		cdio_warn("unknown addrtype %d", addrtype);	      }	      	      sec_count = UINT32_FROM_BE (_entries[idx + 1].lsn);	      	      _register_mapping (env, lsn, sec_count*2, 				 (lsn+CDIO_PREGAP_SECTORS) * M2RAW_SECTOR_SIZE,				 M2RAW_SECTOR_SIZE, TRACK_FORMAT_XA, true,				 flags);	    }	  } else {	    lsn_t lsn = UINT32_FROM_BE (_entries[0].lsn);	    int idx;	    	    cdio_info ("CUEX type image detected");	    /* LSN must start at -150 (LBA 0)? */	    cdio_assert (lsn == -150); 	    	    for (idx = 2; idx < entries; idx += 2) {	      lsn_t sec_count;	      int addrtype = _entries[idx].addr_ctrl >> 4;	      int control  = _entries[idx].addr_ctrl & 0xf;	      int flags = 0;	      if ( 1 == control )  		     flags &= ~CDIO_TRACK_FLAG_COPY_PERMITTED;	      /* extractnrg.pl has addrtype for LBA's 0, and		 for MSF 1. ???		 FIXME: Should decode as appropriate for addrtype.	       */	      cdio_assert ( addrtype == 0 || addrtype == 1 );	      cdio_assert (_entries[idx].track != _entries[idx + 1].track);	      	      lsn       = UINT32_FROM_BE (_entries[idx].lsn);	      sec_count = UINT32_FROM_BE (_entries[idx + 1].lsn);	      	      _register_mapping (env, lsn, sec_count - lsn, 				 (lsn + CDIO_PREGAP_SECTORS)*M2RAW_SECTOR_SIZE,				 M2RAW_SECTOR_SIZE, TRACK_FORMAT_XA, true,				 flags);	    }	  }	  break;	}	      case DAOX_ID: /* "DAOX" */       case DAOI_ID: /* "DAOI" */	{	  track_format_t track_format;	  int form2;	  /* We include an extra 0 byte so these can be used as C strings.*/	  env->psz_mcn    = _cdio_malloc (CDIO_MCN_SIZE+1);	  if (DAOX_ID == opcode) {	    _daox_array_t *_entries = (void *) chunk->data;	    form2         = _entries->_unknown[1];	    env->dtyp   = _entries->_unknown[19];	    memcpy(env->psz_mcn, &(_entries->psz_mcn), CDIO_MCN_SIZE);	    env->psz_mcn[CDIO_MCN_SIZE] = '\0';	  } else {	    _daoi_array_t *_entries = (void *) chunk->data;	    form2         = _entries->_unknown[1];	    env->dtyp   = _entries->_unknown[19];	    memcpy(env->psz_mcn, &(_entries->psz_mcn), CDIO_MCN_SIZE);	    env->psz_mcn[CDIO_MCN_SIZE] = '\0';	  }	  env->is_dao = true;	  cdio_debug ("DAO%c tag detected, track format %d, form %x\n", 		      opcode==DAOX_ID ? 'X': 'I', env->dtyp, form2);	  switch (env->dtyp) {	  case 0:	    /* Mode 1 */	    track_format   = TRACK_FORMAT_DATA;	    env->disc_mode = CDIO_DISC_MODE_CD_DATA;	    break;	  case 2:	    /* Mode 2 form 1 */	    form2          = 0;	    track_format   = TRACK_FORMAT_XA;	    env->disc_mode = CDIO_DISC_MODE_CD_XA;	    break;	  case 3:	    /* Mode 2 */	    track_format   = TRACK_FORMAT_XA;	    env->disc_mode = CDIO_DISC_MODE_CD_XA; /* ?? */	    break;	  case 0x6:	    /* Mode2 form mix */	    track_format   = TRACK_FORMAT_XA;	    env->disc_mode = CDIO_DISC_MODE_CD_MIXED;	    break;	  case 0x20: /* ??? Mode2 form 2, Mode2 raw?? */	    track_format   = TRACK_FORMAT_XA;	    env->disc_mode = CDIO_DISC_MODE_CD_XA; /* ??. */	    break;	  case 0x7:	    track_format   = TRACK_FORMAT_AUDIO;	    env->disc_mode = CDIO_DISC_MODE_CD_DA;	    break;	  default:	    cdio_log (log_level, "Unknown track format %x\n", 

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -