Ejemplo n.º 1
0
static int demux_demuxers_fill_buffer(demuxer_t *demux,demux_stream_t *ds) {
  dd_priv_t* priv;

  priv=demux->priv;

  // HACK: make sure the subtitles get properly interleaved if with -subfile
  if (priv->sd && priv->sd->sub != ds &&
      priv->sd != priv->vd && priv->sd != priv->ad)
    ds_get_next_pts(priv->sd->sub);
  if(priv->vd && priv->vd->video == ds)
    return demux_fill_buffer(priv->vd,ds);
  else if(priv->ad && priv->ad->audio == ds)
    return demux_fill_buffer(priv->ad,ds);
  else if(priv->sd && priv->sd->sub == ds)
    return demux_fill_buffer(priv->sd,ds);

  mp_msg(MSGT_DEMUX,MSGL_WARN,MSGTR_MPDEMUX_DEMUXERS_FillBufferError);
  return 0;
}
Ejemplo n.º 2
0
void update_subtitles(sh_video_t *sh_video, double refpts, demux_stream_t *d_dvdsub, int reset)
{
    double curpts = refpts - sub_delay;
    unsigned char *packet=NULL;
    int len;
    int type = d_dvdsub->sh ? ((sh_sub_t *)d_dvdsub->sh)->type : 'v';
    static subtitle subs;
    if (reset) {
        sub_clear_text(&subs, MP_NOPTS_VALUE);
        if (vo_sub) {
            set_osd_subtitle(NULL);
        }
        if (vo_spudec) {
            spudec_reset(vo_spudec);
            vo_osd_changed(OSDTYPE_SPU);
        }
#ifdef CONFIG_FFMPEG
        if (is_av_sub(type))
            reset_avsub(d_dvdsub->sh);
#endif
    }
    // find sub
    if (subdata) {
        if (sub_fps==0) sub_fps = sh_video ? sh_video->fps : 25;
        current_module = "find_sub";
        if (refpts > sub_last_pts || refpts < sub_last_pts-1.0) {
            find_sub(subdata, curpts *
                     (subdata->sub_uses_time ? 100. : sub_fps));
            if (vo_sub) vo_sub_last = vo_sub;
            // FIXME! frame counter...
            sub_last_pts = refpts;
        }
    }

    // DVD sub:
    if (vo_config_count &&
        (vobsub_id >= 0 || type == 'v')) {
        int timestamp;
        current_module = "spudec";
        /* Get a sub packet from the DVD or a vobsub */
        while(1) {
            // Vobsub
            len = 0;
            if (vo_vobsub) {
                if (curpts >= 0) {
                    len = vobsub_get_packet(vo_vobsub, curpts,
                                            (void**)&packet, &timestamp);
                    if (len > 0) {
                        mp_dbg(MSGT_CPLAYER,MSGL_V,"\rVOB sub: len=%d v_pts=%5.3f v_timer=%5.3f sub=%5.3f ts=%d \n",len,refpts,sh_video->timer,timestamp / 90000.0,timestamp);
                    }
                }
            } else {
                // DVD sub
                len = ds_get_packet_sub(d_dvdsub, (unsigned char**)&packet, NULL, NULL);
                if (len > 0) {
                    // XXX This is wrong, sh_video->pts can be arbitrarily
                    // much behind demuxing position. Unfortunately using
                    // d_video->pts which would have been the simplest
                    // improvement doesn't work because mpeg specific hacks
                    // in video.c set d_video->pts to 0.
                    float x = d_dvdsub->pts - refpts;
                    if (x > -20 && x < 20) // prevent missing subs on pts reset
                        timestamp = 90000*d_dvdsub->pts;
                    else timestamp = 90000*curpts;
                    mp_dbg(MSGT_CPLAYER, MSGL_V, "\rDVD sub: len=%d  "
                           "v_pts=%5.3f  s_pts=%5.3f  ts=%d \n", len,
                           refpts, d_dvdsub->pts, timestamp);
                }
            }
            if (len<=0 || !packet) break;
            // create it only here, since with some broken demuxers we might
            // type = v but no DVD sub and we currently do not change the
            // "original frame size" ever after init, leading to wrong-sized
            // PGS subtitles.
            if (!vo_spudec)
                vo_spudec = spudec_new(NULL);
            if (vo_vobsub || timestamp >= 0)
                spudec_assemble(vo_spudec, packet, len, timestamp);
        }
    } else if (is_text_sub(type) || is_av_sub(type) || type == 'd') {
        int orig_type = type;
        double endpts;
        if (type == 'd' && !d_dvdsub->demuxer->teletext) {
            tt_stream_props tsp = {0};
            void *ptr = &tsp;
            if (teletext_control(NULL, TV_VBI_CONTROL_START, &ptr) == VBI_CONTROL_TRUE)
                d_dvdsub->demuxer->teletext = ptr;
        }
        if (d_dvdsub->non_interleaved)
            ds_get_next_pts(d_dvdsub);
        while (1) {
            double subpts = curpts;
            type = orig_type;
            len = ds_get_packet_sub(d_dvdsub, &packet, &subpts, &endpts);
            if (len < 0)
                break;
            if (is_av_sub(type)) {
#ifdef CONFIG_FFMPEG
                type = decode_avsub(d_dvdsub->sh, &packet, &len, &subpts, &endpts);
                if (type <= 0)
#endif
                    continue;
            }
            if (type == 'm') {
                if (len < 2) continue;
                len = FFMIN(len - 2, AV_RB16(packet));
                packet += 2;
            }
            if (type == 'd') {
                if (d_dvdsub->demuxer->teletext) {
                    uint8_t *p = packet;
                    p++;
                    len--;
                    while (len >= 46) {
                        int sublen = p[1];
                        if (p[0] == 2 || p[0] == 3)
                            teletext_control(d_dvdsub->demuxer->teletext,
                                TV_VBI_CONTROL_DECODE_DVB, p + 2);
                        p   += sublen + 2;
                        len -= sublen + 2;
                    }
                }
                continue;
            }
#ifdef CONFIG_ASS
            if (ass_enabled) {
                sh_sub_t* sh = d_dvdsub->sh;
                ass_track = sh ? sh->ass_track : NULL;
                if (!ass_track) continue;
                if (type == 'a') { // ssa/ass subs with libass
                    if (len > 10 && memcmp(packet, "Dialogue: ", 10) == 0)
                        ass_process_data(ass_track, packet, len);
                    else
                        ass_process_chunk(ass_track, packet, len,
                                          (long long)(subpts*1000 + 0.5),
                                          (long long)((endpts-subpts)*1000 + 0.5));
                } else { // plaintext subs with libass
                    if (subpts != MP_NOPTS_VALUE) {
                        subtitle tmp_subs = {0};
                        if (endpts == MP_NOPTS_VALUE) endpts = subpts + 3;
                        sub_add_text(&tmp_subs, packet, len, endpts, 0);
                        tmp_subs.start = subpts * 100;
                        tmp_subs.end = endpts * 100;
                        ass_process_subtitle(ass_track, &tmp_subs);
                        sub_clear_text(&tmp_subs, MP_NOPTS_VALUE);
                    }
                }
                continue;
            }
#endif
            if (subpts != MP_NOPTS_VALUE) {
                if (endpts == MP_NOPTS_VALUE)
                    sub_clear_text(&subs, MP_NOPTS_VALUE);
                if (type == 'a') { // ssa/ass subs without libass => convert to plaintext
                    int i;
                    unsigned char* p = packet;
                    int skip_commas = 8;
                    if (len > 10 && memcmp(packet, "Dialogue: ", 10) == 0)
                        skip_commas = 9;
                    for (i=0; i < skip_commas && *p != '\0'; p++)
                        if (*p == ',')
                            i++;
                    if (*p == '\0')  /* Broken line? */
                        continue;
                    len -= p - packet;
                    packet = p;
                }
                sub_add_text(&subs, packet, len, endpts, 1);
                set_osd_subtitle(&subs);
            }
            if (d_dvdsub->non_interleaved)
                ds_get_next_pts(d_dvdsub);
        }
        if (sub_clear_text(&subs, curpts))
            set_osd_subtitle(&subs);
    }
    if (vo_spudec) {
        spudec_heartbeat(vo_spudec, 90000*curpts);
        if (spudec_changed(vo_spudec))
            vo_osd_changed(OSDTYPE_SPU);
    }

    current_module=NULL;
}
Ejemplo n.º 3
0
void update_subtitles(sh_video_t *sh_video, demux_stream_t *d_dvdsub, int reset)
{
    unsigned char *packet=NULL;
    int len;
    char type = d_dvdsub->sh ? ((sh_sub_t *)d_dvdsub->sh)->type : 'v';
    static subtitle subs;
    if (type == 'a')
#ifdef USE_ASS
      if (!ass_enabled)
#endif
      type = 't';
    if (reset) {
	sub_clear_text(&subs, MP_NOPTS_VALUE);
	if (vo_sub) {
	    vo_sub = NULL;
	    vo_osd_changed(OSDTYPE_SUBTITLE);
	}
	if (vo_spudec) {
	    spudec_reset(vo_spudec);
	    vo_osd_changed(OSDTYPE_SPU);
	}
    }
    // find sub
    if (subdata) {
	double pts = sh_video->pts;
	if (sub_fps==0) sub_fps = sh_video->fps;
	current_module = "find_sub";
	if (pts > sub_last_pts || pts < sub_last_pts-1.0) {
	    find_sub(subdata, (pts+sub_delay) *
		     (subdata->sub_uses_time ? 100. : sub_fps)); 
	    if (vo_sub) vo_sub_last = vo_sub;
	    // FIXME! frame counter...
	    sub_last_pts = pts;
	}
    }

    // DVD sub:
    if (vo_config_count && vo_spudec && type == 'v') {
	int timestamp;
	current_module = "spudec";
	spudec_heartbeat(vo_spudec, 90000*sh_video->timer);
	/* Get a sub packet from the DVD or a vobsub and make a timestamp
	 * relative to sh_video->timer */
	while(1) {
	    // Vobsub
	    len = 0;
	    if (vo_vobsub) {
		if (sh_video->pts+sub_delay >= 0) {
		    len = vobsub_get_packet(vo_vobsub, sh_video->pts+sub_delay,
					    (void**)&packet, &timestamp);
		    if (len > 0) {
			timestamp -= (sh_video->pts + sub_delay - sh_video->timer)*90000;
			mp_dbg(MSGT_CPLAYER,MSGL_V,"\rVOB sub: len=%d v_pts=%5.3f v_timer=%5.3f sub=%5.3f ts=%d \n",len,sh_video->pts,sh_video->timer,timestamp / 90000.0,timestamp);
		    }
		}
	    } else {
		// DVD sub
		len = ds_get_packet_sub(d_dvdsub, (unsigned char**)&packet);
		if (len > 0) {
		    // XXX This is wrong, sh_video->pts can be arbitrarily
		    // much behind demuxing position. Unfortunately using
		    // d_video->pts which would have been the simplest
		    // improvement doesn't work because mpeg specific hacks
		    // in video.c set d_video->pts to 0.
		    float x = d_dvdsub->pts - sh_video->pts;
		    if (x > -20 && x < 20) // prevent missing subs on pts reset
			timestamp = 90000*(sh_video->timer + d_dvdsub->pts
					   + sub_delay - sh_video->pts);
		    else timestamp = 90000*(sh_video->timer + sub_delay);
		    mp_dbg(MSGT_CPLAYER, MSGL_V, "\rDVD sub: len=%d  "
			   "v_pts=%5.3f  s_pts=%5.3f  ts=%d \n", len,
			   sh_video->pts, d_dvdsub->pts, timestamp);
		}
	    }
	    if (len<=0 || !packet) break;
	    if (timestamp >= 0)
		spudec_assemble(vo_spudec, packet, len, timestamp);
	}

	if (spudec_changed(vo_spudec))
	    vo_osd_changed(OSDTYPE_SPU);
    } else if (dvdsub_id >= 0 && type == 't') {
	double curpts = sh_video->pts + sub_delay;
	double endpts;
	vo_sub = &subs;
	while (d_dvdsub->first) {
	    double pts = ds_get_next_pts(d_dvdsub);
	    if (pts > curpts)
		break;
	    endpts = d_dvdsub->first->endpts;
	    len = ds_get_packet_sub(d_dvdsub, &packet);
#ifdef USE_ASS
	    if (ass_enabled) {
		static ass_track_t *global_ass_track = NULL;
		if (!global_ass_track) global_ass_track = ass_default_track(ass_library);
		ass_track = global_ass_track;
		vo_sub = NULL;
		if (pts != MP_NOPTS_VALUE) {
		    if (endpts == MP_NOPTS_VALUE) endpts = pts + 3;
		    sub_clear_text(&subs, MP_NOPTS_VALUE);
		    sub_add_text(&subs, packet, len, endpts);
		    subs.start = pts * 100;
		    subs.end = endpts * 100;
		    ass_process_subtitle(ass_track, &subs);
		}
	    } else
#endif
		if (pts != MP_NOPTS_VALUE) {
		    if (endpts == MP_NOPTS_VALUE)
			sub_clear_text(&subs, MP_NOPTS_VALUE);
		    sub_add_text(&subs, packet, len, endpts);
		    vo_osd_changed(OSDTYPE_SUBTITLE);
		}
	}
	if (sub_clear_text(&subs, curpts))
	    vo_osd_changed(OSDTYPE_SUBTITLE);
    }
    current_module=NULL;
}