Mercurial > libavformat.hg
annotate assdec.c @ 6314:d907dafa4c5d libavformat
add mime-type for ASS muxer
author | aurel |
---|---|
date | Sun, 25 Jul 2010 19:36:20 +0000 |
parents | af30d878f7d7 |
children | 8788871cbc99 |
rev | line source |
---|---|
3942 | 1 /* |
2 * SSA/ASS demuxer | |
3 * Copyright (c) 2008 Michael Niedermayer | |
4 * | |
5 * This file is part of FFmpeg. | |
6 * | |
7 * FFmpeg is free software; you can redistribute it and/or | |
8 * modify it under the terms of the GNU Lesser General Public | |
9 * License as published by the Free Software Foundation; either | |
10 * version 2.1 of the License, or (at your option) any later version. | |
11 * | |
12 * FFmpeg is distributed in the hope that it will be useful, | |
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of | |
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | |
15 * Lesser General Public License for more details. | |
16 * | |
17 * You should have received a copy of the GNU Lesser General Public | |
18 * License along with FFmpeg; if not, write to the Free Software | |
19 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA | |
20 */ | |
21 | |
22 #include "avformat.h" | |
6300 | 23 #include "internal.h" |
3942 | 24 |
25 #define MAX_LINESIZE 2000 | |
26 | |
27 typedef struct ASSContext{ | |
28 uint8_t *event_buffer; | |
29 uint8_t **event; | |
30 unsigned int event_count; | |
31 unsigned int event_index; | |
32 }ASSContext; | |
33 | |
34 static int probe(AVProbeData *p) | |
35 { | |
36 const char *header= "[Script Info]"; | |
37 | |
38 if( !memcmp(p->buf , header, strlen(header)) | |
39 || !memcmp(p->buf+3, header, strlen(header))) | |
40 return AVPROBE_SCORE_MAX; | |
41 | |
42 return 0; | |
43 } | |
44 | |
45 static int read_close(AVFormatContext *s) | |
46 { | |
47 ASSContext *ass = s->priv_data; | |
48 | |
49 av_freep(&ass->event_buffer); | |
50 av_freep(&ass->event); | |
51 | |
52 return 0; | |
53 } | |
54 | |
55 static int64_t get_pts(const uint8_t *p) | |
56 { | |
57 int hour, min, sec, hsec; | |
58 | |
59 if(sscanf(p, "%*[^,],%d:%d:%d%*c%d", &hour, &min, &sec, &hsec) != 4) | |
60 return AV_NOPTS_VALUE; | |
61 | |
62 // av_log(NULL, AV_LOG_ERROR, "%d %d %d %d %d [%s]\n", i, hour, min, sec, hsec, p); | |
63 | |
64 min+= 60*hour; | |
65 sec+= 60*min; | |
66 | |
67 return sec*100+hsec; | |
68 } | |
69 | |
70 static int event_cmp(uint8_t **a, uint8_t **b) | |
71 { | |
72 return get_pts(*a) - get_pts(*b); | |
73 } | |
74 | |
75 static int read_header(AVFormatContext *s, AVFormatParameters *ap) | |
76 { | |
6303 | 77 int i, len, header_remaining; |
3942 | 78 ASSContext *ass = s->priv_data; |
79 ByteIOContext *pb = s->pb; | |
80 AVStream *st; | |
81 int allocated[2]={0}; | |
82 uint8_t *p, **dst[2]={0}; | |
83 int pos[2]={0}; | |
84 | |
85 st = av_new_stream(s, 0); | |
86 if (!st) | |
87 return -1; | |
88 av_set_pts_info(st, 64, 1, 100); | |
5910
536e5527c1e0
Define AVMediaType enum, and use it instead of enum CodecType, which
stefano
parents:
4484
diff
changeset
|
89 st->codec->codec_type = AVMEDIA_TYPE_SUBTITLE; |
3942 | 90 st->codec->codec_id= CODEC_ID_SSA; |
91 | |
92 header_remaining= INT_MAX; | |
93 dst[0] = &st->codec->extradata; | |
94 dst[1] = &ass->event_buffer; | |
95 while(!url_feof(pb)){ | |
96 uint8_t line[MAX_LINESIZE]; | |
97 | |
6303 | 98 len = ff_get_line(pb, line, sizeof(line)); |
3942 | 99 |
100 if(!memcmp(line, "[Events]", 8)) | |
101 header_remaining= 2; | |
102 else if(line[0]=='[') | |
103 header_remaining= INT_MAX; | |
104 | |
105 i= header_remaining==0; | |
106 | |
107 if(i && get_pts(line) == AV_NOPTS_VALUE) | |
108 continue; | |
109 | |
110 p = av_fast_realloc(*(dst[i]), &allocated[i], pos[i]+MAX_LINESIZE); | |
111 if(!p) | |
112 goto fail; | |
113 *(dst[i])= p; | |
6303 | 114 memcpy(p + pos[i], line, len+1); |
115 pos[i] += len; | |
3942 | 116 if(i) ass->event_count++; |
117 else header_remaining--; | |
118 } | |
119 st->codec->extradata_size= pos[0]; | |
120 | |
121 if(ass->event_count >= UINT_MAX / sizeof(*ass->event)) | |
122 goto fail; | |
123 | |
124 ass->event= av_malloc(ass->event_count * sizeof(*ass->event)); | |
125 p= ass->event_buffer; | |
126 for(i=0; i<ass->event_count; i++){ | |
127 ass->event[i]= p; | |
128 while(*p && *p != '\n') | |
129 p++; | |
3943 | 130 p++; |
3942 | 131 } |
132 | |
4484
da64b6d7a2d9
Silence "assdec.c:146: warning: passing argument 4 of ¡Æqsort¡Ç from incompatible pointer type"
michael
parents:
3950
diff
changeset
|
133 qsort(ass->event, ass->event_count, sizeof(*ass->event), (void*)event_cmp); |
3942 | 134 |
135 return 0; | |
136 | |
137 fail: | |
138 read_close(s); | |
139 | |
140 return -1; | |
141 } | |
142 | |
143 static int read_packet(AVFormatContext *s, AVPacket *pkt) | |
144 { | |
145 ASSContext *ass = s->priv_data; | |
3943 | 146 uint8_t *p, *end; |
3942 | 147 |
148 if(ass->event_index >= ass->event_count) | |
149 return AVERROR(EIO); | |
150 | |
151 p= ass->event[ ass->event_index ]; | |
152 | |
3943 | 153 end= strchr(p, '\n'); |
154 av_new_packet(pkt, end ? end-p+1 : strlen(p)); | |
5913
11bb10c37225
Replace all occurences of PKT_FLAG_KEY with AV_PKT_FLAG_KEY.
cehoyos
parents:
5910
diff
changeset
|
155 pkt->flags |= AV_PKT_FLAG_KEY; |
3942 | 156 pkt->pos= p - ass->event_buffer + s->streams[0]->codec->extradata_size; |
157 pkt->pts= pkt->dts= get_pts(p); | |
158 memcpy(pkt->data, p, pkt->size); | |
159 | |
160 ass->event_index++; | |
161 | |
162 return 0; | |
163 } | |
164 | |
165 AVInputFormat ass_demuxer = { | |
166 "ass", | |
6241 | 167 NULL_IF_CONFIG_SMALL("Advanced SubStation Alpha subtitle format"), |
3942 | 168 sizeof(ASSContext), |
169 probe, | |
170 read_header, | |
171 read_packet, | |
172 read_close, | |
173 // read_seek, | |
174 }; |