subtitle and transport stream patches
JW <[email protected]> Tue, 07 Jul 2020 09:00:23 +1000
| Newsgroups | gmane.comp.video.xine.devel |
|---|---|
| Message-ID | <[email protected]> |
This is a multi-part message in MIME format.
--------------030206030407050307000805
Content-Type: text/plain; charset=ISO-8859-1; format=flowed
Content-Transfer-Encoding: 7bit
I have attached a few patches to fix some problems mostly relating to
subtitles and transport streams. There is a patch to account for the
disconnect between the main stream and the separate subtitle slave
stream. And another patch to greatly improve transport stream seek and
synchronization.
Each patch contains relevant comments.
:JW
--------------030206030407050307000805
Content-Type: text/plain;
name="xine-ts.patch"
Content-Transfer-Encoding: 7bit
Content-Disposition: attachment;
filename="xine-ts.patch"
#
# This patch corrects the very poor synchronization between transport
# streams and external subtitles. It is all very well using bit rate to
# estimate a seek amount but it is not a good idea to feed such a coarse
# estimate into a subtitle stream which is trying to synchronize its output
# when there already exists a highly accurate pts.
#
# The patch also improves transport stream seeking by detecting small
# relative seeks and performing a seek from the current position rather
# than trying to achieve a wildly inaccurate absolute position seek.
#
--- xine-lib-1.2.10/src/demuxers/demux_ts.c.jdw 2019-12-14 07:47:50.000000000 +1100
+++ xine-lib-1.2.10/src/demuxers/demux_ts.c 2020-06-14 15:43:17.000000000 +1000
@@ -559,6 +559,8 @@
int audio_tracks_count;
int64_t last_pts[2], apts, bpts;
+ int64_t first_pts;
+ int64_t cur_pts;
int32_t bounce_left;
int send_newpts;
int buf_flag_seek;
@@ -1075,10 +1077,12 @@
if ((t == BUF_VIDEO_BASE) || (t == BUF_AUDIO_BASE))
newpts_test (this, m->pts, (t == BUF_VIDEO_BASE) ? PTS_VIDEO : PTS_AUDIO);
}
+ if (!this->first_pts)
+ this->first_pts = m->pts;
m->buf->content = m->buf->mem;
m->buf->type = m->type;
m->buf->decoder_flags |= flags;
- m->buf->pts = m->pts;
+ m->buf->pts = this->cur_pts = m->pts;
m->buf->decoder_info[0] = 1;
m->buf->extra_info->input_normpos = m->input_normpos;
m->buf->extra_info->input_time = m->input_time;
@@ -1605,9 +1609,7 @@
if (length > 0) {
m->input_normpos = (double)this->frame_pos * 65535.0 / length;
}
- if (this->rate) {
- m->input_time = this->frame_pos * 1000 / this->rate;
- }
+ m->input_time = (m->pts - this->first_pts)/(90000 / 1000);
}
/*
@@ -2933,26 +2935,29 @@
if (caps & (INPUT_CAP_SEEKABLE | INPUT_CAP_SLOW_SEEKABLE | INPUT_CAP_TIME_SEEKABLE)) {
if ((caps & INPUT_CAP_TIME_SEEKABLE) && this->input->seek_time) {
if (start_pos > 0) {
- int32_t duration = 0;
- if ((this->input->get_optional_data (this->input, &duration, INPUT_OPTIONAL_DATA_DURATION) == INPUT_OPTIONAL_SUCCESS)
- && (duration > 0)) {
- start_time = (double)start_pos * duration / 65535;
- }
+ int32_t duration = 0;
+ if ((this->input->get_optional_data(this->input, &duration, INPUT_OPTIONAL_DATA_DURATION) == INPUT_OPTIONAL_SUCCESS)
+ && (duration > 0)) {
+ start_time = (double)start_pos * duration / 65535;
+ }
}
this->input->seek_time (this->input, start_time, SEEK_SET);
} else {
- start_pos = (off_t)((double)start_pos / 65535 * this->input->get_length (this->input));
if ((!start_pos) && (start_time)) {
- if (this->input->seek_time) {
- this->input->seek_time (this->input, start_time, SEEK_SET);
+ int delta = start_time / 1000 - (this->cur_pts - this->first_pts)/90000;
+ if (-90 < delta && delta < 90) {
+ start_pos = delta * this->rate;
+ this->input->seek (this->input, start_pos, SEEK_CUR);
} else {
- start_pos = (int64_t)start_time * this->rate / 1000;
- this->input->seek (this->input, start_pos, SEEK_SET);
+ start_pos = (int64_t)start_time * this->rate / 1000;
+ this->input->seek (this->input, start_pos, SEEK_SET);
}
} else {
+ start_pos = (off_t)((double)start_pos / 65535 * this->input->get_length(this->input));
this->input->seek (this->input, start_pos, SEEK_SET);
}
}
+
#if TS_PACKET_READER == 2
this->buf_pos = 0;
this->buf_size = 0;
@@ -3238,6 +3243,8 @@
this->bpts = 0;
this->last_pts[0] = 0;
this->last_pts[1] = 0;
+ this->first_pts = 0;
+ this->cur_pts = 0;
this->newpts_fifo = NULL;
# if TS_PACKET_READER == 2
this->buf_pos = 0;
--------------030206030407050307000805
Content-Type: text/plain;
name="xine-spu-select.patch"
Content-Transfer-Encoding: 7bit
Content-Disposition: attachment;
filename="xine-spu-select.patch"
#
# This patch corrects the disconnect between the independent
# subtitle stream and the selection of the subtitle channel.
# It also undoes the hack which would mask the problem by
# disabling the entire osd.
#
# Unfortunately there is also a gap between the creation of the
# subtitle stream and it becoming a slaved stream so there is an
# additional re-invocation of the subtitle channel selection (this
# becomes evident when the -u command-line option is used).
#
--- xine-lib-1.2.10/src/xine-engine/xine.c.jdw 2019-12-14 07:47:50.000000000 +1100
+++ xine-lib-1.2.10/src/xine-engine/xine.c 2020-06-16 14:22:49.000000000 +1000
@@ -2772,8 +2773,10 @@
void _x_select_spu_channel (xine_stream_t *s, int channel) {
xine_stream_private_t *stream = (xine_stream_private_t *)s;
xine_private_t *xine = (xine_private_t *)stream->s.xine;
+ xine_stream_private_t *substream = NULL;
stream = stream->side_streams[0];
+ substream = (xine_stream_private_t *)stream->s.slave;
pthread_mutex_lock (&stream->frontend_lock);
stream->s.spu_channel_user = (channel >= -2 ? channel : -2);
@@ -2783,24 +2786,29 @@
switch (stream->s.spu_channel_user) {
case -2:
stream->s.spu_channel = -1;
- if (stream->s.video_out)
- stream->s.video_out->enable_ovl (stream->s.video_out, 0);
break;
case -1:
- stream->s.spu_channel = stream->s.spu_channel_auto;
- if (stream->s.video_out)
- stream->s.video_out->enable_ovl (stream->s.video_out, 1);
+ if (substream)
+ stream->s.spu_channel = substream->s.spu_channel_auto;
+ else
+ stream->s.spu_channel = stream->s.spu_channel_auto;
break;
default:
stream->s.spu_channel = stream->s.spu_channel_user;
- if (stream->s.video_out)
- stream->s.video_out->enable_ovl (stream->s.video_out, 1);
}
lprintf ("set to %d\n", stream->s.spu_channel);
xine->port_ticket->release (xine->port_ticket, 1);
pthread_mutex_unlock (&stream->frontend_lock);
+
+ if (substream)
+ {
+ pthread_mutex_lock (&substream->frontend_lock);
+ substream->s.spu_channel = stream->s.spu_channel;
+ substream->s.spu_channel_user = stream->s.spu_channel_user;
+ pthread_mutex_unlock (&substream->frontend_lock);
+ }
}
void _x_get_current_info (xine_stream_t *s, extra_info_t *extra_info, int size) {
@@ -3402,6 +3410,8 @@
* of its own, we point to this master's master; if our master is a
* standalone stream, its master pointer will point to itself */
slave->master = master->s.master;
+
+ _x_select_spu_channel (m, master->s.spu_channel_user);
return 1;
}
--------------030206030407050307000805
Content-Type: text/plain;
name="xine-sputext.patch"
Content-Transfer-Encoding: 7bit
Content-Disposition: attachment;
filename="xine-sputext.patch"
#
# Given the correction for control of the slaved subtitle stream
# it becomes necessary for text subtitles to properly implement
# channel matching. In particular, the subtitle stream must continue
# to synchronize with the video decoder and therefore must pause
# properly even if the subtitle channel does not currently match
# what the user wants.
#
--- xine-lib-1.2.10/src/spu_dec/sputext_decoder.c.jdw 2019-12-14 07:47:50.000000000 +1100
+++ xine-lib-1.2.10/src/spu_dec/sputext_decoder.c 2020-06-16 14:28:43.000000000 +1000
@@ -819,9 +833,6 @@
if (buf->decoder_flags & BUF_FLAG_PREVIEW)
return;
- if ((this->stream->spu_channel & 0x1f) != (buf->type & 0x1f))
- return;
-
if ( (buf->decoder_flags & BUF_FLAG_SPECIAL) &&
(buf->decoder_info[1] == BUF_SPECIAL_CHARSET_ENCODING) )
this->buf_encoding = buf->decoder_info_ptr[2];
@@ -987,8 +998,12 @@
}
_x_spu_decoder_sleep(this->stream, start_vpts);
- update_output_size( this );
- draw_subtitle(this, start_vpts, end_vpts);
+
+ if (this->stream->spu_channel >= 0 && (this->stream->spu_channel & 0x1f) == (buf->type & 0x1f))
+ {
+ update_output_size( this );
+ draw_subtitle(this, start_vpts, end_vpts);
+ }
return;
}
--------------030206030407050307000805
Content-Type: text/plain;
name="xine-sscanf.patch"
Content-Transfer-Encoding: 7bit
Content-Disposition: attachment;
filename="xine-sscanf.patch"
#
# The problem with a construct such as 'sscanf(s, "%d.%d", &a1, &a2)'
# is that it can produce erroneous results. For example, given input
# such as "2.1" or "2.01" or "2.001" then a2 will always be 1. So one
# cannot automatically assume it mean 1/10 or 1/100 or 1/1000.
# This is the very reason why sscanf has a "%f" conversion.
#
--- xine-lib-1.2.10/src/spu_dec/sputext_demuxer.c.jdw 2019-12-14 07:47:50.000000000 +1100
+++ xine-lib-1.2.10/src/spu_dec/sputext_demuxer.c 2020-06-16 17:03:38.000000000 +1000
@@ -309,7 +309,8 @@
static subtitle_t *sub_read_line_subviewer(demux_sputext_t *this, subtitle_t *current) {
char line[LINE_LEN + 1];
- int a1,a2,a3,a4,b1,b2,b3,b4;
+ int a1,a2,b1,b2;
+ float a3,b3;
char *p=NULL, *q=NULL;
int len;
@@ -317,12 +318,11 @@
while (1) {
if (!read_line_from_input(this, line, LINE_LEN)) return NULL;
- if (sscanf (line, "%d:%d:%d.%d,%d:%d:%d.%d",&a1,&a2,&a3,&a4,&b1,&b2,&b3,&b4) < 8) {
- if (sscanf (line, "%d:%d:%d,%d,%d:%d:%d,%d",&a1,&a2,&a3,&a4,&b1,&b2,&b3,&b4) < 8)
+ if (sscanf (line, "%d:%d:%f,%d:%d:%f",&a1,&a2,&a3,&b1,&b2,&b3) < 6) {
continue;
}
- current->start = a1*360000+a2*6000+a3*100+a4;
- current->end = b1*360000+b2*6000+b3*100+b4;
+ current->start = a1*360000+a2*6000+a3*100.0;
+ current->end = b1*360000+b2*6000+b3*100.0;
if (!read_line_from_input(this, line, LINE_LEN))
return NULL;
@@ -344,17 +344,21 @@
static subtitle_t *sub_read_line_subrip(demux_sputext_t *this,subtitle_t *current) {
char line[LINE_LEN + 1];
- int a1,a2,a3,a4,b1,b2,b3,b4;
+ int a1,a2,b1,b2;
+ float a3,b3;
int i,end_sub;
memset(current,0,sizeof(subtitle_t));
do {
+ char *p;
if(!read_line_from_input(this,line,LINE_LEN))
return NULL;
- i = sscanf(line,"%d:%d:%d%*[,.]%d --> %d:%d:%d%*[,.]%d",&a1,&a2,&a3,&a4,&b1,&b2,&b3,&b4);
- } while(i < 8);
- current->start = a1*360000+a2*6000+a3*100+a4/10;
- current->end = b1*360000+b2*6000+b3*100+b4/10;
+ while ((p = strchr(line, ',')))
+ *p = '.';
+ i = sscanf(line,"%d:%d:%f --> %d:%d:%f",&a1,&a2,&a3,&b1,&b2,&b3);
+ } while(i < 6);
+ current->start = a1*360000+a2*6000+a3*100.0;
+ current->end = b1*360000+b2*6000+b3*100.0;
i=0;
end_sub=0;
do {
@@ -471,7 +475,8 @@
* WARNING: full XML parses can be required for proper parsing
*/
char line[LINE_LEN + 1];
- int a1,a2,a3,a4,b1,b2,b3,b4;
+ int a1,a2,b1,b2;
+ float a3,b3;
char *p=NULL,*next=NULL;
int i,len,plen;
@@ -483,19 +488,13 @@
* TODO: it seems that format of time is not easily determined, it may be 1:12, 1:12.0 or 0:1:12.0
* to describe the same moment in time. Maybe there are even more formats in use.
*/
- if ((len=sscanf (line, "<Time Begin=\"%d:%d:%d.%d\" End=\"%d:%d:%d.%d\"",&a1,&a2,&a3,&a4,&b1,&b2,&b3,&b4)) < 8)
+ if ((len=sscanf (line, "<Time Begin=\"%d:%d:%f\" End=\"%d:%d:%f\"",&a1,&a2,&a3,&b1,&b2,&b3)) < 6)
- plen=a1=a2=a3=a4=b1=b2=b3=b4=0;
- if (
- ((len=sscanf (line, "<%*[tT]ime %*[bB]egin=\"%d:%d\" %*[Ee]nd=\"%d:%d\"%*[^<]<clear/>%n",&a2,&a3,&b2,&b3,&plen)) < 4) &&
- ((len=sscanf (line, "<%*[tT]ime %*[bB]egin=\"%d:%d\" %*[Ee]nd=\"%d:%d.%d\"%*[^<]<clear/>%n",&a2,&a3,&b2,&b3,&b4,&plen)) < 5) &&
- /* ((len=sscanf (line, "<%*[tT]ime %*[bB]egin=\"%d:%d.%d\" %*[Ee]nd=\"%d:%d\"%*[^<]<clear/>%n",&a2,&a3,&a4,&b2,&b3,&plen)) < 5) && */
- ((len=sscanf (line, "<%*[tT]ime %*[bB]egin=\"%d:%d.%d\" %*[Ee]nd=\"%d:%d.%d\"%*[^<]<clear/>%n",&a2,&a3,&a4,&b2,&b3,&b4,&plen)) < 6) &&
- ((len=sscanf (line, "<%*[tT]ime %*[bB]egin=\"%d:%d:%d.%d\" %*[Ee]nd=\"%d:%d:%d.%d\"%*[^<]<clear/>%n",&a1,&a2,&a3,&a4,&b1,&b2,&b3,&b4,&plen)) < 8)
- )
+ plen=a1=a2=a3=b1=b2=b3=0;
+ if ((len=sscanf (line, "<%*[tT]ime %*[bB]egin=\"%d:%f\" %*[Ee]nd=\"%d:%f\"%n",&a2,&a3,&b2,&b3,&plen)) < 4)
continue;
- current->start = a1*360000+a2*6000+a3*100+a4/10;
- current->end = b1*360000+b2*6000+b3*100+b4/10;
+ current->start = a1*360000+a2*6000+a3*100.0;
+ current->end = b1*360000+b2*6000+b3*100.0;
p=line; p+=plen;i=0;
/* TODO: I don't know what kind of convention is here for marking multiline subs, maybe <br/> like in xml? */
next = strstr(line,"<clear/>")+8;i=0;
@@ -519,24 +518,25 @@
static int max_comma = 32; /* let's use 32 for the case that the */
/* amount of commas increase with newer SSA versions */
- int hour1, min1, sec1, hunsec1, hour2, min2, sec2, hunsec2, nothing;
+ int hour1, min1, hour2, min2, nothing;
+ float sec1, sec2;
int num;
char line[LINE_LEN + 1], line3[LINE_LEN + 1], *line2;
char *tmp;
do {
if (!read_line_from_input(this, line, LINE_LEN)) return NULL;
- } while (sscanf (line, "Dialogue: Marked=%d,%d:%d:%d.%d,%d:%d:%d.%d,"
+ } while (sscanf (line, "Dialogue: Marked=%d,%d:%d:%f,%d:%d:%f,"
"%[^\n\r]", ¬hing,
- &hour1, &min1, &sec1, &hunsec1,
- &hour2, &min2, &sec2, &hunsec2,
- line3) < 9
+ &hour1, &min1, &sec1,
+ &hour2, &min2, &sec2,
+ line3) < 7
&&
- sscanf (line, "Dialogue: %d,%d:%d:%d.%d,%d:%d:%d.%d,"
+ sscanf (line, "Dialogue: %d,%d:%d:%f,%d:%d:%f,"
"%[^\n\r]", ¬hing,
- &hour1, &min1, &sec1, &hunsec1,
- &hour2, &min2, &sec2, &hunsec2,
- line3) < 9 );
+ &hour1, &min1, &sec1,
+ &hour2, &min2, &sec2,
+ line3) < 7 );
line2=strchr(line3, ',');
if (!line2)
@@ -556,8 +556,8 @@
if(*line2 == ',') line2++;
current->lines=0;num=0;
- current->start = 360000*hour1 + 6000*min1 + 100*sec1 + hunsec1;
- current->end = 360000*hour2 + 6000*min2 + 100*sec2 + hunsec2;
+ current->start = 360000*hour1 + 6000*min1 + 100.0*sec1;
+ current->end = 360000*hour2 + 6000*min2 + 100.0*sec2;
while (((tmp=strstr(line2, "\\n")) != NULL) || ((tmp=strstr(line2, "\\N")) != NULL) ){
current->text[num] = strndup(line2, tmp-line2);
--------------030206030407050307000805
Content-Type: text/plain; charset="us-ascii"
MIME-Version: 1.0
Content-Transfer-Encoding: 7bit
Content-Disposition: inline
--------------030206030407050307000805
Content-Type: text/plain; charset="us-ascii"
MIME-Version: 1.0
Content-Transfer-Encoding: 7bit
Content-Disposition: inline
_______________________________________________
xine-devel mailing list
[email protected]
https://lists.sourceforge.net/lists/listinfo/xine-devel
--------------030206030407050307000805--