/**
 * 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;
}
Exemple #2
0
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;
}
Exemple #3
0
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++;
         }
Exemple #4
0
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++;
         }