示例#1
0
static void reset_eof(demuxer_t *demuxer) {
  stream_reset(demuxer->stream);
  demux_flush(demuxer);
  demuxer->video->eof=0;
  demuxer->audio->eof=0;
  demuxer->sub->eof=0;
}
示例#2
0
int demuxer_seek_chapter(demuxer_t *demuxer, int chapter, double *seek_pts)
{
    int ris;

    if (!demuxer->num_chapters || !demuxer->chapters) {
        demux_flush(demuxer);

        ris = stream_control(demuxer->stream, STREAM_CTRL_SEEK_TO_CHAPTER,
                             &chapter);
        if (ris != STREAM_UNSUPPORTED)
            demux_control(demuxer, DEMUXER_CTRL_RESYNC, NULL);

        // exit status may be ok, but main() doesn't have to seek itself
        // (because e.g. dvds depend on sectors, not on pts)
        *seek_pts = -1.0;

        return ris != STREAM_UNSUPPORTED ? chapter : -1;
    } else {  // chapters structure is set in the demuxer
        if (chapter >= demuxer->num_chapters)
            return -1;
        if (chapter < 0)
            chapter = 0;

        *seek_pts = demuxer->chapters[chapter].start / 1e9;

        return chapter;
    }
}
示例#3
0
int demux_seek(demuxer_t *demuxer, float rel_seek_secs, float audio_delay,
               int flags)
{
    if (!demuxer->seekable) {
        if (demuxer->file_format == DEMUXER_TYPE_AVI)
            mp_tmsg(MSGT_SEEK, MSGL_WARN, "Cannot seek in raw AVI streams. (Index required, try with the -idx switch.)\n");
#ifdef CONFIG_TV
        else if (demuxer->file_format == DEMUXER_TYPE_TV)
            mp_tmsg(MSGT_SEEK, MSGL_WARN, "TV input is not seekable! (Seeking will probably be for changing channels ;)\n");
#endif
        else
            mp_tmsg(MSGT_SEEK, MSGL_WARN, "Cannot seek in this file.\n");
        return 0;
    }
    // clear demux buffers:
    demux_flush(demuxer);
    demuxer->video->eof = 0;
    demuxer->audio->eof = 0;
    demuxer->sub->eof = 0;

    /* HACK: assume any demuxer used with these streams can cope with
     * the stream layer suddenly seeking to a different position under it
     * (nothing actually implements DEMUXER_CTRL_RESYNC now).
     */
    struct stream *stream = demuxer->stream;
    if (stream->type == STREAMTYPE_DVD || stream->type == STREAMTYPE_DVDNAV) {
        double pts;

        if (flags & SEEK_ABSOLUTE)
            pts = 0.0f;
        else {
            if (demuxer->stream_pts == MP_NOPTS_VALUE)
                goto dmx_seek;
            pts = demuxer->stream_pts;
        }

        if (flags & SEEK_FACTOR) {
            double tmp = 0;
            if (stream_control(demuxer->stream, STREAM_CTRL_GET_TIME_LENGTH,
                               &tmp) == STREAM_UNSUPPORTED)
                goto dmx_seek;
            pts += tmp * rel_seek_secs;
        } else
            pts += rel_seek_secs;

        if (stream_control(demuxer->stream, STREAM_CTRL_SEEK_TO_TIME, &pts)
            != STREAM_UNSUPPORTED) {
            demux_control(demuxer, DEMUXER_CTRL_RESYNC, NULL);
            return 1;
        }
    }

  dmx_seek:
    if (demuxer->desc->seek)
        demuxer->desc->seek(demuxer, rel_seek_secs, audio_delay, flags);

    return 1;
}
示例#4
0
//returns the first pts found within TIME_STAMP_PROBE_LEN bytes after stream_pos in demuxer's stream.
//if no pts is found or an error occurs, -1.0 is returned.
//Packs are freed.
static float read_first_mpeg_pts_at_position(demuxer_t* demuxer, off_t stream_pos)
{
  stream_t *s = demuxer->stream;
  mpg_demuxer_t *mpg_d = demuxer->priv;
  float pts = -1.0; //the pts to return;
  float found_pts1; //the most recently found pts
  float found_pts2; //the pts found before found_pts1
  float found_pts3; //the pts found before found_pts2
  int found = 0;

  if(!mpg_d || stream_pos < 0)
    return pts;

  found_pts3 = found_pts2 = found_pts1 = mpg_d->last_pts;
  stream_seek(s, stream_pos);

  //We look for pts.
  //However, we do not stop at the first found one, as timestamps may reset
  //Therefore, we seek until we found three consecutive
  //pts within MAX_PTS_DIFF_FOR_CONSECUTIVE.

  while(found<3 && !s->eof
   && (fabsf(found_pts2-found_pts1) < MAX_PTS_DIFF_FOR_CONSECUTIVE)
   && (fabsf(found_pts3-found_pts2) < MAX_PTS_DIFF_FOR_CONSECUTIVE)
   && (stream_tell(s) < stream_pos + TIMESTAMP_PROBE_LEN)
   && ds_fill_buffer(demuxer->video))
  {
    if(mpg_d->last_pts != found_pts1)
    {
      if(!found)
        found_pts3 = found_pts2 = found_pts1 = mpg_d->last_pts; //the most recently found pts
      else
      {
        found_pts3 = found_pts2;
        found_pts2 = found_pts1;
        found_pts1 = mpg_d->last_pts;
      }
      found++;
    }
  }

  if(found == 3) pts = found_pts3;

  //clean up from searching of first pts;
  demux_flush(demuxer);

  return pts;
}
示例#5
0
int demuxer_set_angle(demuxer_t *demuxer, int angle)
{
    int ris, angles = -1;

    angles = demuxer_angles_count(demuxer);
    if ((angles < 1) || (angle > angles))
        return -1;

    demux_flush(demuxer);

    ris = stream_control(demuxer->stream, STREAM_CTRL_SET_ANGLE, &angle);
    if (ris == STREAM_UNSUPPORTED)
        return -1;

    demux_control(demuxer, DEMUXER_CTRL_RESYNC, NULL);

    return angle;
}
示例#6
0
文件: demux_disc.c 项目: bagobor/mpv
static int d_control(demuxer_t *demuxer, int cmd, void *arg)
{
    struct priv *p = demuxer->priv;

    switch (cmd) {
    case DEMUXER_CTRL_GET_TIME_LENGTH: {
        double len;
        if (stream_control(demuxer->stream, STREAM_CTRL_GET_TIME_LENGTH, &len) < 1)
            break;
        *(double *)arg = len;
        return DEMUXER_CTRL_OK;
    }
    case DEMUXER_CTRL_RESYNC:
        demux_flush(p->slave);
        break; // relay to slave demuxer
    case DEMUXER_CTRL_SWITCHED_TRACKS:
        reselect_streams(demuxer);
        return DEMUXER_CTRL_OK;
    }
    return demux_control(p->slave, cmd, arg);
}
示例#7
0
文件: demux_disc.c 项目: feihugis/mpv
static int d_open(demuxer_t *demuxer, enum demux_check check)
{
    struct priv *p = demuxer->priv = talloc_zero(demuxer, struct priv);

    if (check != DEMUX_CHECK_FORCE)
        return -1;

    struct demuxer_params params = {.force_format = "+lavf"};

    if (demuxer->stream->uncached_type == STREAMTYPE_CDDA)
        params.force_format = "+rawaudio";

    char *t = NULL;
    stream_control(demuxer->stream, STREAM_CTRL_GET_DISC_NAME, &t);
    if (t) {
        mp_tags_set_str(demuxer->metadata, "TITLE", t);
        talloc_free(t);
    }

    // Initialize the playback time. We need to read _some_ data to get the
    // correct stream-layer time (at least with libdvdnav).
    stream_peek(demuxer->stream, 1);
    reset_pts(demuxer);

    p->slave = demux_open(demuxer->stream, &params, demuxer->global);
    if (!p->slave)
        return -1;

    // So that we don't miss initial packets of delayed subtitle streams.
    demux_set_stream_autoselect(p->slave, true);

    // With cache enabled, the stream can be seekable. This causes demux_lavf.c
    // (actually libavformat/mpegts.c) to seek sometimes when reading a packet.
    // It does this to seek back a bit in case the current file position points
    // into the middle of a packet.
    if (demuxer->stream->uncached_type != STREAMTYPE_CDDA) {
        demuxer->stream->seekable = false;

        // Can be seekable even if the stream isn't.
        demuxer->seekable = true;

        demuxer->rel_seeks = true;
    }

    add_dvd_streams(demuxer);
    add_streams(demuxer);
    add_stream_chapters(demuxer);

    return 0;
}

static void d_close(demuxer_t *demuxer)
{
    struct priv *p = demuxer->priv;
    free_demuxer(p->slave);
}

static int d_control(demuxer_t *demuxer, int cmd, void *arg)
{
    struct priv *p = demuxer->priv;

    switch (cmd) {
    case DEMUXER_CTRL_GET_TIME_LENGTH: {
        double len;
        if (stream_control(demuxer->stream, STREAM_CTRL_GET_TIME_LENGTH, &len) < 1)
            break;
        *(double *)arg = len;
        return DEMUXER_CTRL_OK;
    }
    case DEMUXER_CTRL_RESYNC:
        demux_flush(p->slave);
        break; // relay to slave demuxer
    case DEMUXER_CTRL_SWITCHED_TRACKS:
        reselect_streams(demuxer);
        return DEMUXER_CTRL_OK;
    }
    return demux_control(p->slave, cmd, arg);
}

const demuxer_desc_t demuxer_desc_disc = {
    .name = "disc",
    .desc = "CD/DVD/BD wrapper",
    .fill_buffer = d_fill_buffer,
    .open = d_open,
    .close = d_close,
    .seek = d_seek,
    .control = d_control,
};
示例#8
0
文件: video.c 项目: cgbarnwell/mvpmc
void
video_callback(mvp_widget_t *widget, char key)
{
	int jump;
	long long offset, size;
	pts_sync_data_t async, vsync;
	av_state_t state;

	/*
	printf("**SSDEBUG: In video_callback and got key %d \n",key);
	*/

	if (!video_playing)
		return;

	if(showing_guide) {
		if(mvp_tvguide_callback(widget, key) == 1)
			return;
		}

	if ( video_functions->key != NULL ) {
		if ( video_functions->key(key) == 1 ) {
			return;
		}
	}

	switch (key) {
	case MVPW_KEY_GO:
	case MVPW_KEY_GUIDE:
		if(showing_guide == 0 && showing_guide == 0) {
			printf("In %s showing guide %d \n",__FUNCTION__, key);
			showing_guide = 1;
			mvp_tvguide_video_topright(1);
			mvp_tvguide_show(mythtv_livetv_program_list, mythtv_livetv_description,
											 mythtv_livetv_clock);
			break;
		}
	/* if the guide button is pressed while guide is active fall through to go back to remove guide and return to TV */
	case MVPW_KEY_TV:
		if(showing_guide == 1) {
			printf("In %s hiding guide %d \n", __FUNCTION__, key);
			showing_guide = 0;
			mvp_tvguide_video_topright(0);
			mvp_tvguide_hide(mythtv_livetv_program_list, mythtv_livetv_description,
											 mythtv_livetv_clock);
		}
		break;
	case MVPW_KEY_STOP:
	case MVPW_KEY_EXIT:
		back_to_guide_menu();
		new_live_tv = 0;
		break;
		
	case MVPW_KEY_PAUSE:
		if (av_pause()) {
			mvpw_show(pause_widget);
			mvpw_hide(ffwd_widget);
			paused = 1;
			if (pause_osd && !display_on && (display_on_alt < 2)) {
				display_on_alt = 2;
				enable_osd();
			}
			screensaver_enable();
		} else {
			if (pause_osd && !display_on &&
			    (display_on_alt == 2)) {
				display_on_alt = 0;
				disable_osd();
				mvpw_expose(root);
			}
			av_get_state(&state);
			if (state.mute)
				mvpw_show(mute_widget);
			else
				mvpw_hide(mute_widget);
			mvpw_hide(pause_widget);
			paused = 0;
			screensaver_disable();
		}
		break;
	case MVPW_KEY_PLAY:
		if ( paused ) {
			/*
			 * play key can be used to un-pause
			 */
			av_pause();
			if (pause_osd && !display_on &&
			    (display_on_alt == 2)) {
				display_on_alt = 0;
				disable_osd();
				mvpw_expose(root);
			}
			mvpw_hide(pause_widget);
			mvpw_hide(mute_widget);
			paused = 0;
			screensaver_disable();
		}
		break;
	case MVPW_KEY_REPLAY:
		seek_by(-30);
		timed_osd(seek_osd_timeout*1000);
		break;
	case MVPW_KEY_REWIND:
		seek_by(-10);
		timed_osd(seek_osd_timeout*1000);
		break;
	case MVPW_KEY_SKIP:
		if (mythtv_seek_amount == 0 ) {
			seek_by(30);
		}
		else if (mythtv_seek_amount == 1 ) {
			seek_by(60);
		}
		else {
			seek_by(30);
		}
		timed_osd(seek_osd_timeout*1000);
		break;
	case MVPW_KEY_FFWD:
		if (av_ffwd() == 0) {
			demux_flush(handle);
			demux_seek(handle);
			av_get_state(&state);
			av_stop();
			av_reset();
			if (state.mute) {
				av_set_mute(1);
			}
			av_play();
			mvpw_hide(ffwd_widget);
		} else {
			av_get_state(&state);
			mvpw_show(ffwd_widget);
			mvpw_hide(pause_widget);
			screensaver_disable();
		}
		timed_osd(seek_osd_timeout*1000);
		break;
	case MVPW_KEY_LEFT:
		if (video_functions->seek) {
			size = video_functions->size();
			jump_target = -1;
			jumping = 1;
                        if (video_write_thread) {
                            pthread_kill(video_write_thread, SIGURG);
                        }
                        if (audio_write_thread) {
                            pthread_kill(audio_write_thread, SIGURG);
                        }
			offset = video_functions->seek(0, SEEK_CUR);
			jump_target = ((-size / 100.0) + offset);
			pthread_cond_broadcast(&video_cond);
		}
		break;
	case MVPW_KEY_RIGHT:
		if (video_functions->seek) {
			size = video_functions->size();
			jump_target = -1;
			jumping = 1;
                        if (video_write_thread) {
                            pthread_kill(video_write_thread, SIGURG);
                        }
                        if (audio_write_thread) {
                            pthread_kill(audio_write_thread, SIGURG);
                        }
			offset = video_functions->seek(0, SEEK_CUR);
			jump_target = ((size / 100.0) + offset);
			pthread_cond_broadcast(&video_cond);
			timed_osd(seek_osd_timeout*1000);
		}
		break;
	case MVPW_KEY_ZERO ... MVPW_KEY_NINE:
		if(new_live_tv) {
			printf("In %s showing guide %d \n",__FUNCTION__, key);
			showing_guide = 1;
			mvp_tvguide_video_topright(1);
			mvp_tvguide_show(mythtv_livetv_program_list, mythtv_livetv_description,
											 mythtv_livetv_clock);
			mvp_tvguide_callback(widget, key);
		}
		else if (mythtv_livetv) {
			back_to_guide_menu();
			mythtv_key_callback(mythtv_browser,  key);
		}
		else {
			size = video_functions->size();
			jump_target = -1;
			jumping = 1;
                        if (video_write_thread) {
                            pthread_kill(video_write_thread, SIGURG);
                        }
                        if (audio_write_thread) {
                            pthread_kill(audio_write_thread, SIGURG);
                        }
			jump = key;
			jump_target = size * (jump / 10.0);
			pthread_cond_broadcast(&video_cond);
			timed_osd(seek_osd_timeout*1000);
		}
		break;
	case MVPW_KEY_MENU:
		mvpw_show(popup_menu);
		mvpw_focus(popup_menu);
		break;
	case MVPW_KEY_MUTE:
		if (mvpw_visible(ffwd_widget)) {
			mvpw_hide(mute_widget);
			break;
		}
		if (av_mute() == 1) {
			mvpw_show(mute_widget);
		} else {
			mvpw_hide(mute_widget);
		}
		break;
	case MVPW_KEY_BLANK:
	case MVPW_KEY_OK:
		if (display_on || display_on_alt) {
			disable_osd();
			mvpw_expose(root);
			display_on = 1;
			display_on_alt = 0;
		} else {
			enable_osd();
		}
		display_on = !display_on;
		break;
	case MVPW_KEY_FULL:
	case MVPW_KEY_PREV_CHAN:
		if(IS_4x3(av_get_tv_aspect())) {
			if(av_get_tv_aspect() == AV_TV_ASPECT_4x3_CCO)
				av_set_tv_aspect(AV_TV_ASPECT_4x3);
			else
				av_set_tv_aspect(AV_TV_ASPECT_4x3_CCO);
		}
		break;
	case MVPW_KEY_CHAN_UP:
	case MVPW_KEY_UP:
		if (mythtv_livetv)
			mythtv_channel_up();
		break;
	case MVPW_KEY_CHAN_DOWN:
	case MVPW_KEY_DOWN:
		if (mythtv_livetv)
			mythtv_channel_down();
		break;
	case MVPW_KEY_RECORD:
		/*
		 * XXX: This is a temporary hack until we figure out how
		 *      to tell when the audio and video are out of sync,
		 *      and correct it automatically.
		 */
		av_get_audio_sync(&async);
		av_get_video_sync(&vsync);
		printf("PRE  SYNC:  a 0x%"PRIx64" 0x%"PRIx64"  v 0x%"PRIx64" 0x%"PRIx64"\n",
		       async.stc, async.pts, vsync.stc, vsync.pts);
		av_delay_video(1000);
		av_get_audio_sync(&async);
		av_get_video_sync(&vsync);
		printf("POST SYNC:  a 0x%"PRIx64" 0x%"PRIx64"  v 0x%"PRIx64" 0x%"PRIx64"\n",
		       async.stc, async.pts, vsync.stc, vsync.pts);
		break;
	case MVPW_KEY_VOL_UP:
	case MVPW_KEY_VOL_DOWN:
		volume_key_callback(volume_dialog, key);
		mvpw_show(volume_dialog);
		mvpw_set_timer(volume_dialog, timer_hide, 3000);
		break;
	default:
		PRINTF("button %d\n", key);
		break;
	}
}
示例#9
0
文件: video.c 项目: cgbarnwell/mvpmc
static int
do_seek(void)
{
	demux_attr_t *attr;
	int seconds, new_seek_Bps;
	long long offset;
	struct timeval now, delta;
	static int count = 0;

	count++;

	attr = demux_get_attr(handle);
	gettimeofday(&now, NULL);
	timersub(&now, &seek_timeval, &delta);

	/*
	 * Give up after 2 seconds
	 */
	if ((delta.tv_sec >= 2) && seeking) {
		seeking = 0;
		printf("SEEK ABORTED (%lu.%.2lu) %d\n",
		       delta.tv_sec, delta.tv_usec/10000, count);
		count = 0;

		return 0;
	}

	if (!attr->gop_valid) {
		if ( --seek_attempts > 0 ) {
			PRINTF("GOP retry\n");
			return -1;
		}
		printf("SEEK RETRY due to lack of GOP\n");
		demux_flush(handle);
		demux_seek(handle);
		seek_attempts = 16;
		return -1;
	}

	if (pts_seek_attempts > 0) {
		seconds = attr->gop.pts/PTS_HZ;
	} else if (gop_seek_attempts > 0) {
		seconds = (attr->gop.hour * 3600) +
			(attr->gop.minute * 60) + attr->gop.second;
	} else {
		seconds = 0;
	}

	/*
	 * Recompute Bps from actual time and position differences
	 * provided the time difference is big enough
	 */
	if ( abs(seconds - seek_start_seconds) > SEEK_FUDGE ) {
		offset = video_functions->seek(0, SEEK_CUR);
		new_seek_Bps = (offset - seek_start_pos) /
			(seconds - seek_start_seconds);
		if ( new_seek_Bps > 10000 ) /* Sanity check */
			seek_Bps = new_seek_Bps;
	}

	PRINTF("New Bps %d\n", seek_Bps);
	
	if ( abs(seconds - seek_seconds) <= SEEK_FUDGE ) {
		seeking = 0;
		printf("SEEK DONE: to %d at %d (%lu.%.2lu) %d\n",
		       seek_seconds, seconds,
		       delta.tv_sec, delta.tv_usec/10000, count);
	} else {
		offset = video_functions->seek(0, SEEK_CUR);
		PRINTF("RESEEK: From %lld + %d\n", offset,
		       seek_Bps * (seek_seconds-seconds));
		offset = video_functions->seek(seek_Bps * (seek_seconds-seconds), SEEK_CUR);
		demux_flush(handle);
		demux_seek(handle);
		seek_attempts--;
		PRINTF("SEEKING 1: %d/%d %lld\n",
		       seconds, seek_seconds, offset);
		return -1;
	}

	count = 0;

	return 0;
}