Exemple #1
0
static int dvdnav_stream_read(dvdnav_priv_t * priv, unsigned char *buf, int *len) {
  int event = DVDNAV_NOP;

  if (!len) return -1;
  *len=-1;
  if (!priv) return -1;
  if (!buf) return -1;

  if (dvd_nav_still) {
    mp_msg(MSGT_OPEN,MSGL_V, "%s: got a stream_read while I should be asleep!\n",__FUNCTION__);
    *len=0;
    return -1;
  }

  if (dvdnav_get_next_block(priv->dvdnav,buf,&event,len)!=DVDNAV_STATUS_OK) {
    mp_msg(MSGT_OPEN,MSGL_V, "Error getting next block from DVD %d (%s)\n",event, dvdnav_err_to_string(priv->dvdnav) );
    *len=-1;
  }
  else if (event!=DVDNAV_BLOCK_OK) {
    // need to handle certain events internally (like skipping stills)
    switch (event) {
      case DVDNAV_NAV_PACKET:
        return event;
      case DVDNAV_STILL_FRAME: {
        dvdnav_still_event_t *still_event = (dvdnav_still_event_t*)(buf);
        //if (priv->started) dvd_nav_still=1;
        //else
          dvdnav_still_skip(priv->dvdnav); // don't let dvdnav stall on this image

        break;
      }
      case DVDNAV_HIGHLIGHT: {
        dvdnav_get_highlight (priv, 1);
        break;
      }
      case DVDNAV_CELL_CHANGE: {
        dvdnav_cell_change_event_t *ev =  (dvdnav_cell_change_event_t*)buf;
        if(ev->pgc_length)
          priv->duration = ev->pgc_length/90;
        break;
      }
      case DVDNAV_SPU_CLUT_CHANGE: {
        memcpy(priv->spu_clut, buf, 16*sizeof(unsigned int));
        priv->spu_set = 1;
        break;
      }
      case DVDNAV_WAIT:
        dvdnav_wait_skip(priv->dvdnav);
        break;
    }

    *len=0;
  }
  return event;
}
Exemple #2
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;
  char *filename;
  dvdnav_priv_t *priv;

  if(p->device) filename = p->device; 
  else if(dvd_device) filename= dvd_device; 
  else filename = DEFAULT_DVD_DEVICE;
  if(!(priv=new_dvdnav_stream(filename))) {
    mp_msg(MSGT_OPEN,MSGL_ERR,MSGTR_CantOpenDVD,filename, strerror(errno));
    return STREAM_UNSUPPORTED;
  }

  if(p->track > 0) {
    if(dvd_chapter > 0 && dvd_last_chapter > 0 && dvd_chapter > dvd_last_chapter) {
      mp_msg(MSGT_OPEN,MSGL_FATAL,"dvdnav_stream, invalid chapter range: %d > %d\n", dvd_chapter, dvd_last_chapter);
      return STREAM_UNSUPPORTED;
    }
    priv->title = p->track;
    if(dvdnav_title_play(priv->dvdnav, p->track) != DVDNAV_STATUS_OK) {
      mp_msg(MSGT_OPEN,MSGL_FATAL,"dvdnav_stream, couldn't select title %d, error '%s'\n", p->track, dvdnav_err_to_string(priv->dvdnav));
      return STREAM_UNSUPPORTED;
    }
    if(dvd_chapter > 0)
      dvdnav_part_play(priv->dvdnav, p->track, dvd_chapter);
  } else if(p->track == -1)
    dvdnav_menu_call(priv->dvdnav, DVD_MENU_Root);
  else {
    mp_msg(MSGT_OPEN,MSGL_INFO,"dvdnav_stream, you didn't specify a track number (as in dvdnav://1), playing whole disc\n");
    dvdnav_menu_call(priv->dvdnav, DVD_MENU_Title);
  }
  if(mp_msg_test(MSGT_IDENTIFY, MSGL_INFO))
    identify(priv, p);
  if(dvd_angle > 1)
    dvdnav_angle_change(priv->dvdnav, dvd_angle);

  stream->sector_size = 2048;
  stream->flags = STREAM_READ | STREAM_SEEK;
  stream->fill_buffer = fill_buffer;
  stream->seek = seek;
  stream->control = control;
  stream->close = stream_dvdnav_close;
  stream->type = STREAMTYPE_DVDNAV;
  stream->priv=(void*)priv;
  *file_format = DEMUXER_TYPE_MPEG_PS;

  update_title_len(stream);
  if(!stream->pos)
    mp_msg(MSGT_OPEN,MSGL_ERR, "INIT ERROR: couldn't get init pos %s\r\n", dvdnav_err_to_string(priv->dvdnav));

  mp_msg(MSGT_OPEN,MSGL_INFO, "Remember to disable MPlayer's cache when playing dvdnav:// streams (adding -nocache to your command line)\r\n");

  return STREAM_OK;
}
Exemple #3
0
static int seek(stream_t *s, off_t newpos) {
  uint32_t sector = 0;
  dvdnav_priv_t *priv = s->priv;

  if(s->end_pos && newpos > s->end_pos)
     newpos = s->end_pos;
  sector = newpos / 2048ULL;
  if(dvdnav_sector_search(priv->dvdnav, (uint64_t) sector, SEEK_SET) != DVDNAV_STATUS_OK)
    goto fail;

  s->pos = newpos;

  return 1;

fail:
  mp_msg(MSGT_STREAM,MSGL_INFO,"dvdnav_stream, seeking to %"PRIu64" failed: %s\n", newpos, dvdnav_err_to_string(priv->dvdnav));

  return 1;
}
Exemple #4
0
static int dvdnav_stream_read(dvdnav_priv_t * priv, unsigned char *buf, int *len) {
  int event = DVDNAV_NOP;

  *len=-1;
  if (dvdnav_get_next_block(priv->dvdnav,buf,&event,len)!=DVDNAV_STATUS_OK) {
    mp_msg(MSGT_OPEN,MSGL_V, "Error getting next block from DVD %d (%s)\n",event, dvdnav_err_to_string(priv->dvdnav) );
    *len=-1;
  }
  else if (event!=DVDNAV_BLOCK_OK) {
    // need to handle certain events internally (like skipping stills)
    switch (event) {
      case DVDNAV_NAV_PACKET:
        return event;
      case DVDNAV_STILL_FRAME: {
        dvdnav_still_event_t *still_event = (dvdnav_still_event_t *) buf;
        priv->still_length = still_event->length;
        /* set still frame duration */
        priv->duration = dvdnav_get_duration (priv->still_length);
        if (priv->still_length <= 1) {
          pci_t *pnavpci = dvdnav_get_current_nav_pci (priv->dvdnav);
          priv->duration = mp_dvdtimetomsec (&pnavpci->pci_gi.e_eltm);
        }
        break;
      }
      case DVDNAV_HIGHLIGHT: {
        dvdnav_get_highlight (priv, 1);
        break;
      }
      case DVDNAV_CELL_CHANGE: {
        dvdnav_cell_change_event_t *ev =  (dvdnav_cell_change_event_t*)buf;
        uint32_t nextstill;

        priv->state &= ~NAV_FLAG_WAIT_SKIP;
        priv->state |= NAV_FLAG_STREAM_CHANGE;
        if(ev->pgc_length)
          priv->duration = ev->pgc_length/90;

        if (dvdnav_is_domain_vts(priv->dvdnav)) {
          mp_msg(MSGT_IDENTIFY, MSGL_INFO, "DVDNAV_TITLE_IS_MOVIE\n");
          priv->state &= ~NAV_FLAG_VTS_DOMAIN;
        } else {
          mp_msg(MSGT_IDENTIFY, MSGL_INFO, "DVDNAV_TITLE_IS_MENU\n");
          priv->state |= NAV_FLAG_VTS_DOMAIN;
        }

        nextstill = dvdnav_get_next_still_flag (priv->dvdnav);
        if (nextstill) {
          priv->duration = dvdnav_get_duration (nextstill);
          priv->still_length = nextstill;
          if (priv->still_length <= 1) {
            pci_t *pnavpci = dvdnav_get_current_nav_pci (priv->dvdnav);
            priv->duration = mp_dvdtimetomsec (&pnavpci->pci_gi.e_eltm);
          }
        }

        break;
      }
      case DVDNAV_SPU_CLUT_CHANGE: {
        memcpy(priv->spu_clut, buf, 16*sizeof(unsigned int));
        priv->state |= NAV_FLAG_SPU_SET;
        break;
      }
      case DVDNAV_WAIT: {
        if ((priv->state & NAV_FLAG_WAIT_SKIP) &&
            !(priv->state & NAV_FLAG_WAIT))
          dvdnav_wait_skip (priv->dvdnav);
        else
          priv->state |= NAV_FLAG_WAIT;
        break;
      }
      case DVDNAV_VTS_CHANGE: {
        priv->state &= ~NAV_FLAG_WAIT_SKIP;
        priv->state |= NAV_FLAG_STREAM_CHANGE;
        break;
      }
      case DVDNAV_SPU_STREAM_CHANGE: {
        priv->state |= NAV_FLAG_STREAM_CHANGE;
        break;
      }
    }

    *len=0;
  }
  return event;
}
Exemple #5
0
int main(int argc, char **argv) {
  dvdnav_t *dvdnav;
  uint8_t mem[DVD_VIDEO_LB_LEN];
  int finished = 0;
  int output_fd = 0;
  int dump = 0, tt_dump = 0;
  
  /* open dvdnav handle */
  printf("Opening DVD...\n");
  if (dvdnav_open(&dvdnav, "/dev/dvd") != DVDNAV_STATUS_OK) {
    printf("Error on dvdnav_open\n");
    return 1;
  }
  
  /* set read ahead cache usage */
  if (dvdnav_set_readahead_flag(dvdnav, DVD_READ_CACHE) != DVDNAV_STATUS_OK) {
    printf("Error on dvdnav_set_readahead_flag: %s\n", dvdnav_err_to_string(dvdnav));
    return 2;
  }
  
  /* set the language */
  if (dvdnav_menu_language_select(dvdnav, DVD_LANGUAGE) != DVDNAV_STATUS_OK ||
      dvdnav_audio_language_select(dvdnav, DVD_LANGUAGE) != DVDNAV_STATUS_OK ||
      dvdnav_spu_language_select(dvdnav, DVD_LANGUAGE) != DVDNAV_STATUS_OK) {
    printf("Error on setting languages: %s\n", dvdnav_err_to_string(dvdnav));
    return 2;
  }
  
  /* set the PGC positioning flag to have position information relatively to the
   * whole feature instead of just relatively to the current chapter */
  if (dvdnav_set_PGC_positioning_flag(dvdnav, 1) != DVDNAV_STATUS_OK) {
    printf("Error on dvdnav_set_PGC_positioning_flag: %s\n", dvdnav_err_to_string(dvdnav));
    return 2;
  }
  

  /* the read loop which regularly calls dvdnav_get_next_block
   * and handles the returned events */
  printf("Reading...\n");
  while (!finished) {
    int result, event, len;
    uint8_t *buf = mem;
    
    /* the main reading function */
#if DVD_READ_CACHE
    result = dvdnav_get_next_cache_block(dvdnav, &buf, &event, &len);
#else
    result = dvdnav_get_next_block(dvdnav, buf, &event, &len);
#endif

    if (result == DVDNAV_STATUS_ERR) {
      printf("Error getting next block: %s\n", dvdnav_err_to_string(dvdnav));
      return 3;
    }

    switch (event) {
    case DVDNAV_BLOCK_OK:
      /* We have received a regular block of the currently playing MPEG stream.
       * A real player application would now pass this block through demuxing
       * and decoding. We simply write it to disc here. */
      
      if (!output_fd) {
	printf("Opening output...\n");
	output_fd = open("libdvdnav.mpg", O_CREAT | O_WRONLY, S_IRWXU | S_IRWXG);
	if (output_fd == -1) {
	  printf("Error opening output\n");
	  return 4;
	}
      }
      
      if (dump || tt_dump)
	write(output_fd, buf, len);

      break;
    case DVDNAV_NOP:
      /* Nothing to do here. */
      break;
    case DVDNAV_STILL_FRAME: 
      /* We have reached a still frame. A real player application would wait
       * the amount of time specified by the still's length while still handling
       * user input to make menus and other interactive stills work.
       * A length of 0xff means an indefinite still which has to be skipped
       * indirectly by some user interaction. */
      {
	dvdnav_still_event_t *still_event = (dvdnav_still_event_t *)buf;
	if (still_event->length < 0xff)
	  printf("Skipping %d seconds of still frame\n", still_event->length);
	else
	  printf("Skipping indefinite length still frame\n");
	dvdnav_still_skip(dvdnav);
      }
      break;
    case DVDNAV_WAIT:
      /* We have reached a point in DVD playback, where timing is critical.
       * Player application with internal fifos can introduce state
       * inconsistencies, because libdvdnav is always the fifo's length
       * ahead in the stream compared to what the application sees.
       * Such applications should wait until their fifos are empty
       * when they receive this type of event. */
      printf("Skipping wait condition\n");
      dvdnav_wait_skip(dvdnav);
      break;
    case DVDNAV_SPU_CLUT_CHANGE:
      /* Player applications should pass the new colour lookup table to their
       * SPU decoder */
      break;
    case DVDNAV_SPU_STREAM_CHANGE:
      /* Player applications should inform their SPU decoder to switch channels */
      break;
    case DVDNAV_AUDIO_STREAM_CHANGE:
      /* Player applications should inform their audio decoder to switch channels */
      break;
    case DVDNAV_HIGHLIGHT:
      /* Player applications should inform their overlay engine to highlight the 
       * given button */
      {
	dvdnav_highlight_event_t *highlight_event = (dvdnav_highlight_event_t *)buf;
	printf("Selected button %d\n", highlight_event->buttonN);
      }
      break;
    case DVDNAV_VTS_CHANGE:
      /* Some status information like video aspect and video scale permissions do
       * not change inside a VTS. Therefore this event can be used to query such
       * information only when necessary and update the decoding/displaying
       * accordingly. */
      break;
    case DVDNAV_CELL_CHANGE:
      /* Some status information like the current Title and Part numbers do not
       * change inside a cell. Therefore this event can be used to query such
       * information only when necessary and update the decoding/displaying
       * accordingly. */
      {
	int tt = 0, ptt = 0, pos, len;
	char input = '\0';
	
	dvdnav_current_title_info(dvdnav, &tt, &ptt);
	dvdnav_get_position(dvdnav, &pos, &len);
	printf("Cell change: Title %d, Chapter %d\n", tt, ptt);
	printf("At position %.0f%% inside the feature\n", 100 * (double)pos / (double)len);

	dump = 0;
	if (tt_dump && tt != tt_dump)
	  tt_dump = 0;

	if (!dump && !tt_dump) {
	  fflush(stdin);
	  while ((input != 'a') && (input != 's') && (input != 'q') && (input != 't')) {
	    printf("(a)ppend cell to output\n(s)kip cell\nappend until end of (t)itle\n(q)uit\n");
	    scanf("%c", &input);
	  }
	  
	  switch (input) {
	  case 'a':
	    dump = 1;
	    break;
	  case 't':
	    tt_dump = tt;
	    break;
	  case 'q':
	    finished = 1;
	  }
	}
      }
      break;
    case DVDNAV_NAV_PACKET:
      /* A NAV packet provides PTS discontinuity information, angle linking information and
       * button definitions for DVD menus. Angles are handled completely inside libdvdnav.
       * For the menus to work, the NAV packet information has to be passed to the overlay
       * engine of the player so that it knows the dimensions of the button areas. */
      {
	pci_t *pci;
	dsi_t *dsi;
	
	/* Applications with fifos should not use these functions to retrieve NAV packets,
	 * they should implement their own NAV handling, because the packet you get from these
	 * functions will already be ahead in the stream which can cause state inconsistencies.
	 * Applications with fifos should therefore pass the NAV packet through the fifo
	 * and decoding pipeline just like any other data. */
	pci = dvdnav_get_current_nav_pci(dvdnav);
	dsi = dvdnav_get_current_nav_dsi(dvdnav);
	
	if(pci->hli.hl_gi.btn_ns > 0) {
	  int button;
	  
	  printf("Found %i DVD menu buttons...\n", pci->hli.hl_gi.btn_ns);

	  for (button = 0; button < pci->hli.hl_gi.btn_ns; button++) {
	    btni_t *btni = &(pci->hli.btnit[button]);
	    printf("Button %i top-left @ (%i,%i), bottom-right @ (%i,%i)\n", 
		    button + 1, btni->x_start, btni->y_start,
		    btni->x_end, btni->y_end);
	  }

	  button = 0;
	  while ((button <= 0) || (button > pci->hli.hl_gi.btn_ns)) {
	    printf("Which button (1 to %i): ", pci->hli.hl_gi.btn_ns);
	    scanf("%i", &button);
	  }

	  printf("Selecting button %i...\n", button);
	  /* This is the point where applications with fifos have to hand in a NAV packet
	   * which has traveled through the fifos. See the notes above. */
	  dvdnav_button_select_and_activate(dvdnav, pci, button);
	}
      }
      break;
    case DVDNAV_HOP_CHANNEL:
      /* This event is issued whenever a non-seamless operation has been executed.
       * Applications with fifos should drop the fifos content to speed up responsiveness. */
      break;
    case DVDNAV_STOP:
      /* Playback should end here. */
      {
	finished = 1;
      }
      break;
    default:
      printf("Unknown event (%i)\n", event);
      finished = 1;
      break;
    }
#if DVD_READ_CACHE
    dvdnav_free_cache_block(dvdnav, buf);
#endif
  }
  
  /* destroy dvdnav handle */
  if (dvdnav_close(dvdnav) != DVDNAV_STATUS_OK) {
    printf("Error on dvdnav_close: %s\n", dvdnav_err_to_string(dvdnav));
    return 5;
  }
  close(output_fd);
  
  return 0;
} 
Exemple #6
0
void k9PlayMPEG2::playTitle() {
    dvdnav_t *dvdnav;
    uint8_t mem[DVD_VIDEO_LB_LEN];
    int finished = 0;
    int32_t tt = 0,ptt=0;
    uint32_t pos, lgr;
    int title=m_title->getnumTitle();


    /* open dvdnav handle */
    if (dvdnav_open(&dvdnav, m_device,m_dvd) != DVDNAV_STATUS_OK) {
        setError("ERR:Error on dvdnav_open\n");
        return ;
    }

    /* set read ahead cache usage */
    if (dvdnav_set_readahead_flag(dvdnav, DVD_READ_CACHE) != DVDNAV_STATUS_OK) {
        setError(QString("ERR:Error on dvdnav_set_readahead_flag: %1\n").arg(dvdnav_err_to_string(dvdnav)));
        return;
    }

    /* set the language */
    if (dvdnav_menu_language_select(dvdnav, DVD_LANGUAGE) != DVDNAV_STATUS_OK ||
            dvdnav_audio_language_select(dvdnav, DVD_LANGUAGE) != DVDNAV_STATUS_OK ||
            dvdnav_spu_language_select(dvdnav, DVD_LANGUAGE) != DVDNAV_STATUS_OK) {
        setError(QString("ERR:Error on setting languages: %1\n").arg(dvdnav_err_to_string(dvdnav)));
        return ;
    }

    /* set the PGC positioning flag to have position information relatively to the
     * whole feature instead of just relatively to the current chapter */
    if (dvdnav_set_PGC_positioning_flag(dvdnav, 1) != DVDNAV_STATUS_OK) {
        setError(QString("ERR:Error on dvdnav_set_PGC_positioning_flag: %1\n").arg(dvdnav_err_to_string(dvdnav)));
        return ;
    }

    int32_t parts;
    dvdnav_get_number_of_parts(dvdnav , title, &parts);
     
    if (m_chapter==0)
    	dvdnav_title_play(dvdnav , title);
    else
        dvdnav_part_play(dvdnav , title,m_chapter);
    /* the read loop which regularly calls dvdnav_get_next_block
     * and handles the returned events */

    while (!finished && !m_stopped && qApp!=NULL) {
        int result, event, len;
        uint8_t *buf = mem;

        if (m_idxLect !=0xFFFFFFFF) {
  	    dvdnav_sector_search(dvdnav, m_idxLect,SEEK_SET);
	    m_idxLect=0xFFFFFFFF;
	}


        /* the main reading function */
#ifdef DVD_READ_CACHE

        result = dvdnav_get_next_cache_block(dvdnav, &buf, &event, &len);
#else

        result = dvdnav_get_next_block(dvdnav, buf, &event, &len);
#endif


        if (result == DVDNAV_STATUS_ERR) {
            setError(QString("ERR:Error getting next block: %1\n").arg(dvdnav_err_to_string(dvdnav)));
            return;
        }

        switch (event) {
        case DVDNAV_NAV_PACKET:
            {
		dvdnav_current_title_info(dvdnav, &tt, &ptt);
		dvdnav_get_position(dvdnav, &pos, &lgr);

		if (tt != title)
			finished=1;
	
		if (finished==0 && buf[17]==0xE0) {
			m_decoder.addData( buf,len);
		}
		if (qApp->tryLock()) {
		   emit setPosition( pos);
		   qApp->unlock();
		}


            }
	    break;
	//removed break --> save
        case DVDNAV_BLOCK_OK:
            /* We have received a regular block of the currently playing MPEG stream.*/
		m_decoder.addData( buf,len);
            break;
        case DVDNAV_NOP:
            /* Nothing to do here. */
            break;
        case DVDNAV_STILL_FRAME:
            /* We have reached a still frame. A real player application would wait
             * the amount of time specified by the still's length while still handling
             * user input to make menus and other interactive stills work.
             * A length of 0xff means an indefinite still which has to be skipped
             * indirectly by some user interaction. */
            {
                dvdnav_still_event_t *still_event = (dvdnav_still_event_t *)buf;
                dvdnav_still_skip(dvdnav);
            }
            break;
        case DVDNAV_WAIT:
            /* We have reached a point in DVD playback, where timing is critical.
             * Player application with internal fifos can introduce state
             * inconsistencies, because libdvdnav is always the fifo's length
             * ahead in the stream compared to what the application sees.
             * Such applications should wait until their fifos are empty
             * when they receive this type of event. */
            dvdnav_wait_skip(dvdnav);
            break;
        case DVDNAV_SPU_CLUT_CHANGE:
            /* Player applications should pass the new colour lookup table to their
             * SPU decoder */
            break;
        case DVDNAV_SPU_STREAM_CHANGE:
            /* Player applications should inform their SPU decoder to switch channels */
            break;
        case DVDNAV_AUDIO_STREAM_CHANGE:
            /* Player applications should inform their audio decoder to switch channels */
            break;
        case DVDNAV_HIGHLIGHT:
            /* Player applications should inform their overlay engine to highlight the
             * given button */
            {
                dvdnav_highlight_event_t *highlight_event = (dvdnav_highlight_event_t *)buf;
            }
            break;
        case DVDNAV_VTS_CHANGE:
            /* Some status information like video aspect and video scale permissions do
             * not change inside a VTS. Therefore this event can be used to query such
             * information only when necessary and update the decoding/displaying
             * accordingly. */
            break;
        case DVDNAV_CELL_CHANGE:
//		dvdnav_get_position(dvdnav, &pos, &lgr);
            break;
        case DVDNAV_HOP_CHANNEL:
            /* This event is issued whenever a non-seamless operation has been executed.
             * Applications with fifos should drop the fifos content to speed up responsiveness. */
            break;
        case DVDNAV_STOP:
            /* Playback should end here. */
            {
                finished = 1;
            }
            break;
        default:
            finished = 1;
            break;
        }

#ifdef DVD_READ_CACHE
        dvdnav_free_cache_block(dvdnav, buf);
#endif

    }
    m_decoder.setNoData();
    /* destroy dvdnav handle */
    dvdnav_close(dvdnav);

}