/** * Open a DVD image or block device file. */ static dvd_reader_t *DVDOpenImageFile( const char *location, int have_css ) { dvd_reader_t *dvd; dvd_input_t dev; static int volid_size = 32, volsetid_size = 128; char volid[volid_size]; unsigned char volsetid[volsetid_size]; dev = dvdinput_open( location ); if( !dev ) { fprintf( stderr, "libdvdread: Can't open %s for reading\n", location ); return NULL; } dvd = (dvd_reader_t *) malloc( sizeof( dvd_reader_t ) ); if( !dvd ) { dvdinput_close(dev); return NULL; } dvd->dev = dev; dvd->path_root = NULL; dvd->udfcache_level = DEFAULT_UDF_CACHE_LEVEL; dvd->udfcache = NULL; if( have_css ) { /* Only if DVDCSS_METHOD = title, a bit if it's disc or if * DVDCSS_METHOD = key but region mismatch. Unfortunately we * don't have that information. */ dvd->css_state = 1; /* Need key init. */ } else { dvd->css_state = 0; } dvd->css_title = 0; // check is iso9660/udf format if (DVDUDFVolumeInfo(dvd, volid, volid_size, volsetid, volsetid_size) == 0) { dvd->isImageFile = 1; } else if (DVDISOVolumeInfo(dvd, volid, volid_size, volsetid, volsetid_size) == 0) { dvd->isImageFile = 2; } else{ dvdinput_close(dev); free(dvd); dvd = NULL; } return dvd; }
static int control(stream_t *stream,int cmd,void* arg) { dvd_priv_t *d = stream->priv; switch(cmd) { case STREAM_CTRL_GET_TIME_LENGTH: { *((double *)arg) = (double) mp_get_titleset_length(d->vts_file, d->tt_srpt, d->cur_title)/1000.0; return 1; } case STREAM_CTRL_GET_START_TIME: { *((double *)arg) = 0; return 1; } case STREAM_CTRL_GET_NUM_TITLES: { *((unsigned int *)arg) = d->vmg_file->tt_srpt->nr_of_srpts; return 1; } case STREAM_CTRL_GET_NUM_CHAPTERS: { int r; r = get_num_chapter(d->vts_file, d->tt_srpt, d->cur_title); if(! r) return STREAM_UNSUPPORTED; *((unsigned int *)arg) = r; return 1; } case STREAM_CTRL_GET_CHAPTER_TIME: { int r; r = get_chapter_time(d->vts_file, d->tt_srpt, d->cur_title, (double *)arg); if(! r) return STREAM_UNSUPPORTED; return 1; } case STREAM_CTRL_GET_CURRENT_TITLE: { *((unsigned int *)arg) = d->cur_title; return 1; } case STREAM_CTRL_GET_CURRENT_TIME: { double tm; tm = dvd_get_current_time(stream, -1); if(tm != -1) { *((double *)arg) = tm; return 1; } break; } case STREAM_CTRL_SEEK_TO_TIME: { if(dvd_seek_to_time(stream, d->vts_file, *((double*)arg))) return 1; break; } case STREAM_CTRL_GET_ASPECT_RATIO: { *((double *)arg) = !d->vts_file->vtsi_mat->vts_video_attr.display_aspect_ratio ? 4.0/3.0 : 16.0/9.0; return 1; } case STREAM_CTRL_GET_NUM_ANGLES: { *((int *)arg) = d->vmg_file->tt_srpt->title[d->dvd_title].nr_of_angles; return 1; } case STREAM_CTRL_GET_ANGLE: { *((int *)arg) = d->dvd_angle; return 1; } case STREAM_CTRL_SET_ANGLE: { int ang = *((int *)arg); if(ang>d->vmg_file->tt_srpt->title[d->dvd_title].nr_of_angles || ang<=0) break; d->dvd_angle = ang; d->angle_seek = 1; return 1; } case STREAM_CTRL_GET_LANG: { struct stream_lang_req *req = arg; int lang = 0; switch(req->type) { case STREAM_AUDIO: lang = dvd_lang_from_aid(stream, req->id); break; case STREAM_SUB: lang = dvd_lang_from_sid(stream, req->id); break; } if (!lang) break; snprintf(req->name, sizeof(req->name), "%c%c", lang >> 8, lang); return STREAM_OK; } case STREAM_CTRL_GET_DVD_INFO: { struct stream_dvd_info_req *req = arg; memset(req, 0, sizeof(*req)); req->num_subs = dvd_number_of_subs(stream); memcpy(req->palette, d->cur_pgc->palette, sizeof(req->palette)); return STREAM_OK; } case STREAM_CTRL_GET_DISC_NAME: { char buffer[128]; if (DVDUDFVolumeInfo(d->dvd, buffer, sizeof(buffer), NULL, 0) < 0 && DVDISOVolumeInfo(d->dvd, buffer, sizeof(buffer), NULL, 0) < 0) break; if (!buffer[0]) break; *(char**)arg = talloc_strdup(NULL, buffer); return STREAM_OK; } } return STREAM_UNSUPPORTED; }
static int open_s(stream_t *stream, int mode) { int k; dvd_priv_t *d = stream->priv; MP_VERBOSE(stream, "URL: %s\n", stream->url); dvd_title = d->cfg_title + 1; if(1){ //int ret,ret2; int ttn,pgc_id,pgn; dvd_reader_t *dvd; dvd_file_t *title; ifo_handle_t *vmg_file; tt_srpt_t *tt_srpt; ifo_handle_t *vts_file; pgc_t *pgc; /** * Open the disc. */ if(d->cfg_device) dvd_device_current = d->cfg_device; else if(dvd_device) dvd_device_current = dvd_device; else dvd_device_current = DEFAULT_DVD_DEVICE; dvd_set_speed(stream,dvd_device_current, dvd_speed); #if defined(__APPLE__) || defined(__DARWIN__) /* Dynamic DVD drive selection on Darwin */ if(!strcmp(dvd_device_current, "/dev/rdiskN")) { int i; size_t len = strlen(dvd_device_current)+1; char *temp_device = malloc(len); for (i = 1; i < 10; i++) { snprintf(temp_device, len, "/dev/rdisk%d", i); dvd = DVDOpen(temp_device); if(!dvd) { MP_ERR(stream, "Couldn't open DVD device: %s (%s)\n",temp_device, strerror(errno)); } else { #if DVDREAD_VERSION <= LIBDVDREAD_VERSION(0,9,4) dvd_file_t *dvdfile = DVDOpenFile(dvd,dvd_title,DVD_READ_INFO_FILE); if(!dvdfile) { MP_ERR(stream, "Couldn't open DVD device: %s (%s)\n",temp_device, strerror(errno)); DVDClose(dvd); continue; } DVDCloseFile(dvdfile); #endif break; } } free(temp_device); if(!dvd) { return STREAM_UNSUPPORTED; } } else #endif /* defined(__APPLE__) || defined(__DARWIN__) */ { dvd = DVDOpen(dvd_device_current); if(!dvd) { MP_ERR(stream, "Couldn't open DVD device: %s (%s)\n",dvd_device_current, strerror(errno)); return STREAM_UNSUPPORTED; } } MP_VERBOSE(stream, "Reading disc structure, please wait...\n"); /** * Load the video manager to find out the information about the titles on * this disc. */ vmg_file = ifoOpen(dvd, 0); if(!vmg_file) { MP_ERR(stream, "Can't open VMG info!\n"); DVDClose( dvd ); return STREAM_UNSUPPORTED; } tt_srpt = vmg_file->tt_srpt; if (mp_msg_test(stream->log, MSGL_SMODE)) { int title_no; ///< title number MP_SMODE(stream, "ID_DVD_TITLES=%d\n", tt_srpt->nr_of_srpts); for (title_no = 0; title_no < tt_srpt->nr_of_srpts; title_no++) { MP_SMODE(stream, "ID_DVD_TITLE_%d_CHAPTERS=%d\n", title_no, tt_srpt->title[title_no].nr_of_ptts); MP_SMODE(stream, "ID_DVD_TITLE_%d_ANGLES=%d\n", title_no, tt_srpt->title[title_no].nr_of_angles); } } if (mp_msg_test(stream->log, MSGL_SMODE)) { char volid[32]; unsigned char discid [16]; ///< disk ID, a 128 bit MD5 sum int vts_no; ///< video title set number for (vts_no = 1; vts_no <= vmg_file->vts_atrt->nr_of_vtss; vts_no++) mp_describe_titleset(stream, dvd, tt_srpt, vts_no); if (DVDDiscID(dvd, discid) >= 0) { int i; MP_SMODE(stream, "ID_DVD_DISC_ID="); for (i = 0; i < 16; i ++) MP_SMODE(stream, "%02X", discid[i]); MP_SMODE(stream, "\n"); } if (DVDUDFVolumeInfo(dvd, volid, sizeof(volid), NULL, 0) >= 0 || DVDISOVolumeInfo(dvd, volid, sizeof(volid), NULL, 0) >= 0) MP_SMODE(stream, "ID_DVD_VOLUME_ID=%s\n", volid); } /** * Make sure our title number is valid. */ MP_INFO(stream, "There are %d titles on this DVD.\n", tt_srpt->nr_of_srpts ); if(dvd_title < 1 || dvd_title > tt_srpt->nr_of_srpts) { MP_ERR(stream, "Invalid DVD title number: %d\n", dvd_title); ifoClose( vmg_file ); DVDClose( dvd ); return STREAM_UNSUPPORTED; } MP_SMODE(stream, "ID_DVD_CURRENT_TITLE=%d\n", dvd_title); --dvd_title; // remap 1.. -> 0.. /** * Make sure the angle number is valid for this title. */ MP_INFO(stream, "There are %d angles in this DVD title.\n", tt_srpt->title[dvd_title].nr_of_angles); if(dvd_angle<1 || dvd_angle>tt_srpt->title[dvd_title].nr_of_angles) { MP_ERR(stream, "Invalid DVD angle number: %d\n", dvd_angle); goto fail; } ttn = tt_srpt->title[dvd_title].vts_ttn - 1; /** * Load the VTS information for the title set our title is in. */ vts_file = ifoOpen( dvd, tt_srpt->title[dvd_title].title_set_nr ); if(!vts_file) { MP_ERR(stream, "Cannot open the IFO file for DVD title %d.\n", tt_srpt->title[dvd_title].title_set_nr ); goto fail; } /** * We've got enough info, time to open the title set data. */ title = DVDOpenFile(dvd, tt_srpt->title[dvd_title].title_set_nr, DVD_READ_TITLE_VOBS); if(!title) { MP_ERR(stream, "Cannot open title VOBS (VTS_%02d_1.VOB).\n", tt_srpt->title[dvd_title].title_set_nr); ifoClose( vts_file ); goto fail; } MP_VERBOSE(stream, "DVD successfully opened.\n"); // store data d->dvd=dvd; d->title=title; d->vmg_file=vmg_file; d->tt_srpt=tt_srpt; d->vts_file=vts_file; d->cur_title = dvd_title; pgc = vts_file->vts_pgcit ? vts_file->vts_pgcit->pgci_srp[ttn].pgc : NULL; /** * Check number of audio channels and types */ { d->nr_of_channels=0; if(vts_file->vts_pgcit) { int i; for(i=0;i<8;i++) if(pgc->audio_control[i] & 0x8000) { audio_attr_t * audio = &vts_file->vtsi_mat->vts_audio_attr[i]; int language = 0; char tmp[] = "unknown"; stream_language_t *audio_stream = &d->audio_streams[d->nr_of_channels]; if(audio->lang_type == 1) { language=audio->lang_code; tmp[0]=language>>8; tmp[1]=language&0xff; tmp[2]=0; } audio_stream->language=language; audio_stream->id=pgc->audio_control[i] >> 8 & 7; switch(audio->audio_format) { case 0: // ac3 audio_stream->id+=FIRST_AC3_AID; break; case 6: // dts audio_stream->id+=FIRST_DTS_AID; break; case 2: // mpeg layer 1/2/3 case 3: // mpeg2 ext audio_stream->id+=FIRST_MPG_AID; break; case 4: // lpcm audio_stream->id+=FIRST_PCM_AID; break; } audio_stream->type=audio->audio_format; // Pontscho: to my mind, tha channels: // 1 - stereo // 5 - 5.1 audio_stream->channels=audio->channels; MP_INFO(stream, "audio stream: %d format: %s (%s) language: %s aid: %d.\n", d->nr_of_channels, dvd_audio_stream_types[ audio->audio_format ], dvd_audio_stream_channels[ audio->channels ], tmp, audio_stream->id ); MP_SMODE(stream, "ID_AUDIO_ID=%d\n", audio_stream->id); if(language && tmp[0]) MP_SMODE(stream, "ID_AID_%d_LANG=%s\n", audio_stream->id, tmp); d->nr_of_channels++; }
static int open_s(stream_t *stream,int mode, void* opts, int* file_format) { struct stream_priv_s* p = (struct stream_priv_s*)opts; int k; mp_msg(MSGT_OPEN,MSGL_V,"URL: %s\n", stream->url); dvd_title = p->title; if(1){ //int ret,ret2; dvd_priv_t *d; int ttn,pgc_id,pgn; dvd_reader_t *dvd; dvd_file_t *title; ifo_handle_t *vmg_file; tt_srpt_t *tt_srpt; ifo_handle_t *vts_file; pgc_t *pgc; /** * Open the disc. */ if(p->device) dvd_device_current = p->device; else if(dvd_device) dvd_device_current = dvd_device; else dvd_device_current = DEFAULT_DVD_DEVICE; dvd_set_speed(dvd_device_current, dvd_speed); #if defined(__APPLE__) || defined(__DARWIN__) /* Dynamic DVD drive selection on Darwin */ if(!strcmp(dvd_device_current, "/dev/rdiskN")) { int i; size_t len = strlen(dvd_device_current)+1; char *temp_device = malloc(len); for (i = 1; i < 10; i++) { snprintf(temp_device, len, "/dev/rdisk%d", i); dvd = DVDOpen(temp_device); if(!dvd) { mp_msg(MSGT_OPEN,MSGL_ERR,MSGTR_CantOpenDVD,temp_device, strerror(errno)); } else { #if DVDREAD_VERSION <= LIBDVDREAD_VERSION(0,9,4) dvd_file_t *dvdfile = DVDOpenFile(dvd,dvd_title,DVD_READ_INFO_FILE); if(!dvdfile) { mp_msg(MSGT_OPEN,MSGL_ERR,MSGTR_CantOpenDVD,temp_device, strerror(errno)); DVDClose(dvd); continue; } DVDCloseFile(dvdfile); #endif break; } } free(temp_device); if(!dvd) { m_struct_free(&stream_opts,opts); return STREAM_UNSUPPORTED; } } else #endif /* defined(__APPLE__) || defined(__DARWIN__) */ { dvd = DVDOpen(dvd_device_current); if(!dvd) { mp_msg(MSGT_OPEN,MSGL_ERR,MSGTR_CantOpenDVD,dvd_device_current, strerror(errno)); m_struct_free(&stream_opts,opts); return STREAM_UNSUPPORTED; } } mp_msg(MSGT_OPEN,MSGL_V,"Reading disc structure, please wait...\n"); /** * Load the video manager to find out the information about the titles on * this disc. */ vmg_file = ifoOpen(dvd, 0); if(!vmg_file) { mp_msg(MSGT_OPEN,MSGL_ERR, MSGTR_DVDnoVMG); DVDClose( dvd ); m_struct_free(&stream_opts,opts); return STREAM_UNSUPPORTED; } tt_srpt = vmg_file->tt_srpt; if (mp_msg_test(MSGT_IDENTIFY, MSGL_INFO)) { int title_no; ///< title number mp_msg(MSGT_IDENTIFY, MSGL_INFO, "ID_DVD_TITLES=%d\n", tt_srpt->nr_of_srpts); for (title_no = 0; title_no < tt_srpt->nr_of_srpts; title_no++) { mp_msg(MSGT_IDENTIFY, MSGL_INFO, "ID_DVD_TITLE_%d_CHAPTERS=%d\n", title_no + 1, tt_srpt->title[title_no].nr_of_ptts); mp_msg(MSGT_IDENTIFY, MSGL_INFO, "ID_DVD_TITLE_%d_ANGLES=%d\n", title_no + 1, tt_srpt->title[title_no].nr_of_angles); } } if (mp_msg_test(MSGT_IDENTIFY, MSGL_V)) { char volid[32]; unsigned char discid [16]; ///< disk ID, a 128 bit MD5 sum int vts_no; ///< video title set number for (vts_no = 1; vts_no <= vmg_file->vts_atrt->nr_of_vtss; vts_no++) mp_describe_titleset(dvd, tt_srpt, vts_no); if (DVDDiscID(dvd, discid) >= 0) { int i; mp_msg(MSGT_IDENTIFY, MSGL_V, "ID_DVD_DISC_ID="); for (i = 0; i < 16; i ++) mp_msg(MSGT_IDENTIFY, MSGL_V, "%02X", discid[i]); mp_msg(MSGT_IDENTIFY, MSGL_V, "\n"); } if (DVDUDFVolumeInfo(dvd, volid, sizeof(volid), NULL, 0) >= 0 || DVDISOVolumeInfo(dvd, volid, sizeof(volid), NULL, 0) >= 0) mp_msg(MSGT_IDENTIFY, MSGL_V, "ID_DVD_VOLUME_ID=%s\n", volid); } #ifdef GEKKO /** * Try to autodetect main title if title number not specified. */ if (dvd_title == 0) { int longest_len = 0; int longest_title = 0; int vts_no; for (vts_no = 1; vts_no <= vmg_file->vts_atrt->nr_of_vtss; vts_no++) { ifo_handle_t *temp_vts_file = ifoOpen(dvd, vts_no); // ignore failed titles if (temp_vts_file) { int title_no; for (title_no = 0; title_no < tt_srpt->nr_of_srpts; title_no++) { int len; if (tt_srpt->title[title_no].title_set_nr != vts_no) continue; len = mp_get_titleset_length(temp_vts_file, tt_srpt, title_no); if (len > longest_len) { longest_len = len; longest_title = title_no; } } ifoClose(temp_vts_file); } } dvd_title = longest_title + 1; // remap +1 for the validation } if(dvd_angle < 1) dvd_angle = 1; #endif /** * Make sure our title number is valid. */ mp_msg(MSGT_OPEN,MSGL_STATUS, MSGTR_DVDnumTitles, tt_srpt->nr_of_srpts ); if(dvd_title < 1 || dvd_title > tt_srpt->nr_of_srpts) { mp_msg(MSGT_OPEN,MSGL_ERR, MSGTR_DVDinvalidTitle, dvd_title); ifoClose( vmg_file ); DVDClose( dvd ); m_struct_free(&stream_opts,opts); return STREAM_UNSUPPORTED; } mp_msg(MSGT_IDENTIFY, MSGL_INFO, "ID_DVD_CURRENT_TITLE=%d\n", dvd_title); --dvd_title; // remap 1.. -> 0.. /** * Make sure the angle number is valid for this title. */ mp_msg(MSGT_OPEN,MSGL_STATUS, MSGTR_DVDnumAngles, tt_srpt->title[dvd_title].nr_of_angles); if(dvd_angle<1 || dvd_angle>tt_srpt->title[dvd_title].nr_of_angles) { mp_msg(MSGT_OPEN,MSGL_ERR, MSGTR_DVDinvalidAngle, dvd_angle); goto fail; } --dvd_angle; // remap 1.. -> 0.. ttn = tt_srpt->title[dvd_title].vts_ttn - 1; /** * Load the VTS information for the title set our title is in. */ vts_file = ifoOpen( dvd, tt_srpt->title[dvd_title].title_set_nr ); if(!vts_file) { mp_msg(MSGT_OPEN,MSGL_ERR, MSGTR_DVDnoIFO, tt_srpt->title[dvd_title].title_set_nr ); goto fail; } /** * We've got enough info, time to open the title set data. */ title = DVDOpenFile(dvd, tt_srpt->title[dvd_title].title_set_nr, DVD_READ_TITLE_VOBS); if(!title) { mp_msg(MSGT_OPEN,MSGL_ERR, MSGTR_DVDnoVOBs, tt_srpt->title[dvd_title].title_set_nr); ifoClose( vts_file ); goto fail; } mp_msg(MSGT_OPEN,MSGL_V, "DVD successfully opened.\n"); // store data d=malloc(sizeof(dvd_priv_t)); memset(d,0,sizeof(dvd_priv_t)); d->dvd=dvd; d->title=title; d->vmg_file=vmg_file; d->tt_srpt=tt_srpt; d->vts_file=vts_file; d->cur_title = dvd_title+1; pgc = vts_file->vts_pgcit ? vts_file->vts_pgcit->pgci_srp[ttn].pgc : NULL; /** * Check number of audio channels and types */ { d->nr_of_channels=0; if(vts_file->vts_pgcit) { int i; for(i=0;i<8;i++) if(pgc->audio_control[i] & 0x8000) { audio_attr_t * audio = &vts_file->vtsi_mat->vts_audio_attr[i]; int language = 0; char tmp[] = "unknown"; stream_language_t *audio_stream = &d->audio_streams[d->nr_of_channels]; if(audio->lang_type == 1) { language=audio->lang_code; tmp[0]=language>>8; tmp[1]=language&0xff; tmp[2]=0; } audio_stream->language=language; audio_stream->id=pgc->audio_control[i] >> 8 & 7; switch(audio->audio_format) { case 0: // ac3 audio_stream->id+=FIRST_AC3_AID; break; case 6: // dts audio_stream->id+=FIRST_DTS_AID; break; case 2: // mpeg layer 1/2/3 case 3: // mpeg2 ext audio_stream->id+=FIRST_MPG_AID; break; case 4: // lpcm audio_stream->id+=FIRST_PCM_AID; break; } audio_stream->type=audio->audio_format; // Pontscho: to my mind, tha channels: // 1 - stereo // 5 - 5.1 audio_stream->channels=audio->channels; mp_msg(MSGT_OPEN,MSGL_STATUS,MSGTR_DVDaudioStreamInfo, d->nr_of_channels, dvd_audio_stream_types[ audio->audio_format ], dvd_audio_stream_channels[ audio->channels ], tmp, audio_stream->id ); mp_msg(MSGT_IDENTIFY, MSGL_INFO, "ID_AUDIO_ID=%d\n", audio_stream->id); if(language && tmp[0]) mp_msg(MSGT_IDENTIFY, MSGL_INFO, "ID_AID_%d_LANG=%s\n", audio_stream->id, tmp); d->nr_of_channels++; }