예제 #1
0
static void demux_demuxers_seek(demuxer_t *demuxer,float rel_seek_secs,float audio_delay,int flags) {
  dd_priv_t* priv;
  float pos;
  priv=demuxer->priv;

  priv->ad->stream->eof = 0;
  priv->sd->stream->eof = 0;

  // Seek video
  demux_seek(priv->vd,rel_seek_secs,audio_delay,flags);
  // Get the new pos
  pos = demuxer->video->pts;
  if (!pos) {
    demux_fill_buffer(priv->vd, demuxer->video);
    if (demuxer->video->first)
      pos = demuxer->video->first->pts;
  }

  if(priv->ad != priv->vd && demuxer->audio->sh) {
    sh_audio_t* sh = demuxer->audio->sh;
    demux_seek(priv->ad,pos,audio_delay,1);
    // In case the demuxer don't set pts
    if(!demuxer->audio->pts)
      demuxer->audio->pts = pos-((ds_tell_pts(demuxer->audio)-sh->a_in_buffer_len)/(float)sh->i_bps);
  }

  if(priv->sd != priv->vd)
      demux_seek(priv->sd,pos,audio_delay,1);

}
예제 #2
0
파일: sub.c 프로젝트: htc550605125/mpv
static void reinit_subdec(struct MPContext *mpctx, struct track *track,
                          struct dec_sub *dec_sub)
{
    struct MPOpts *opts = mpctx->opts;

    if (sub_is_initialized(dec_sub))
        return;

    struct sh_video *sh_video =
        mpctx->d_video ? mpctx->d_video->header->video : NULL;
    int w = sh_video ? sh_video->disp_w : 0;
    int h = sh_video ? sh_video->disp_h : 0;
    float fps = sh_video ? sh_video->fps : 25;

    init_sub_renderer(mpctx);

    sub_set_video_res(dec_sub, w, h);
    sub_set_video_fps(dec_sub, fps);
    sub_set_ass_renderer(dec_sub, mpctx->ass_library, mpctx->ass_renderer,
                         &mpctx->ass_lock);
    sub_init_from_sh(dec_sub, track->stream);

    // Don't do this if the file has video/audio streams. Don't do it even
    // if it has only sub streams, because reading packets will change the
    // demuxer position.
    if (!track->preloaded && track->is_external && !opts->sub_clear_on_seek) {
        demux_seek(track->demuxer, 0, SEEK_ABSOLUTE);
        track->preloaded = sub_read_all_packets(dec_sub, track->stream);
        if (track->preloaded)
            demux_stop_thread(track->demuxer);
    }
}
static void demux_demuxers_seek(demuxer_t *demuxer,float rel_seek_secs,float audio_delay,int flags) {
  dd_priv_t* priv;
  float pos;
  priv=demuxer->priv;

  priv->ad->stream->eof = 0;
  priv->sd->stream->eof = 0;

  // Seek video
  demux_seek(priv->vd,rel_seek_secs,audio_delay,flags);
  // Get the new pos
  pos = demuxer->video->pts;
  if (!pos) {
    // since the video demuxer might provide multiple
    // streams (e.g. subs) we might have to call
    // demux_fill_buffer multiple times.
    int limit = 10;
    do {
      demux_fill_buffer(priv->vd, demuxer->video);
    } while (--limit && !demuxer->video->first);
    if (demuxer->video->first)
      pos = demuxer->video->first->pts;
  }

  if(priv->ad != priv->vd && demuxer->audio->sh) {
    sh_audio_t* sh = demuxer->audio->sh;
    demux_seek(priv->ad,pos,audio_delay,1);
    // In case the demuxer don't set pts
    if(!demuxer->audio->pts)
      demuxer->audio->pts = pos-((ds_tell_pts(demuxer->audio)-sh->a_in_buffer_len)/(float)sh->i_bps);
  }

  if(priv->sd != priv->vd)
      demux_seek(priv->sd,pos,audio_delay,1);

}
예제 #4
0
파일: demux_disc.c 프로젝트: feihugis/mpv
static void get_disc_lang(struct stream *stream, struct sh_stream *sh)
{
    struct stream_lang_req req = {.type = sh->type, .id = sh->demuxer_id};
    if (stream->uncached_type == STREAMTYPE_DVD && sh->type == STREAM_SUB)
        req.id = req.id & 0x1F; // mpeg ID to index
    stream_control(stream, STREAM_CTRL_GET_LANG, &req);
    if (req.name[0])
        sh->lang = talloc_strdup(sh, req.name);
}

static void add_dvd_streams(demuxer_t *demuxer)
{
    struct priv *p = demuxer->priv;
    struct stream *stream = demuxer->stream;
    if (stream->uncached_type != STREAMTYPE_DVD)
        return;
    struct stream_dvd_info_req info;
    if (stream_control(stream, STREAM_CTRL_GET_DVD_INFO, &info) > 0) {
        for (int n = 0; n < MPMIN(32, info.num_subs); n++) {
            struct sh_stream *sh = demux_alloc_sh_stream(STREAM_SUB);
            sh->demuxer_id = n + 0x20;
            sh->codec->codec = "dvd_subtitle";
            get_disc_lang(stream, sh);
            // p->streams _must_ match with p->slave->streams, so we can't add
            // it yet - it has to be done when the real stream appears, which
            // could be right on start, or any time later.
            p->dvd_subs[n] = sh;

            // emulate the extradata
            struct mp_csp_params csp = MP_CSP_PARAMS_DEFAULTS;
            struct mp_cmat cmatrix;
            mp_get_csp_matrix(&csp, &cmatrix);

            char *s = talloc_strdup(sh, "");
            s = talloc_asprintf_append(s, "palette: ");
            for (int i = 0; i < 16; i++) {
                int color = info.palette[i];
                int y[3] = {(color >> 16) & 0xff, (color >> 8) & 0xff, color & 0xff};
                int c[3];
                mp_map_fixp_color(&cmatrix, 8, y, 8, c);
                color = (c[2] << 16) | (c[1] << 8) | c[0];

                if (i != 0)
                    s = talloc_asprintf_append(s, ", ");
                s = talloc_asprintf_append(s, "%06x", color);
            }
            s = talloc_asprintf_append(s, "\n");

            sh->codec->extradata = s;
            sh->codec->extradata_size = strlen(s);

            demux_add_sh_stream(demuxer, sh);
        }
    }
}

static void add_streams(demuxer_t *demuxer)
{
    struct priv *p = demuxer->priv;

    for (int n = p->num_streams; n < demux_get_num_stream(p->slave); n++) {
        struct sh_stream *src = demux_get_stream(p->slave, n);
        if (src->type == STREAM_SUB) {
            struct sh_stream *sub = NULL;
            if (src->demuxer_id >= 0x20 && src->demuxer_id <= 0x3F)
                sub = p->dvd_subs[src->demuxer_id - 0x20];
            if (sub) {
                assert(p->num_streams == n); // directly mapped
                MP_TARRAY_APPEND(p, p->streams, p->num_streams, sub);
                continue;
            }
        }
        struct sh_stream *sh = demux_alloc_sh_stream(src->type);
        assert(p->num_streams == n); // directly mapped
        MP_TARRAY_APPEND(p, p->streams, p->num_streams, sh);
        // Copy all stream fields that might be relevant
        *sh->codec = *src->codec;
        sh->demuxer_id = src->demuxer_id;
        if (src->type == STREAM_VIDEO) {
            double ar;
            if (stream_control(demuxer->stream, STREAM_CTRL_GET_ASPECT_RATIO, &ar)
                                == STREAM_OK)
            {
                struct mp_image_params f = {.w = src->codec->disp_w,
                                            .h = src->codec->disp_h};
                mp_image_params_set_dsize(&f, 1728 * ar, 1728);
                sh->codec->par_w = f.p_w;
                sh->codec->par_h = f.p_h;
            }
        }
        get_disc_lang(demuxer->stream, sh);
        demux_add_sh_stream(demuxer, sh);
    }
    reselect_streams(demuxer);
}

static void d_seek(demuxer_t *demuxer, double rel_seek_secs, int flags)
{
    struct priv *p = demuxer->priv;

    if (demuxer->stream->uncached_type == STREAMTYPE_CDDA) {
        demux_seek(p->slave, rel_seek_secs, flags);
        return;
    }

    double pts = p->seek_pts;
    if (flags & SEEK_ABSOLUTE)
        pts = 0.0f;
    double base_pts = pts; // to what pts is relative

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

    MP_VERBOSE(demuxer, "seek to: %f\n", pts);

    double seek_arg[] = {pts, base_pts, flags};
    stream_control(demuxer->stream, STREAM_CTRL_SEEK_TO_TIME, seek_arg);
    demux_control(p->slave, DEMUXER_CTRL_RESYNC, NULL);

    p->seek_pts = pts;
    p->seek_reinit = true;
}

static void reset_pts(demuxer_t *demuxer)
{
    struct priv *p = demuxer->priv;

    double base;
    if (stream_control(demuxer->stream, STREAM_CTRL_GET_CURRENT_TIME, &base) < 1)
        base = 0;

    MP_VERBOSE(demuxer, "reset to time: %f\n", base);

    p->base_dts = p->last_dts = MP_NOPTS_VALUE;
    p->base_time = base;
    p->seek_reinit = false;
}

static int d_fill_buffer(demuxer_t *demuxer)
{
    struct priv *p = demuxer->priv;

    struct demux_packet *pkt = demux_read_any_packet(p->slave);
    if (!pkt)
        return 0;

    demux_update(p->slave);

    if (p->seek_reinit)
        reset_pts(demuxer);

    add_streams(demuxer);
    if (pkt->stream >= p->num_streams) { // out of memory?
        talloc_free(pkt);
        return 0;
    }

    struct sh_stream *sh = p->streams[pkt->stream];
    if (!demux_stream_is_selected(sh)) {
        talloc_free(pkt);
        return 1;
    }

    if (demuxer->stream->uncached_type == STREAMTYPE_CDDA) {
        demux_add_packet(sh, pkt);
        return 1;
    }

    MP_TRACE(demuxer, "ipts: %d %f %f\n", sh->type, pkt->pts, pkt->dts);

    if (sh->type == STREAM_SUB) {
        if (p->base_dts == MP_NOPTS_VALUE)
            MP_WARN(demuxer, "subtitle packet along PTS reset\n");
    } else if (pkt->dts != MP_NOPTS_VALUE) {
        // Use the very first DTS to rebase the start time of the MPEG stream
        // to the playback time.
        if (p->base_dts == MP_NOPTS_VALUE)
            p->base_dts = pkt->dts;

        if (p->last_dts == MP_NOPTS_VALUE)
            p->last_dts = pkt->dts;

        if (fabs(p->last_dts - pkt->dts) >= DTS_RESET_THRESHOLD) {
            MP_WARN(demuxer, "PTS discontinuity: %f->%f\n", p->last_dts, pkt->dts);
            p->base_time += p->last_dts - p->base_dts;
            p->base_dts = pkt->dts - pkt->duration;
        }
        p->last_dts = pkt->dts;
    }

    if (p->base_dts != MP_NOPTS_VALUE) {
        double delta = -p->base_dts + p->base_time;
        if (pkt->pts != MP_NOPTS_VALUE)
            pkt->pts += delta;
        if (pkt->dts != MP_NOPTS_VALUE)
            pkt->dts += delta;
    }

    MP_TRACE(demuxer, "opts: %d %f %f\n", sh->type, pkt->pts, pkt->dts);

    if (pkt->pts != MP_NOPTS_VALUE)
        p->seek_pts = pkt->pts;

    demux_add_packet(sh, pkt);
    return 1;
}

static void add_stream_chapters(struct demuxer *demuxer)
{
    int num = 0;
    if (stream_control(demuxer->stream, STREAM_CTRL_GET_NUM_CHAPTERS, &num) < 1)
        return;
    for (int n = 0; n < num; n++) {
        double p = n;
        if (stream_control(demuxer->stream, STREAM_CTRL_GET_CHAPTER_TIME, &p) < 1)
            continue;
        demuxer_add_chapter(demuxer, "", p, 0);
    }
}
예제 #5
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;
	}
}
예제 #6
0
파일: video.c 프로젝트: cgbarnwell/mvpmc
void*
video_read_start(void *arg)
{
	pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
	int ret;
	int n = 0, len = 0, reset = 1;
	int sent_idle_notify;
	demux_attr_t *attr;
	video_info_t *vi;
	int set_aspect = 1;
	char *inbuf = inbuf_static;
	char *tsbuf;
	int tslen;
	int tsmode = TS_MODE_UNKNOWN;
	av_state_t state;

	pthread_mutex_lock(&mutex);

	printf("mpeg read thread started (pid %d)\n", getpid());
	pthread_cond_wait(&video_cond, &mutex);

	while (1) {
		sent_idle_notify = 0;
		while (!video_playing) {
			demux_reset(handle);
			ts_demux_reset(tshandle);
			demux_seek(handle);
			vid_event_discontinuity_possible();
			if ( !(sent_idle_notify) ) {
				if ( video_functions != NULL &&
				     video_functions->notify != NULL ) {
					video_functions->notify(MVP_READ_THREAD_IDLE);
				}
				printf("mpeg read thread sleeping...\n");
				sent_idle_notify = 1;
			}
			pthread_cond_wait(&video_cond, &mutex);
			TRC("%s: past pthread_cond_wait(&video_cond, &mutex)\n", __FUNCTION__);
		}

#ifdef STREAM_TEST
		if ( stream_test_started == 0 ) {
			stream_test_started = 1;
			//Get start time
			gettimeofday(&start_tv, NULL);
		}
#endif

		if (video_reopen) {
		        vid_event_clear();
			if (video_functions->open() == 0) {
				/* Jump to the start of the new file */
				jump_target = 0;
				jumping = 1;
				video_reopen = 0;
				tsmode = TS_MODE_UNKNOWN;
			} else {
				fprintf(stderr, "video open failed!\n");
				video_playing = 0;
				continue;
			}
			len = 0;
			reset = 1;
			set_aspect = 1;
		}

		if ((seeking && reset) || jumping) {
			demux_reset(handle);
			ts_demux_reset(tshandle);
			demux_seek(handle);
			av_get_state(&state);
			av_reset();
			av_reset_stc();
			vid_event_discontinuity_possible();
			if (seeking)
				reset = 0;
			if (state.mute)
				av_set_mute(1);
			if (paused) {
				av_play();
				paused = 0;
				mvpw_hide(pause_widget);
				screensaver_disable();
			}
			pcm_decoded = 0;
			ac3len = 0;
			len = 0;
			if (jumping) {
				while (jump_target < 0)
					usleep(1000);
				video_functions->seek(jump_target, SEEK_SET);
			}
			jumping = 0;
		}

		if ( !video_playing ) {
			continue;
		}

		if (len == 0) {

			if ( video_functions->read_dynb != NULL ){
				tslen = video_functions->read_dynb(&tsbuf, 1024 * 256);
			}
			else {
				tsbuf = tsbuf_static;
				do {
					tslen = video_functions->read(tsbuf,
						      sizeof(tsbuf_static));
				} while ( tslen==-1 && errno==EAGAIN);
			}
			thruput_count += tslen;
			inbuf = inbuf_static;

			if (tsmode == TS_MODE_UNKNOWN) {
				if (tslen > 0) {
					tsmode = ts_demux_is_ts(tshandle, tsbuf, tslen);
					printf("auto detection transport stream returned %d\n", tsmode);
					if (tsmode == TS_MODE_NO)
						len = tslen;
			    	}
			} else if (tsmode == TS_MODE_NO) {
				len = tslen;
			} else {
				len = ts_demux_transform(tshandle, tsbuf, tslen, inbuf, sizeof(inbuf_static));
				int resyncs = ts_demux_resync_count(tshandle);
				if (resyncs > 50) {
					printf("resync count = %d, switch back to unknown mode\n", resyncs);
					tsmode = TS_MODE_UNKNOWN;
					ts_demux_reset(tshandle);
				}
			}
			n = 0;
			if (len == 0 && playlist ) {
				video_reopen = 2;
				playlist_next();
			}
		}

		if ( !video_playing ) {
			continue;
		}

#ifdef STREAM_TEST
		stream_test_cnt += len;
		len = 0;

		if ( stream_test_cnt > 1024*1024*20 ) {
			unsigned int delta_ms;

			gettimeofday(&done_tv, NULL);
			if ( done_tv.tv_usec < start_tv.tv_usec ) {
				done_tv.tv_usec += 1000000;
				done_tv.tv_sec	 -= 1;
			}
			delta_ms = (done_tv.tv_sec - start_tv.tv_sec) * 1000;
			delta_ms += (done_tv.tv_usec - start_tv.tv_usec) / 1000;
			printf("Test Done\n");
			printf("Bytes transferred: %u\n", stream_test_cnt);
			printf("Elapsed time %u mS\n", delta_ms);
			while ( 1 ) {
				sleep(10);
				printf("Test Done....\n");
			}
		}
		continue;
#else
		if (tsmode == TS_MODE_YES)
			ret = DEMUX_PUT(handle, inbuf+n, len-n);
		else
			ret = DEMUX_PUT(handle, tsbuf+n, len-n);
#endif

		if ((ret <= 0) && (!seeking)) {
			pthread_cond_broadcast(&video_cond);
			usleep(1000);
			continue;
		}

		if (seeking) { 
			if (do_seek()) {
				len = 0;
				continue;
			} else {
				reset = 1;
			}
		}

		n += ret;
		if (n == len)
			len = 0;

		pthread_cond_broadcast(&video_cond);

		attr = demux_get_attr(handle);
		vi = &attr->video.stats.info.video;
		if (attr->audio.type != audio_type) {
			audio_type = attr->audio.type;
			switch (audio_type) {
			case AUDIO_MODE_AC3:
				if (audio_output_mode == AUD_OUTPUT_PASSTHRU ) {
					if (av_set_audio_output(AV_AUDIO_AC3) < 0) {
						/* revert to downmixing */
						audio_output_mode = AUD_OUTPUT_STEREO;
					    // fall through to PCM
					} else {
                                    // don't set audio_type
						audio_output = AV_AUDIO_AC3;
						printf("switch to AC3 Passthru\n");
						break;
					}
				}
			case AUDIO_MODE_PCM:
				audio_output = AV_AUDIO_PCM;
				printf("switch to PCM audio output device\n");
				break;
			default:
				av_set_audio_type(audio_type);
				audio_output = AV_AUDIO_MPEG;
				printf("switch to MPEG audio output device\n");
				break;
			}
			av_set_audio_output(audio_output);
		} else {
			if (audio_type==AUDIO_MODE_AC3){
				sync_ac3_audio();
			}
		}

	} //while

	return NULL;
}
예제 #7
0
파일: video.c 프로젝트: cgbarnwell/mvpmc
int
file_open(void)
{
	seeking = 1;
	audio_selected = 0;
	audio_checks = 0;

	if ( http_playing == HTTP_FILE_CLOSED ) {
		if (video_reopen == 1)
			audio_clear();
		
		close(fd);
		fd = -1;
	}

        if (video_write_thread) {
            pthread_kill(video_write_thread, SIGURG);
        }
        if (audio_write_thread) {
            pthread_kill(audio_write_thread, SIGURG);
        }

	if ( http_playing == HTTP_FILE_CLOSED ) {
		if (gui_state != MVPMC_STATE_EMULATE) {
			fd=open(current, O_RDONLY|O_LARGEFILE);
		} else {
			fd = open("/tmp/FIFO", O_RDONLY);
		}
		if (fd < 0) {
			printf("Open failed errno %d file %s\n",
			       errno, current);
			video_reopen = 0;
			return -1;
		}
		printf("opened %s\n", current);
	} else {
		printf("http opened %s\n", current);
	}

	if (video_reopen == 1) {
		av_set_audio_output(AV_AUDIO_MPEG);
		fd_audio = av_get_audio_fd();

		av_play();

		demux_reset(handle);
		ts_demux_reset(tshandle);
		demux_attr_reset(handle);
		demux_seek(handle);
		vid_event_discontinuity_possible();
		if (gui_state == MVPMC_STATE_EMULATE || http_playing == HTTP_VIDEO_FILE_MPG) {
			video_thumbnail(AV_THUMBNAIL_OFF, 0);
		} else {
			video_thumbnail(AV_THUMBNAIL_EIGTH, 0);
		}
		av_play();
	}

	zoomed = 0;
	display_on = 0;

	seeking = 0;
	jumping = 0;
	audio_type = 0;
	pcm_decoded = 0;
	ac3len = 0;

	video_reopen = 0;

	pthread_cond_broadcast(&video_cond);

	printf("write threads released\n");

	return 0;
}
예제 #8
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;
}
예제 #9
0
파일: sub.c 프로젝트: hroncok/mpv
void reinit_subs(struct MPContext *mpctx)
{
    struct MPOpts *opts = mpctx->opts;
    struct track *track = mpctx->current_track[STREAM_SUB];

    assert(!(mpctx->initialized_flags & INITIALIZED_SUB));

    init_demux_stream(mpctx, STREAM_SUB);
    struct sh_stream *sh = mpctx->sh[STREAM_SUB];

    // No track selected, or lazily added DVD track (will actually be created
    // on first sub packet)
    if (!sh)
        return;

    if (!sh->sub->dec_sub) {
        assert(!mpctx->d_sub);
        sh->sub->dec_sub = sub_create(mpctx->global);
    }

    assert(!mpctx->d_sub || sh->sub->dec_sub == mpctx->d_sub);

    // The decoder is kept in the stream header in order to make ordered
    // chapters work well.
    mpctx->d_sub = sh->sub->dec_sub;

    mpctx->initialized_flags |= INITIALIZED_SUB;

    struct dec_sub *dec_sub = mpctx->d_sub;
    assert(dec_sub);

    if (!sub_is_initialized(dec_sub)) {
        struct sh_video *sh_video =
            mpctx->d_video ? mpctx->d_video->header->video : NULL;
        int w = sh_video ? sh_video->disp_w : 0;
        int h = sh_video ? sh_video->disp_h : 0;
        float fps = sh_video ? sh_video->fps : 25;

        set_dvdsub_fake_extradata(dec_sub, track->demuxer->stream, w, h);
        sub_set_video_res(dec_sub, w, h);
        sub_set_video_fps(dec_sub, fps);
        sub_set_ass_renderer(dec_sub, mpctx->ass_library, mpctx->ass_renderer);
        sub_init_from_sh(dec_sub, sh);

        // Don't do this if the file has video/audio streams. Don't do it even
        // if it has only sub streams, because reading packets will change the
        // demuxer position.
        if (!track->preloaded && track->is_external) {
            demux_seek(track->demuxer, 0, SEEK_ABSOLUTE);
            track->preloaded = sub_read_all_packets(dec_sub, sh);
        }
    }

    mpctx->osd->dec_sub = dec_sub;

    // Decides whether to use OSD path or normal subtitle rendering path.
    mpctx->osd->render_bitmap_subs =
        opts->ass_enabled || !sub_has_get_text(dec_sub);

    reset_subtitles(mpctx);
}