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

📄 dvd_udf.c

📁 python的多媒体包,可以实现很多漂亮的功能哦
💻 C
📖 第 1 页 / 共 2 页
字号:
}

/**
 * Dir: Location of directory to scan
 * FileName: Name of file to look for
 * FileICB: Location of ICB of the found file
 * return 1 on success, 0 on error;
 */
static int UDFScanDir( dvd_reader_t *device, struct AD Dir, char *FileName,
											struct Partition *partition, struct AD *FileICB,
											int cache_file_info) 
{
	char filename[ MAX_UDF_FILE_NAME_LEN ];
	uint8_t directory[ 2 * DVD_VIDEO_LB_LEN ];
	uint32_t lbnum;
	uint16_t TagID;
	uint8_t filechar;
	unsigned int p;
	uint8_t *cached_dir = NULL;
#if UDF_CACHE
	uint32_t dir_lba;
	struct AD tmpICB;
#endif
	int found = 0;
	int in_cache = 0;
	
	/* Scan dir for ICB of file */
	lbnum = partition->Start + Dir.Location;

#if UDF_CACHE
	if(DVDUDFCacheLevel(device, -1) > 0) {
		/* caching */
		
		if(!GetUDFCache(device, LBUDFCache, lbnum, &cached_dir)) {
			dir_lba = (Dir.Length + DVD_VIDEO_LB_LEN) / DVD_VIDEO_LB_LEN;
			if((cached_dir = malloc(dir_lba * DVD_VIDEO_LB_LEN)) == NULL) {
				return 0;
			}
			if( DVDReadLBUDF( device, lbnum, dir_lba, cached_dir, 0) <= 0 ) {
				free(cached_dir);
				cached_dir = NULL;
			}
			/*
			if(cached_dir) {
			fprintf(stderr, "malloc dir: %d\n",
			dir_lba * DVD_VIDEO_LB_LEN);
			}
			*/
			SetUDFCache(device, LBUDFCache, lbnum, &cached_dir);
		} else {
			in_cache = 1;
		}
		
		if(cached_dir == NULL) {
			return 0;
		}
		
		p = 0;
		
		while( p < Dir.Length ) {
			UDFDescriptor( &cached_dir[ p ], &TagID );
			if( TagID == 257 ) {
				p += UDFFileIdentifier( &cached_dir[ p ], &filechar,
					filename, &tmpICB );
				if(cache_file_info && !in_cache) {
					uint8_t tmpFiletype;
					struct AD tmpFile;
					
					if( !strcasecmp( FileName, filename ) ) {
						*FileICB = tmpICB;
						found = 1;
						
					}
					UDFMapICB(device, tmpICB, &tmpFiletype,
						partition, &tmpFile);
				} else {
					if( !strcasecmp( FileName, filename ) ) {
						*FileICB = tmpICB;
						return 1;
					}
				}
			} else {
				if(cache_file_info && (!in_cache) && found) {
					return 1;
				}
				return 0;
			}
		}
		if(cache_file_info && (!in_cache) && found) {
			return 1;
		}
		return 0;
	}
#endif

	if( DVDReadLBUDF( device, lbnum, 2, directory, 0 ) <= 0 ) {
		return 0;
	}
	
	p = 0;
	while( p < Dir.Length ) {
		if( p > DVD_VIDEO_LB_LEN ) {
			++lbnum;
			p -= DVD_VIDEO_LB_LEN;
			Dir.Length -= DVD_VIDEO_LB_LEN;
			if( DVDReadLBUDF( device, lbnum, 2, directory, 0 ) <= 0 ) {
				return 0;
			}
		}
		UDFDescriptor( &directory[ p ], &TagID );
		if( TagID == 257 ) {
			p += UDFFileIdentifier( &directory[ p ], &filechar,
				filename, FileICB );
			if( !strcasecmp( FileName, filename ) ) {
				return 1;
			}
		} else {
			return 0;
		}
	}
	
	return 0;
}


static int UDFGetAVDP( dvd_reader_t *device,
		       struct avdp_t *avdp)
{
  uint8_t Anchor[ DVD_VIDEO_LB_LEN ];
  uint32_t lbnum, MVDS_location, MVDS_length;
  uint16_t TagID;
  uint32_t lastsector;
  int terminate;
  struct avdp_t; 
  
#if UDF_CACHE
  if(GetUDFCache(device, AVDPCache, 0, avdp)) {
    return 1;
  }
#endif

  /* Find Anchor */
  lastsector = 0;
  lbnum = 256;   /* Try #1, prime anchor */
  terminate = 0;
  
  for(;;) {
    if( DVDReadLBUDF( device, lbnum, 1, Anchor, 0 ) > 0 ) {
      UDFDescriptor( Anchor, &TagID );
    } else {
      TagID = 0;
    }
    if (TagID != 2) {
      /* Not an anchor */
      if( terminate ) return 0; /* Final try failed */
      
      if( lastsector ) {
	
	/* We already found the last sector.  Try #3, alternative
	 * backup anchor.  If that fails, don't try again.
	 */
	lbnum = lastsector;
	terminate = 1;
      } else {
	/* TODO: Find last sector of the disc (this is optional). */
	if( lastsector ) {
	  /* Try #2, backup anchor */
	  lbnum = lastsector - 256;
	} else {
	  /* Unable to find last sector */
	  return 0;
	}
      }
    } else {
      /* It's an anchor! We can leave */
      break;
    }
  }
  /* Main volume descriptor */
  UDFExtentAD( &Anchor[ 16 ], &MVDS_length, &MVDS_location );
  avdp->mvds.location = MVDS_location;
  avdp->mvds.length = MVDS_length;
  
  /* Backup volume descriptor */
  UDFExtentAD( &Anchor[ 24 ], &MVDS_length, &MVDS_location );
  avdp->rvds.location = MVDS_location;
  avdp->rvds.length = MVDS_length;
  
#if UDF_CACHE
  SetUDFCache(device, AVDPCache, 0, avdp);
#endif

  return 1;
}

/**
 * Looks for partition on the disc.  Returns 1 if partition found, 0 on error.
 *   partnum: Number of the partition, starting at 0.
 *   part: structure to fill with the partition information
 */
static int UDFFindPartition( dvd_reader_t *device, int partnum,
			     struct Partition *part ) 
{
    uint8_t LogBlock[ DVD_VIDEO_LB_LEN ];
    uint32_t lbnum, MVDS_location, MVDS_length;
    uint16_t TagID;
    int i, volvalid;
    struct avdp_t avdp;

    
    if(!UDFGetAVDP(device, &avdp)) {
      return 0;
    }

    /* Main volume descriptor */
    MVDS_location = avdp.mvds.location;
    MVDS_length = avdp.mvds.length;

    part->valid = 0;
    volvalid = 0;
    part->VolumeDesc[ 0 ] = '\0';
    i = 1;
    do {
        /* Find Volume Descriptor */
        lbnum = MVDS_location;
        do {

            if( DVDReadLBUDF( device, lbnum++, 1, LogBlock, 0 ) <= 0 ) {
                TagID = 0;
            } else {
                UDFDescriptor( LogBlock, &TagID );
            }

            if( ( TagID == 5 ) && ( !part->valid ) ) {
                /* Partition Descriptor */
                UDFPartition( LogBlock, &part->Flags, &part->Number,
                              part->Contents, &part->Start, &part->Length );
                part->valid = ( partnum == part->Number );
            } else if( ( TagID == 6 ) && ( !volvalid ) ) {
                /* Logical Volume Descriptor */
                if( UDFLogVolume( LogBlock, part->VolumeDesc ) ) {  
                    /* TODO: sector size wrong! */
                } else {
                    volvalid = 1;
                }
            }

        } while( ( lbnum <= MVDS_location + ( MVDS_length - 1 )
                 / DVD_VIDEO_LB_LEN ) && ( TagID != 8 )
                 && ( ( !part->valid ) || ( !volvalid ) ) );

        if( ( !part->valid) || ( !volvalid ) ) {
	  /* Backup volume descriptor */
	  MVDS_location = avdp.mvds.location;
	  MVDS_length = avdp.mvds.length;
        }
    } while( i-- && ( ( !part->valid ) || ( !volvalid ) ) );

    /* We only care for the partition, not the volume */
    return part->valid;
}

uint32_t UDFFindFile( dvd_reader_t *device, char *filename,
		      uint32_t *filesize )
{
    uint8_t LogBlock[ DVD_VIDEO_LB_LEN ];
    uint32_t lbnum;
    uint16_t TagID;
    struct Partition partition;
    struct AD RootICB, File, ICB;
    char tokenline[ MAX_UDF_FILE_NAME_LEN ];
    char *token;
    uint8_t filetype;

    *filesize = 0;
    tokenline[0] = '\0';
    strcat( tokenline, filename );

#if UDF_CACHE
    if(!(GetUDFCache(device, PartitionCache, 0, &partition) &&
        GetUDFCache(device, RootICBCache, 0, &RootICB))) {
#endif
      /* Find partition, 0 is the standard location for DVD Video.*/
      if( !UDFFindPartition( device, 0, &partition ) ) return 0;
#if UDF_CACHE
      SetUDFCache(device, PartitionCache, 0, &partition);
#endif      

      /* Find root dir ICB */
      lbnum = partition.Start;
      do {
        if( DVDReadLBUDF( device, lbnum++, 1, LogBlock, 0 ) <= 0 ) {
            TagID = 0;
        } else {
            UDFDescriptor( LogBlock, &TagID );
        }

        /* File Set Descriptor */
        if( TagID == 256 ) {  // File Set Descriptor
            UDFLongAD( &LogBlock[ 400 ], &RootICB );
        }
    } while( ( lbnum < partition.Start + partition.Length )
             && ( TagID != 8 ) && ( TagID != 256 ) );

    /* Sanity checks. */
    if( TagID != 256 ) return 0;
    if( RootICB.Partition != 0 ) return 0;

#if UDF_CACHE
    SetUDFCache(device, RootICBCache, 0, &RootICB);
    }
#endif

    /* Find root dir */
    if( !UDFMapICB( device, RootICB, &filetype, &partition, &File ) ) return 0;
    if( filetype != 4 ) return 0;  /* Root dir should be dir */

    {
      int cache_file_info = 0;
      /* Tokenize filepath */
      token = strtok(tokenline, "/");
      
      while( token != NULL ) {
       
        if( !UDFScanDir( device, File, token, &partition, &ICB,
                        cache_file_info)) {
         return 0;
       }
        if( !UDFMapICB( device, ICB, &filetype, &partition, &File ) ) {
         return 0;
       }
       if(!strcmp(token, "VIDEO_TS")) {
         cache_file_info = 1;
       }
        token = strtok( NULL, "/" );
      }
    } 

    /* Sanity check. */
    if( File.Partition != 0 ) return 0;
   
    *filesize = File.Length;
    /* Hack to not return partition.Start for empty files. */
    if( !File.Location )
      return 0;
    else
      return partition.Start + File.Location;
}



/**
 * Gets a Descriptor .
 * Returns 1 if descriptor found, 0 on error.
 * id, tagid of descriptor
 * bufsize, size of BlockBuf (must be >= DVD_VIDEO_LB_LEN).
 */
static int UDFGetDescriptor( dvd_reader_t *device, int id,
			     uint8_t *descriptor, int bufsize) 
{
  uint32_t lbnum, MVDS_location, MVDS_length;
  struct avdp_t avdp;
  uint16_t TagID;
  uint32_t lastsector;
  int i, terminate;
  int desc_found = 0;
  /* Find Anchor */
  lastsector = 0;
  lbnum = 256;   /* Try #1, prime anchor */
  terminate = 0;
  if(bufsize < DVD_VIDEO_LB_LEN) {
    return 0;
  }
  
  if(!UDFGetAVDP(device, &avdp)) {
    return 0;
  }

  /* Main volume descriptor */
  MVDS_location = avdp.mvds.location;
  MVDS_length = avdp.mvds.length;
  
  i = 1;
  do {
    /* Find  Descriptor */
    lbnum = MVDS_location;
    do {
      
      if( DVDReadLBUDF( device, lbnum++, 1, descriptor, 0 ) <= 0 ) {
	TagID = 0;
      } else {
	UDFDescriptor( descriptor, &TagID );
      }
      
      if( (TagID == id) && ( !desc_found ) ) {
	/* Descriptor */
	desc_found = 1;
      }
    } while( ( lbnum <= MVDS_location + ( MVDS_length - 1 )
	       / DVD_VIDEO_LB_LEN ) && ( TagID != 8 )
	     && ( !desc_found) );
    
    if( !desc_found ) {
      /* Backup volume descriptor */
      MVDS_location = avdp.rvds.location;
      MVDS_length = avdp.rvds.length;
    }
  } while( i-- && ( !desc_found )  );
  
  return desc_found;
}


static int UDFGetPVD(dvd_reader_t *device, struct pvd_t *pvd)
{
  uint8_t pvd_buf[DVD_VIDEO_LB_LEN];
  
#if UDF_CACHE
  if(GetUDFCache(device, PVDCache, 0, pvd)) {
    return 1;
  }
#endif

  if(!UDFGetDescriptor( device, 1, pvd_buf, sizeof(pvd_buf))) {
    return 0;
  }
  
  memcpy(pvd->VolumeIdentifier, &pvd_buf[24], 32);
  memcpy(pvd->VolumeSetIdentifier, &pvd_buf[72], 128);

#if UDF_CACHE
  SetUDFCache(device, PVDCache, 0, pvd);
#endif

  return 1;
}

/**
 * Gets the Volume Identifier string, in 8bit unicode (latin-1)
 * volid, place to put the string
 * volid_size, size of the buffer volid points to
 * returns the size of buffer needed for all data
 */
int UDFGetVolumeIdentifier(dvd_reader_t *device, char *volid,
			   unsigned int volid_size)
{
  struct pvd_t pvd;
  unsigned int volid_len;

  /* get primary volume descriptor */
  if(!UDFGetPVD(device, &pvd)) {
    return 0;
  }

  volid_len = pvd.VolumeIdentifier[31];
  if(volid_len > 31) {
    /* this field is only 32 bytes something is wrong */
    volid_len = 31;
  }
  if(volid_size > volid_len) {
    volid_size = volid_len;
  }
  Unicodedecode(pvd.VolumeIdentifier, volid_size, volid);
  
  return volid_len;
}

/**
 * Gets the Volume Set Identifier, as a 128-byte dstring (not decoded)
 * WARNING This is not a null terminated string
 * volsetid, place to put the data
 * volsetid_size, size of the buffer volsetid points to 
 * the buffer should be >=128 bytes to store the whole volumesetidentifier
 * returns the size of the available volsetid information (128)
 * or 0 on error
 */
int UDFGetVolumeSetIdentifier(dvd_reader_t *device, uint8_t *volsetid,
			      unsigned int volsetid_size)
{
  struct pvd_t pvd;

  /* get primary volume descriptor */
  if(!UDFGetPVD(device, &pvd)) {
    return 0;
  }


  if(volsetid_size > 128) {
    volsetid_size = 128;
  }
  
  memcpy(volsetid, pvd.VolumeSetIdentifier, volsetid_size);
  
  return 128;
}

⌨️ 快捷键说明

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