|  |  | @@ -0,0 +1,128 @@ | 
		
	
		
			
			|  |  |  | /* | 
		
	
		
			
			|  |  |  | * Copyright (c) 2012 Clément Bœsch | 
		
	
		
			
			|  |  |  | * | 
		
	
		
			
			|  |  |  | * This file is part of FFmpeg. | 
		
	
		
			
			|  |  |  | * | 
		
	
		
			
			|  |  |  | * FFmpeg is free software; you can redistribute it and/or | 
		
	
		
			
			|  |  |  | * modify it under the terms of the GNU Lesser General Public | 
		
	
		
			
			|  |  |  | * License as published by the Free Software Foundation; either | 
		
	
		
			
			|  |  |  | * version 2.1 of the License, or (at your option) any later version. | 
		
	
		
			
			|  |  |  | * | 
		
	
		
			
			|  |  |  | * FFmpeg is distributed in the hope that it will be useful, | 
		
	
		
			
			|  |  |  | * but WITHOUT ANY WARRANTY; without even the implied warranty of | 
		
	
		
			
			|  |  |  | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU | 
		
	
		
			
			|  |  |  | * Lesser General Public License for more details. | 
		
	
		
			
			|  |  |  | * | 
		
	
		
			
			|  |  |  | * You should have received a copy of the GNU Lesser General Public | 
		
	
		
			
			|  |  |  | * License along with FFmpeg; if not, write to the Free Software | 
		
	
		
			
			|  |  |  | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA | 
		
	
		
			
			|  |  |  | */ | 
		
	
		
			
			|  |  |  | 
 | 
		
	
		
			
			|  |  |  | /** | 
		
	
		
			
			|  |  |  | * @file | 
		
	
		
			
			|  |  |  | * VPlayer subtitles format demuxer | 
		
	
		
			
			|  |  |  | */ | 
		
	
		
			
			|  |  |  | 
 | 
		
	
		
			
			|  |  |  | #include "avformat.h" | 
		
	
		
			
			|  |  |  | #include "internal.h" | 
		
	
		
			
			|  |  |  | #include "subtitles.h" | 
		
	
		
			
			|  |  |  | 
 | 
		
	
		
			
			|  |  |  | typedef struct { | 
		
	
		
			
			|  |  |  | FFDemuxSubtitlesQueue q; | 
		
	
		
			
			|  |  |  | } VPlayerContext; | 
		
	
		
			
			|  |  |  | 
 | 
		
	
		
			
			|  |  |  | static int vplayer_probe(AVProbeData *p) | 
		
	
		
			
			|  |  |  | { | 
		
	
		
			
			|  |  |  | char c; | 
		
	
		
			
			|  |  |  | const unsigned char *ptr = p->buf; | 
		
	
		
			
			|  |  |  | 
 | 
		
	
		
			
			|  |  |  | if (sscanf(ptr, "%*d:%*d:%*d.%*d%c", &c) == 1 && strchr(": =", c)) | 
		
	
		
			
			|  |  |  | return AVPROBE_SCORE_MAX; | 
		
	
		
			
			|  |  |  | return 0; | 
		
	
		
			
			|  |  |  | } | 
		
	
		
			
			|  |  |  | 
 | 
		
	
		
			
			|  |  |  | static int64_t read_ts(char **line) | 
		
	
		
			
			|  |  |  | { | 
		
	
		
			
			|  |  |  | char c; | 
		
	
		
			
			|  |  |  | int hh, mm, ss, ms, len; | 
		
	
		
			
			|  |  |  | 
 | 
		
	
		
			
			|  |  |  | if (sscanf(*line, "%d:%d:%d.%d%c%n", | 
		
	
		
			
			|  |  |  | &hh, &mm, &ss, &ms, &c, &len) >= 5) { | 
		
	
		
			
			|  |  |  | *line += len; | 
		
	
		
			
			|  |  |  | return (hh*3600LL + mm*60LL + ss) * 100LL + ms; | 
		
	
		
			
			|  |  |  | } | 
		
	
		
			
			|  |  |  | return AV_NOPTS_VALUE; | 
		
	
		
			
			|  |  |  | } | 
		
	
		
			
			|  |  |  | 
 | 
		
	
		
			
			|  |  |  | static int vplayer_read_header(AVFormatContext *s) | 
		
	
		
			
			|  |  |  | { | 
		
	
		
			
			|  |  |  | VPlayerContext *vplayer = s->priv_data; | 
		
	
		
			
			|  |  |  | AVStream *st = avformat_new_stream(s, NULL); | 
		
	
		
			
			|  |  |  | 
 | 
		
	
		
			
			|  |  |  | if (!st) | 
		
	
		
			
			|  |  |  | return AVERROR(ENOMEM); | 
		
	
		
			
			|  |  |  | avpriv_set_pts_info(st, 64, 1, 100); | 
		
	
		
			
			|  |  |  | st->codec->codec_type = AVMEDIA_TYPE_SUBTITLE; | 
		
	
		
			
			|  |  |  | st->codec->codec_id   = AV_CODEC_ID_VPLAYER; | 
		
	
		
			
			|  |  |  | 
 | 
		
	
		
			
			|  |  |  | while (!url_feof(s->pb)) { | 
		
	
		
			
			|  |  |  | char line[4096]; | 
		
	
		
			
			|  |  |  | char *p = line; | 
		
	
		
			
			|  |  |  | const int64_t pos = avio_tell(s->pb); | 
		
	
		
			
			|  |  |  | int len = ff_get_line(s->pb, line, sizeof(line)); | 
		
	
		
			
			|  |  |  | int64_t pts_start; | 
		
	
		
			
			|  |  |  | 
 | 
		
	
		
			
			|  |  |  | if (!len) | 
		
	
		
			
			|  |  |  | break; | 
		
	
		
			
			|  |  |  | 
 | 
		
	
		
			
			|  |  |  | line[strcspn(line, "\r\n")] = 0; | 
		
	
		
			
			|  |  |  | 
 | 
		
	
		
			
			|  |  |  | pts_start = read_ts(&p); | 
		
	
		
			
			|  |  |  | if (pts_start != AV_NOPTS_VALUE) { | 
		
	
		
			
			|  |  |  | AVPacket *sub; | 
		
	
		
			
			|  |  |  | 
 | 
		
	
		
			
			|  |  |  | sub = ff_subtitles_queue_insert(&vplayer->q, p, strlen(p), 0); | 
		
	
		
			
			|  |  |  | if (!sub) | 
		
	
		
			
			|  |  |  | return AVERROR(ENOMEM); | 
		
	
		
			
			|  |  |  | sub->pos = pos; | 
		
	
		
			
			|  |  |  | sub->pts = pts_start; | 
		
	
		
			
			|  |  |  | sub->duration = -1; | 
		
	
		
			
			|  |  |  | } | 
		
	
		
			
			|  |  |  | } | 
		
	
		
			
			|  |  |  | 
 | 
		
	
		
			
			|  |  |  | ff_subtitles_queue_finalize(&vplayer->q); | 
		
	
		
			
			|  |  |  | return 0; | 
		
	
		
			
			|  |  |  | } | 
		
	
		
			
			|  |  |  | 
 | 
		
	
		
			
			|  |  |  | static int vplayer_read_packet(AVFormatContext *s, AVPacket *pkt) | 
		
	
		
			
			|  |  |  | { | 
		
	
		
			
			|  |  |  | VPlayerContext *vplayer = s->priv_data; | 
		
	
		
			
			|  |  |  | return ff_subtitles_queue_read_packet(&vplayer->q, pkt); | 
		
	
		
			
			|  |  |  | } | 
		
	
		
			
			|  |  |  | 
 | 
		
	
		
			
			|  |  |  | static int vplayer_read_seek(AVFormatContext *s, int stream_index, | 
		
	
		
			
			|  |  |  | int64_t min_ts, int64_t ts, int64_t max_ts, int flags) | 
		
	
		
			
			|  |  |  | { | 
		
	
		
			
			|  |  |  | VPlayerContext *vplayer = s->priv_data; | 
		
	
		
			
			|  |  |  | return ff_subtitles_queue_seek(&vplayer->q, s, stream_index, | 
		
	
		
			
			|  |  |  | min_ts, ts, max_ts, flags); | 
		
	
		
			
			|  |  |  | } | 
		
	
		
			
			|  |  |  | 
 | 
		
	
		
			
			|  |  |  | static int vplayer_read_close(AVFormatContext *s) | 
		
	
		
			
			|  |  |  | { | 
		
	
		
			
			|  |  |  | VPlayerContext *vplayer = s->priv_data; | 
		
	
		
			
			|  |  |  | ff_subtitles_queue_clean(&vplayer->q); | 
		
	
		
			
			|  |  |  | return 0; | 
		
	
		
			
			|  |  |  | } | 
		
	
		
			
			|  |  |  | 
 | 
		
	
		
			
			|  |  |  | AVInputFormat ff_vplayer_demuxer = { | 
		
	
		
			
			|  |  |  | .name           = "vplayer", | 
		
	
		
			
			|  |  |  | .long_name      = NULL_IF_CONFIG_SMALL("VPlayer subtitles"), | 
		
	
		
			
			|  |  |  | .priv_data_size = sizeof(VPlayerContext), | 
		
	
		
			
			|  |  |  | .read_probe     = vplayer_probe, | 
		
	
		
			
			|  |  |  | .read_header    = vplayer_read_header, | 
		
	
		
			
			|  |  |  | .read_packet    = vplayer_read_packet, | 
		
	
		
			
			|  |  |  | .read_seek2     = vplayer_read_seek, | 
		
	
		
			
			|  |  |  | .read_close     = vplayer_read_close, | 
		
	
		
			
			|  |  |  | .extensions     = "txt", | 
		
	
		
			
			|  |  |  | }; |