[MPlayer-dev-eng] [PATCH] some embedded subtitle cleanups
Reimar Döffinger
Reimar.Doeffinger at stud.uni-karlsruhe.de
Sun Nov 12 16:03:49 CET 2006
Hello,
On Sun, Nov 12, 2006 at 03:23:02PM +0100, Reimar D?ffinger wrote:
> this patch is a first step to cleanup subtitle stream handling by
> handling it more similar to other streams.
> Many more changes will be needed in the future, but we have to start
> somewhere.
> Okay to apply?
Fixed version, it also adds preliminary support for subtitles in these
files (that part is to be applied separately of course):
http://samples.mplayerhq.hu/mov/subtitles-embedded/subtitlemovie.mov
http://samples.mplayerhq.hu/sub/NeroMP4/unsupported-embedded-subs-2.mp4
Greetings,
Reimar Döffinger
-------------- next part --------------
Index: libmpdemux/demux_mkv.c
===================================================================
--- libmpdemux/demux_mkv.c (revision 20861)
+++ libmpdemux/demux_mkv.c (working copy)
@@ -1766,6 +1766,8 @@
demux_mkv_open_video (demuxer_t *demuxer, mkv_track_t *track, int vid);
static int
demux_mkv_open_audio (demuxer_t *demuxer, mkv_track_t *track, int aid);
+static int
+demux_mkv_open_sub (demuxer_t *demuxer, mkv_track_t *track, int sid);
static void
display_create_tracks (demuxer_t *demuxer)
@@ -1796,7 +1798,7 @@
break;
case MATROSKA_TRACK_SUBTITLE:
type = "subtitles";
- mp_msg(MSGT_IDENTIFY, MSGL_INFO, "ID_SUBTITLE_ID=%d\n", sid);
+ demux_mkv_open_sub(demuxer, mkv_d->tracks[i], sid);
if (mkv_d->tracks[i]->name)
mp_msg(MSGT_IDENTIFY, MSGL_INFO, "ID_SID_%d_NAME=%s\n", sid, mkv_d->tracks[i]->name);
mp_msg(MSGT_IDENTIFY, MSGL_INFO, "ID_SID_%d_LANG=%s\n", sid, mkv_d->tracks[i]->language);
@@ -2408,18 +2410,18 @@
#endif
static int
-demux_mkv_open_sub (demuxer_t *demuxer, mkv_track_t *track)
+demux_mkv_open_sub (demuxer_t *demuxer, mkv_track_t *track, int sid)
{
if (track->subtitle_type != MATROSKA_SUBTYPE_UNKNOWN)
{
+ sh_sub_t *sh = new_sh_sub_sid(demuxer, track->tnum, sid);
if ((track->subtitle_type == MATROSKA_SUBTYPE_VOBSUB) ||
(track->subtitle_type == MATROSKA_SUBTYPE_SSA))
{
if (track->private_data != NULL)
{
- demuxer->sub->sh = malloc(sizeof(sh_sub_t));
- if (demuxer->sub->sh != NULL)
- memcpy(demuxer->sub->sh, &track->sh_sub, sizeof(sh_sub_t));
+ if (sh)
+ memcpy(sh, &track->sh_sub, sizeof(sh_sub_t));
}
}
}
@@ -2680,7 +2682,7 @@
track = demux_mkv_find_track_by_language (mkv_d, dvdsub_lang,
MATROSKA_TRACK_SUBTITLE);
- if (track && !demux_mkv_open_sub (demuxer, track))
+ if (track)
{
mp_msg (MSGT_DEMUX, MSGL_INFO,
MSGTR_MPDEMUX_MKV_WillDisplaySubtitleTrack, track->tnum);
Index: libmpdemux/demux_mov.c
===================================================================
--- libmpdemux/demux_mov.c (revision 20861)
+++ libmpdemux/demux_mov.c (working copy)
@@ -32,6 +32,9 @@
#include "bswap.h"
+#include "libvo/sub.h"
+extern subtitle *vo_sub;
+
#include "qtpalette.h"
#include "parse_mp4.h" // .MP4 specific stuff
@@ -290,6 +293,7 @@
}
#define MOV_MAX_TRACKS 256
+#define MOV_MAX_SUBLEN 1024
typedef struct {
off_t moov_start;
@@ -300,6 +304,9 @@
mov_track_t* tracks[MOV_MAX_TRACKS];
int timescale; // movie timescale
int duration; // movie duration (in movie timescale units)
+ subtitle subs;
+ char subtext[MOV_MAX_SUBLEN + 1];
+ int current_sub;
} mov_priv_t;
#define MOV_FOURCC(a,b,c,d) ((a<<24)|(b<<16)|(c<<8)|(d))
@@ -312,6 +319,7 @@
mp_msg(MSGT_DEMUX,MSGL_V,"Checking for MOV\n");
memset(priv,0,sizeof(mov_priv_t));
+ priv->current_sub = -1;
while(1){
int i;
@@ -1285,6 +1293,11 @@
break;
}
case MOV_TRAK_GENERIC:
+ if (trak->fourcc == mmioFOURCC('m','p','4','s') ||
+ trak->fourcc == mmioFOURCC('t','e','x','t')) {
+ sh_sub_t *sh = new_sh_sub(demuxer, priv->track_db);
+ sh->type = (trak->fourcc == mmioFOURCC('m','p','4','s')) ? 'v' : 't';
+ } else
mp_msg(MSGT_DEMUX, MSGL_V, "Generic track - not completely understood! (id: %d)\n",
trak->id);
/* XXX: Also this contains the FLASH data */
@@ -1918,6 +1931,15 @@
demuxer->video->id=-2;
}
}
+ if(demuxer->sub->id>=0){
+ sh_video_t* sh=demuxer->s_streams[demuxer->sub->id];
+ if(sh){
+ demuxer->sub->sh=sh; sh->ds=demuxer->sub;
+ } else {
+ mp_msg(MSGT_DEMUX, MSGL_ERR, "MOV: selected video stream (%d) does not exists\n",demuxer->video->id);
+ demuxer->sub->id=-2;
+ }
+ }
if(demuxer->video->id<0 && demuxer->audio->id<0) {
/* No AV streams found. Try to find an MPEG stream. */
@@ -2115,6 +2137,41 @@
++trak->pos;
+ if (demuxer->sub->id >= 0) {
+ int samplenr = 0;
+ trak = priv->tracks[demuxer->sub->id];
+ while (samplenr < trak->samples_size) {
+ double subpts = (double)trak->samples[samplenr].pts / (double)trak->timescale;
+ if (subpts >= pts) break;
+ samplenr++;
+ }
+ samplenr--;
+ if (samplenr < 0)
+ vo_sub = NULL;
+ else if (samplenr != priv->current_sub) {
+ sh_sub_t *sh = demuxer->sub->sh;
+ off_t pos = trak->samples[samplenr].pos;
+ int len = trak->samples[samplenr].size;
+ double subpts = (double)trak->samples[samplenr].pts / (double)trak->timescale;
+ stream_seek(demuxer->stream, pos);
+ if (sh->type == 'v')
+ ds_read_packet(demuxer->sub, demuxer->stream, len, subpts, pos, 0);
+ else {
+ stream_skip(demuxer->stream, 2); // size
+ len -= 2;
+ if (len < 0) len = 0;
+ if (len > MOV_MAX_SUBLEN) len = MOV_MAX_SUBLEN;
+ stream_read(demuxer->stream, priv->subtext, len);
+ priv->subtext[len] = 0;
+ priv->subs.lines = 1;
+ priv->subs.text[0] = &priv->subtext;
+ vo_sub = &priv->subs;
+ }
+ priv->current_sub = samplenr;
+ }
+ vo_osd_changed (OSDTYPE_SUBTITLE);
+ }
+
return 1;
}
Index: libmpdemux/demux_mpg.c
===================================================================
--- libmpdemux/demux_mpg.c (revision 20861)
+++ libmpdemux/demux_mpg.c (working copy)
@@ -298,7 +298,7 @@
if(!demux->s_streams[aid]){
mp_msg(MSGT_DEMUX,MSGL_V,"==> Found subtitle: %d\n",aid);
- demux->s_streams[aid]=1;
+ new_sh_sub(demux, aid);
}
if(demux->sub->id > -1)
Index: libmpdemux/stheader.h
===================================================================
--- libmpdemux/stheader.h (revision 20861)
+++ libmpdemux/stheader.h (working copy)
@@ -95,6 +95,8 @@
sh_audio_t* new_sh_audio_aid(demuxer_t *demuxer,int id,int aid);
#define new_sh_video(d, i) new_sh_video_vid(d, i, i)
sh_video_t* new_sh_video_vid(demuxer_t *demuxer,int id,int vid);
+#define new_sh_sub(d, i) new_sh_sub_sid(d, i, i)
+sh_sub_t *new_sh_sub_sid(demuxer_t *demuxer, int id, int sid);
void free_sh_audio(demuxer_t *demuxer, int id);
void free_sh_video(sh_video_t *sh);
Index: libmpdemux/demuxer.c
===================================================================
--- libmpdemux/demuxer.c (revision 20861)
+++ libmpdemux/demuxer.c (working copy)
@@ -201,6 +201,23 @@
return d;
}
+sh_sub_t *new_sh_sub_sid(demuxer_t *demuxer, int id, int sid) {
+ if (id > MAX_S_STREAMS - 1 || id < 0) {
+ mp_msg(MSGT_DEMUXER,MSGL_WARN,"Requested sub stream id overflow (%d > %d)\n",
+ id, MAX_S_STREAMS);
+ return NULL;
+ }
+ if (demuxer->s_streams[id])
+ mp_msg(MSGT_DEMUXER, MSGL_WARN, "Sub stream %i redefined\n", id);
+ else {
+ sh_sub_t *sh = calloc(1, sizeof(sh_sub_t));
+ demuxer->s_streams[id] = sh;
+ sh->sid = sid;
+ mp_msg(MSGT_IDENTIFY, MSGL_INFO, "ID_SUBTITLE_ID=%d\n", sid);
+ }
+ return demuxer->s_streams[id];
+}
+
sh_audio_t* new_sh_audio_aid(demuxer_t *demuxer,int id,int aid){
if(id > MAX_A_STREAMS-1 || id < 0)
{
Index: libmpdemux/demuxer.h
===================================================================
--- libmpdemux/demuxer.h (revision 20861)
+++ libmpdemux/demuxer.h (working copy)
@@ -138,10 +138,12 @@
#ifdef USE_ASS
ass_track_t* ass_track; // for SSA/ASS streams (type == 'a')
#endif
+ int sid;
} sh_sub_t;
#define MAX_A_STREAMS 256
#define MAX_V_STREAMS 256
+#define MAX_S_STREAMS 32
struct demuxer_st;
@@ -199,7 +201,7 @@
// stream headers:
void* a_streams[MAX_A_STREAMS]; // audio streams (sh_audio_t)
void* v_streams[MAX_V_STREAMS]; // video sterams (sh_video_t)
- char s_streams[32]; // dvd subtitles (flag)
+ void *s_streams[MAX_S_STREAMS]; // dvd subtitles (flag)
demux_chapter_t* chapters;
int num_chapters;
More information about the MPlayer-dev-eng
mailing list