Update to MPlayer SVN rev 29473 and FFmpeg SVN rev 19572.
[vaapi:athaifas-mplayer.git] / libavcodec / .svn / text-base / dvbsub_parser.c.svn-base
1 /*
2  * DVB subtitle parser for FFmpeg
3  * Copyright (c) 2005 Ian Caulfield
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 #include "avcodec.h"
22 #include "dsputil.h"
23 #include "get_bits.h"
24
25 //#define DEBUG
26 //#define DEBUG_PACKET_CONTENTS
27
28 /* Parser (mostly) copied from dvdsub.c */
29
30 #define PARSE_BUF_SIZE  (65536)
31
32
33 /* parser definition */
34 typedef struct DVBSubParseContext {
35     uint8_t *packet_buf;
36     int packet_start;
37     int packet_index;
38     int in_packet;
39 } DVBSubParseContext;
40
41 static av_cold int dvbsub_parse_init(AVCodecParserContext *s)
42 {
43     DVBSubParseContext *pc = s->priv_data;
44     pc->packet_buf = av_malloc(PARSE_BUF_SIZE);
45
46     return 0;
47 }
48
49 static int dvbsub_parse(AVCodecParserContext *s,
50                         AVCodecContext *avctx,
51                         const uint8_t **poutbuf, int *poutbuf_size,
52                         const uint8_t *buf, int buf_size)
53 {
54     DVBSubParseContext *pc = s->priv_data;
55     uint8_t *p, *p_end;
56     int len, buf_pos = 0;
57
58     dprintf(avctx, "DVB parse packet pts=%"PRIx64", lpts=%"PRIx64", cpts=%"PRIx64":\n",
59             s->pts, s->last_pts, s->cur_frame_pts[s->cur_frame_start_index]);
60
61 #ifdef DEBUG_PACKET_CONTENTS
62     int i;
63
64     for (i=0; i < buf_size; i++)
65     {
66         av_log(avctx, AV_LOG_INFO, "%02x ", buf[i]);
67         if (i % 16 == 15)
68             av_log(avctx, AV_LOG_INFO, "\n");
69     }
70
71     if (i % 16 != 0)
72         av_log(avctx, AV_LOG_INFO, "\n");
73
74 #endif
75
76     *poutbuf = NULL;
77     *poutbuf_size = 0;
78
79     s->fetch_timestamp = 1;
80
81     if (s->last_pts != s->pts && s->pts != AV_NOPTS_VALUE) /* Start of a new packet */
82     {
83         if (pc->packet_index != pc->packet_start)
84         {
85             dprintf(avctx, "Discarding %d bytes\n",
86                     pc->packet_index - pc->packet_start);
87         }
88
89         pc->packet_start = 0;
90         pc->packet_index = 0;
91
92         if (buf_size < 2 || buf[0] != 0x20 || buf[1] != 0x00) {
93             dprintf(avctx, "Bad packet header\n");
94             return -1;
95         }
96
97         buf_pos = 2;
98
99         pc->in_packet = 1;
100     } else {
101         if (pc->packet_start != 0)
102         {
103             if (pc->packet_index != pc->packet_start)
104             {
105                 memmove(pc->packet_buf, pc->packet_buf + pc->packet_start,
106                             pc->packet_index - pc->packet_start);
107
108                 pc->packet_index -= pc->packet_start;
109                 pc->packet_start = 0;
110             } else {
111                 pc->packet_start = 0;
112                 pc->packet_index = 0;
113             }
114         }
115     }
116
117     if (buf_size - buf_pos + pc->packet_index > PARSE_BUF_SIZE)
118         return -1;
119
120 /* if not currently in a packet, discard data */
121     if (pc->in_packet == 0)
122         return buf_size;
123
124     memcpy(pc->packet_buf + pc->packet_index, buf + buf_pos, buf_size - buf_pos);
125     pc->packet_index += buf_size - buf_pos;
126
127     p = pc->packet_buf;
128     p_end = pc->packet_buf + pc->packet_index;
129
130     while (p < p_end)
131     {
132         if (*p == 0x0f)
133         {
134             if (p + 6 <= p_end)
135             {
136                 len = AV_RB16(p + 4);
137
138                 if (p + len + 6 <= p_end)
139                 {
140                     *poutbuf_size += len + 6;
141
142                     p += len + 6;
143                 } else
144                     break;
145             } else
146                 break;
147         } else if (*p == 0xff) {
148             if (p + 1 < p_end)
149             {
150                 dprintf(avctx, "Junk at end of packet\n");
151             }
152             pc->packet_index = p - pc->packet_buf;
153             pc->in_packet = 0;
154             break;
155         } else {
156             av_log(avctx, AV_LOG_ERROR, "Junk in packet\n");
157
158             pc->packet_index = p - pc->packet_buf;
159             pc->in_packet = 0;
160             break;
161         }
162     }
163
164     if (*poutbuf_size > 0)
165     {
166         *poutbuf = pc->packet_buf;
167         pc->packet_start = *poutbuf_size;
168     }
169
170     if (s->pts == AV_NOPTS_VALUE)
171         s->pts = s->last_pts;
172
173     return buf_size;
174 }
175
176 static av_cold void dvbsub_parse_close(AVCodecParserContext *s)
177 {
178     DVBSubParseContext *pc = s->priv_data;
179     av_freep(&pc->packet_buf);
180 }
181
182 AVCodecParser dvbsub_parser = {
183     { CODEC_ID_DVB_SUBTITLE },
184     sizeof(DVBSubParseContext),
185     dvbsub_parse_init,
186     dvbsub_parse,
187     dvbsub_parse_close,
188 };