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

📄 dvdnav.c

📁 linux下的MPEG1
💻 C
📖 第 1 页 / 共 3 页
字号:
/*  * Copyright (C) 2000 Rich Wareham <richwareham@users.sourceforge.net> *  * This file is part of libdvdnav, a DVD navigation library. *  * libdvdnav 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. *  * libdvdnav 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 * * $Id: dvdnav.c,v 1.34 2005/10/15 14:04:05 jcdutton Exp $ * */#ifdef HAVE_CONFIG_H#include "config.h"#endif/*#define LOG_DEBUG*/#include "dvdnav_internal.h"#include "read_cache.h"#include "nav_read.h"#include <stdlib.h>#include <stdio.h>#include <sys/time.h>#include "remap.h"static dvdnav_status_t dvdnav_clear(dvdnav_t * this) {  /* clear everything except file, vm, mutex, readahead */  if (this->file) DVDCloseFile(this->file);  this->file = NULL;  memset(&this->pci,0,sizeof(this->pci));  memset(&this->dsi,0,sizeof(this->dsi));  this->last_cmd_nav_lbn = SRI_END_OF_CELL;  /* Set initial values of flags */  this->position_current.still = 0;  this->skip_still = 0;  this->sync_wait = 0;  this->sync_wait_skip = 0;  this->spu_clut_changed = 0;  this->started = 0;  dvdnav_read_cache_clear(this->cache);    return DVDNAV_STATUS_OK;}dvdnav_status_t dvdnav_open(dvdnav_t** dest, const char *path) {  dvdnav_t *this;  struct timeval time;    /* Create a new structure */  fprintf(MSG_OUT, "libdvdnav: Using dvdnav version %s from http://xine.sf.net\n", VERSION);  (*dest) = NULL;  this = (dvdnav_t*)malloc(sizeof(dvdnav_t));  if(!this)    return DVDNAV_STATUS_ERR;  memset(this, 0, (sizeof(dvdnav_t) ) ); /* Make sure this structure is clean */   pthread_mutex_init(&this->vm_lock, NULL);  /* Initialise the error string */  printerr("");  /* Initialise the VM */  this->vm = vm_new_vm();  if(!this->vm) {    printerr("Error initialising the DVD VM.");    pthread_mutex_destroy(&this->vm_lock);    free(this);    return DVDNAV_STATUS_ERR;  }  if(!vm_reset(this->vm, path)) {    printerr("Error starting the VM / opening the DVD device.");    pthread_mutex_destroy(&this->vm_lock);    vm_free_vm(this->vm);    free(this);    return DVDNAV_STATUS_ERR;  }  /* Set the path. FIXME: Is a deep copy 'right' */  strncpy(this->path, path, MAX_PATH_LEN);  /* Pre-open and close a file so that the CSS-keys are cached. */  this->file = DVDOpenFile(vm_get_dvd_reader(this->vm), 0, DVD_READ_MENU_VOBS);      /* Start the read-ahead cache. */  this->cache = dvdnav_read_cache_new(this);  /* Seed the random numbers. So that the DVD VM Command rand()   * gives a different start value each time a DVD is played. */  gettimeofday(&time, NULL);  srand(time.tv_usec);   dvdnav_clear(this);   (*dest) = this;  return DVDNAV_STATUS_OK;}dvdnav_status_t dvdnav_close(dvdnav_t *this) {#ifdef LOG_DEBUG  fprintf(MSG_OUT, "libdvdnav: close:called\n");#endif  if(!this) {    printerr("Passed a NULL pointer.");    return DVDNAV_STATUS_ERR;  }  if (this->file) {    DVDCloseFile(this->file);#ifdef LOG_DEBUG    fprintf(MSG_OUT, "libdvdnav: close:file closing\n");#endif    this->file = NULL;  }  /* Free the VM */  if(this->vm)    vm_free_vm(this->vm);  pthread_mutex_destroy(&this->vm_lock);  /* We leave the final freeing of the entire structure to the cache,   * because we don't know, if there are still buffers out in the wild,   * that must return first. */  if(this->cache)    dvdnav_read_cache_free(this->cache);  else    free(this);    return DVDNAV_STATUS_OK;}dvdnav_status_t dvdnav_reset(dvdnav_t *this) {  dvdnav_status_t result;#ifdef LOG_DEBUG  fprintf(MSG_OUT, "libdvdnav: reset:called\n");#endif  if(!this) {    printerr("Passed a NULL pointer.");    return DVDNAV_STATUS_ERR;  }  pthread_mutex_lock(&this->vm_lock); #ifdef LOG_DEBUG  fprintf(MSG_OUT, "libdvdnav: reseting vm\n");#endif  if(!vm_reset(this->vm, NULL)) {    printerr("Error restarting the VM.");    pthread_mutex_unlock(&this->vm_lock);     return DVDNAV_STATUS_ERR;  }#ifdef LOG_DEBUG  fprintf(MSG_OUT, "libdvdnav: clearing dvdnav\n");#endif  result = dvdnav_clear(this);  pthread_mutex_unlock(&this->vm_lock);   return result;}dvdnav_status_t dvdnav_path(dvdnav_t *this, const char** path) {  if(!this || !path) {    printerr("Passed a NULL pointer.");    return DVDNAV_STATUS_ERR;  }  (*path) = this->path;  return DVDNAV_STATUS_OK;}const char* dvdnav_err_to_string(dvdnav_t *this) {    if(!this)    return "Hey! You gave me a NULL pointer you naughty person!";    return this->err_str;}/* converts a dvd_time_t to PTS ticks */int64_t dvdnav_convert_time(dvd_time_t *time) {  int64_t result;  int64_t frames;    result  = (time->hour    >> 4  ) * 10 * 60 * 60 * 90000;  result += (time->hour    & 0x0f)      * 60 * 60 * 90000;  result += (time->minute  >> 4  )      * 10 * 60 * 90000;  result += (time->minute  & 0x0f)           * 60 * 90000;  result += (time->second  >> 4  )           * 10 * 90000;  result += (time->second  & 0x0f)                * 90000;    frames  = ((time->frame_u & 0x30) >> 4) * 10;  frames += ((time->frame_u & 0x0f)     )     ;    if (time->frame_u & 0x80)    result += frames * 3000;  else    result += frames * 3600;    return result;}/* * Returns 1 if block contains NAV packet, 0 otherwise. * Processes said NAV packet if present. * * Most of the code in here is copied from xine's MPEG demuxer * so any bugs which are found in that should be corrected here also. */static int32_t dvdnav_decode_packet(dvdnav_t *this, uint8_t *p, dsi_t *nav_dsi, pci_t *nav_pci) {  int32_t        bMpeg1 = 0;  uint32_t       nHeaderLen;  uint32_t       nPacketLen;  uint32_t       nStreamID;  if (p[3] == 0xBA) { /* program stream pack header */    int32_t nStuffingBytes;    bMpeg1 = (p[4] & 0x40) == 0;    if (bMpeg1) {      p += 12;    } else { /* mpeg2 */      nStuffingBytes = p[0xD] & 0x07;      p += 14 + nStuffingBytes;    }  }  if (p[3] == 0xbb) { /* program stream system header */    nHeaderLen = (p[4] << 8) | p[5];    p += 6 + nHeaderLen;  }  /* we should now have a PES packet here */  if (p[0] || p[1] || (p[2] != 1)) {    fprintf(MSG_OUT, "libdvdnav: demux error! %02x %02x %02x (should be 0x000001) \n",p[0],p[1],p[2]);    return 0;  }  nPacketLen = p[4] << 8 | p[5];  nStreamID  = p[3];  nHeaderLen = 6;  p += nHeaderLen;  if (nStreamID == 0xbf) { /* Private stream 2 */#if 0    int32_t i;    fprintf(MSG_OUT, "libdvdnav: nav packet=%u\n",p-p_start-6);    for(i=0;i<80;i++)      fprintf(MSG_OUT, "%02x ",p[i-6]);    fprintf(MSG_OUT, "\n");#endif    if(p[0] == 0x00) {      navRead_PCI(nav_pci, p+1);    }    p += nPacketLen;    /* We should now have a DSI packet. */    if(p[6] == 0x01) {      nPacketLen = p[4] << 8 | p[5];      p += 6;      navRead_DSI(nav_dsi, p+1);    }     return 1;  }  return 0;}/* DSI is used for most angle stuff.  * PCI is used for only non-seemless angle stuff */ static int32_t dvdnav_get_vobu(dvdnav_t *this, dsi_t *nav_dsi, pci_t *nav_pci, dvdnav_vobu_t *vobu) {  uint32_t next;  int32_t angle, num_angle;  vobu->vobu_start = nav_dsi->dsi_gi.nv_pck_lbn; /* Absolute offset from start of disk */  vobu->vobu_length = nav_dsi->dsi_gi.vobu_ea; /* Relative offset from vobu_start */       /*   * If we're not at the end of this cell, we can determine the next   * VOBU to display using the VOBU_SRI information section of the   * DSI.  Using this value correctly follows the current angle,   * avoiding the doubled scenes in The Matrix, and makes our life   * really happy.   *   * vobu_next is an offset value, 0x3fffffff = SRI_END_OF_CELL   * DVDs are about 6 Gigs, which is only up to 0x300000 blocks   * Should really assert if bit 31 != 1   */  #if 0  /* Old code -- may still be useful one day */  if(nav_dsi->vobu_sri.next_vobu != SRI_END_OF_CELL ) {    vobu->vobu_next = ( nav_dsi->vobu_sri.next_vobu & 0x3fffffff );  } else {    vobu->vobu_next = vobu->vobu_length;  }#else  /* Relative offset from vobu_start */  vobu->vobu_next = ( nav_dsi->vobu_sri.next_vobu & 0x3fffffff );#endif    vm_get_angle_info(this->vm, &angle, &num_angle);  /* FIMXE: The angle reset doesn't work for some reason for the moment */#if 0  if((num_angle < angle) && (angle != 1)) {    fprintf(MSG_OUT, "libdvdnav: angle ends!\n");        /* This is to switch back to angle one when we     * finish with angles. */    dvdnav_angle_change(this, 1);  } #endif  if(num_angle != 0) {        if((next = nav_pci->nsml_agli.nsml_agl_dsta[angle-1]) != 0) {      if((next & 0x3fffffff) != 0) {	if(next & 0x80000000)	  vobu->vobu_next = - (int32_t)(next & 0x3fffffff);	else	  vobu->vobu_next = + (int32_t)(next & 0x3fffffff);      }    } else if((next = nav_dsi->sml_agli.data[angle-1].address) != 0) {      vobu->vobu_length = nav_dsi->sml_pbi.ilvu_ea;            if((next & 0x80000000) && (next != 0x7fffffff))	vobu->vobu_next =  - (int32_t)(next & 0x3fffffff);      else	vobu->vobu_next =  + (int32_t)(next & 0x3fffffff);    }  }  return 1;

⌨️ 快捷键说明

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