yading@10
|
1 /*
|
yading@10
|
2 * DVB subtitle parser for FFmpeg
|
yading@10
|
3 * Copyright (c) 2005 Ian Caulfield
|
yading@10
|
4 *
|
yading@10
|
5 * This file is part of FFmpeg.
|
yading@10
|
6 *
|
yading@10
|
7 * FFmpeg is free software; you can redistribute it and/or
|
yading@10
|
8 * modify it under the terms of the GNU Lesser General Public
|
yading@10
|
9 * License as published by the Free Software Foundation; either
|
yading@10
|
10 * version 2.1 of the License, or (at your option) any later version.
|
yading@10
|
11 *
|
yading@10
|
12 * FFmpeg is distributed in the hope that it will be useful,
|
yading@10
|
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
|
yading@10
|
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
yading@10
|
15 * Lesser General Public License for more details.
|
yading@10
|
16 *
|
yading@10
|
17 * You should have received a copy of the GNU Lesser General Public
|
yading@10
|
18 * License along with FFmpeg; if not, write to the Free Software
|
yading@10
|
19 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
yading@10
|
20 */
|
yading@10
|
21 #include "avcodec.h"
|
yading@10
|
22 #include "get_bits.h"
|
yading@10
|
23
|
yading@10
|
24 /* Parser (mostly) copied from dvdsub.c */
|
yading@10
|
25
|
yading@10
|
26 #define PARSE_BUF_SIZE (65536)
|
yading@10
|
27
|
yading@10
|
28
|
yading@10
|
29 /* parser definition */
|
yading@10
|
30 typedef struct DVBSubParseContext {
|
yading@10
|
31 uint8_t *packet_buf;
|
yading@10
|
32 int packet_start;
|
yading@10
|
33 int packet_index;
|
yading@10
|
34 int in_packet;
|
yading@10
|
35 } DVBSubParseContext;
|
yading@10
|
36
|
yading@10
|
37 static av_cold int dvbsub_parse_init(AVCodecParserContext *s)
|
yading@10
|
38 {
|
yading@10
|
39 DVBSubParseContext *pc = s->priv_data;
|
yading@10
|
40 pc->packet_buf = av_malloc(PARSE_BUF_SIZE);
|
yading@10
|
41
|
yading@10
|
42 return 0;
|
yading@10
|
43 }
|
yading@10
|
44
|
yading@10
|
45 static int dvbsub_parse(AVCodecParserContext *s,
|
yading@10
|
46 AVCodecContext *avctx,
|
yading@10
|
47 const uint8_t **poutbuf, int *poutbuf_size,
|
yading@10
|
48 const uint8_t *buf, int buf_size)
|
yading@10
|
49 {
|
yading@10
|
50 DVBSubParseContext *pc = s->priv_data;
|
yading@10
|
51 uint8_t *p, *p_end;
|
yading@10
|
52 int i, len, buf_pos = 0;
|
yading@10
|
53
|
yading@10
|
54 av_dlog(avctx, "DVB parse packet pts=%"PRIx64", lpts=%"PRIx64", cpts=%"PRIx64":\n",
|
yading@10
|
55 s->pts, s->last_pts, s->cur_frame_pts[s->cur_frame_start_index]);
|
yading@10
|
56
|
yading@10
|
57 for (i=0; i < buf_size; i++)
|
yading@10
|
58 {
|
yading@10
|
59 av_dlog(avctx, "%02x ", buf[i]);
|
yading@10
|
60 if (i % 16 == 15)
|
yading@10
|
61 av_dlog(avctx, "\n");
|
yading@10
|
62 }
|
yading@10
|
63
|
yading@10
|
64 if (i % 16 != 0)
|
yading@10
|
65 av_dlog(avctx, "\n");
|
yading@10
|
66
|
yading@10
|
67 *poutbuf = NULL;
|
yading@10
|
68 *poutbuf_size = 0;
|
yading@10
|
69
|
yading@10
|
70 s->fetch_timestamp = 1;
|
yading@10
|
71
|
yading@10
|
72 if (s->last_pts != s->pts && s->pts != AV_NOPTS_VALUE) /* Start of a new packet */
|
yading@10
|
73 {
|
yading@10
|
74 if (pc->packet_index != pc->packet_start)
|
yading@10
|
75 {
|
yading@10
|
76 av_dlog(avctx, "Discarding %d bytes\n",
|
yading@10
|
77 pc->packet_index - pc->packet_start);
|
yading@10
|
78 }
|
yading@10
|
79
|
yading@10
|
80 pc->packet_start = 0;
|
yading@10
|
81 pc->packet_index = 0;
|
yading@10
|
82
|
yading@10
|
83 if (buf_size < 2 || buf[0] != 0x20 || buf[1] != 0x00) {
|
yading@10
|
84 av_dlog(avctx, "Bad packet header\n");
|
yading@10
|
85 return -1;
|
yading@10
|
86 }
|
yading@10
|
87
|
yading@10
|
88 buf_pos = 2;
|
yading@10
|
89
|
yading@10
|
90 pc->in_packet = 1;
|
yading@10
|
91 } else {
|
yading@10
|
92 if (pc->packet_start != 0)
|
yading@10
|
93 {
|
yading@10
|
94 if (pc->packet_index != pc->packet_start)
|
yading@10
|
95 {
|
yading@10
|
96 memmove(pc->packet_buf, pc->packet_buf + pc->packet_start,
|
yading@10
|
97 pc->packet_index - pc->packet_start);
|
yading@10
|
98
|
yading@10
|
99 pc->packet_index -= pc->packet_start;
|
yading@10
|
100 pc->packet_start = 0;
|
yading@10
|
101 } else {
|
yading@10
|
102 pc->packet_start = 0;
|
yading@10
|
103 pc->packet_index = 0;
|
yading@10
|
104 }
|
yading@10
|
105 }
|
yading@10
|
106 }
|
yading@10
|
107
|
yading@10
|
108 if (buf_size - buf_pos + pc->packet_index > PARSE_BUF_SIZE)
|
yading@10
|
109 return -1;
|
yading@10
|
110
|
yading@10
|
111 /* if not currently in a packet, discard data */
|
yading@10
|
112 if (pc->in_packet == 0)
|
yading@10
|
113 return buf_size;
|
yading@10
|
114
|
yading@10
|
115 memcpy(pc->packet_buf + pc->packet_index, buf + buf_pos, buf_size - buf_pos);
|
yading@10
|
116 pc->packet_index += buf_size - buf_pos;
|
yading@10
|
117
|
yading@10
|
118 p = pc->packet_buf;
|
yading@10
|
119 p_end = pc->packet_buf + pc->packet_index;
|
yading@10
|
120
|
yading@10
|
121 while (p < p_end)
|
yading@10
|
122 {
|
yading@10
|
123 if (*p == 0x0f)
|
yading@10
|
124 {
|
yading@10
|
125 if (p + 6 <= p_end)
|
yading@10
|
126 {
|
yading@10
|
127 len = AV_RB16(p + 4);
|
yading@10
|
128
|
yading@10
|
129 if (p + len + 6 <= p_end)
|
yading@10
|
130 {
|
yading@10
|
131 *poutbuf_size += len + 6;
|
yading@10
|
132
|
yading@10
|
133 p += len + 6;
|
yading@10
|
134 } else
|
yading@10
|
135 break;
|
yading@10
|
136 } else
|
yading@10
|
137 break;
|
yading@10
|
138 } else if (*p == 0xff) {
|
yading@10
|
139 if (p + 1 < p_end)
|
yading@10
|
140 {
|
yading@10
|
141 av_dlog(avctx, "Junk at end of packet\n");
|
yading@10
|
142 }
|
yading@10
|
143 pc->packet_index = p - pc->packet_buf;
|
yading@10
|
144 pc->in_packet = 0;
|
yading@10
|
145 break;
|
yading@10
|
146 } else {
|
yading@10
|
147 av_log(avctx, AV_LOG_ERROR, "Junk in packet\n");
|
yading@10
|
148
|
yading@10
|
149 pc->packet_index = p - pc->packet_buf;
|
yading@10
|
150 pc->in_packet = 0;
|
yading@10
|
151 break;
|
yading@10
|
152 }
|
yading@10
|
153 }
|
yading@10
|
154
|
yading@10
|
155 if (*poutbuf_size > 0)
|
yading@10
|
156 {
|
yading@10
|
157 *poutbuf = pc->packet_buf;
|
yading@10
|
158 pc->packet_start = *poutbuf_size;
|
yading@10
|
159 }
|
yading@10
|
160
|
yading@10
|
161 if (s->pts == AV_NOPTS_VALUE)
|
yading@10
|
162 s->pts = s->last_pts;
|
yading@10
|
163
|
yading@10
|
164 return buf_size;
|
yading@10
|
165 }
|
yading@10
|
166
|
yading@10
|
167 static av_cold void dvbsub_parse_close(AVCodecParserContext *s)
|
yading@10
|
168 {
|
yading@10
|
169 DVBSubParseContext *pc = s->priv_data;
|
yading@10
|
170 av_freep(&pc->packet_buf);
|
yading@10
|
171 }
|
yading@10
|
172
|
yading@10
|
173 AVCodecParser ff_dvbsub_parser = {
|
yading@10
|
174 .codec_ids = { AV_CODEC_ID_DVB_SUBTITLE },
|
yading@10
|
175 .priv_data_size = sizeof(DVBSubParseContext),
|
yading@10
|
176 .parser_init = dvbsub_parse_init,
|
yading@10
|
177 .parser_parse = dvbsub_parse,
|
yading@10
|
178 .parser_close = dvbsub_parse_close,
|
yading@10
|
179 };
|