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 22#include <inttypes.h> 23#include <string.h> 24 25#include "libavutil/intreadwrite.h" 26 27#include "avcodec.h" 28 29/* Parser (mostly) copied from dvdsub.c */ 30 31#define PARSE_BUF_SIZE (65536) 32 33 34/* parser definition */ 35typedef struct DVBSubParseContext { 36 int packet_start; 37 int packet_index; 38 int in_packet; 39 uint8_t packet_buf[PARSE_BUF_SIZE]; 40} DVBSubParseContext; 41 42static int dvbsub_parse(AVCodecParserContext *s, 43 AVCodecContext *avctx, 44 const uint8_t **poutbuf, int *poutbuf_size, 45 const uint8_t *buf, int buf_size) 46{ 47 DVBSubParseContext *pc = s->priv_data; 48 uint8_t *p, *p_end; 49 int i, len, buf_pos = 0; 50 int out_size = 0; 51 52 ff_dlog(avctx, "DVB parse packet pts=%"PRIx64", lpts=%"PRIx64", cpts=%"PRIx64":\n", 53 s->pts, s->last_pts, s->cur_frame_pts[s->cur_frame_start_index]); 54 55 for (i=0; i < buf_size; i++) 56 { 57 ff_dlog(avctx, "%02x ", buf[i]); 58 if (i % 16 == 15) 59 ff_dlog(avctx, "\n"); 60 } 61 62 if (i % 16 != 0) 63 ff_dlog(avctx, "\n"); 64 65 *poutbuf = buf; 66 *poutbuf_size = buf_size; 67 68 s->fetch_timestamp = 1; 69 70 if (s->last_pts != s->pts && s->pts != AV_NOPTS_VALUE) /* Start of a new packet */ 71 { 72 if (pc->packet_index != pc->packet_start) 73 { 74 ff_dlog(avctx, "Discarding %d bytes\n", 75 pc->packet_index - pc->packet_start); 76 } 77 78 pc->packet_start = 0; 79 pc->packet_index = 0; 80 81 if (buf_size < 2 || buf[0] != 0x20 || buf[1] != 0x00) { 82 ff_dlog(avctx, "Bad packet header\n"); 83 return buf_size; 84 } 85 86 buf_pos = 2; 87 88 pc->in_packet = 1; 89 } else { 90 if (pc->packet_start != 0) 91 { 92 if (pc->packet_index != pc->packet_start) 93 { 94 memmove(pc->packet_buf, pc->packet_buf + pc->packet_start, 95 pc->packet_index - pc->packet_start); 96 97 pc->packet_index -= pc->packet_start; 98 pc->packet_start = 0; 99 } else { 100 pc->packet_start = 0; 101 pc->packet_index = 0; 102 } 103 } 104 } 105 106 if (buf_size - buf_pos + pc->packet_index > PARSE_BUF_SIZE) 107 return buf_size; 108 109/* if not currently in a packet, pass data */ 110 if (pc->in_packet == 0) 111 return buf_size; 112 113 memcpy(pc->packet_buf + pc->packet_index, buf + buf_pos, buf_size - buf_pos); 114 pc->packet_index += buf_size - buf_pos; 115 116 p = pc->packet_buf; 117 p_end = pc->packet_buf + pc->packet_index; 118 119 while (p < p_end) 120 { 121 if (*p == 0x0f) 122 { 123 if (6 <= p_end - p) 124 { 125 len = AV_RB16(p + 4); 126 127 if (len + 6 <= p_end - p) 128 { 129 out_size += len + 6; 130 131 p += len + 6; 132 } else 133 break; 134 } else 135 break; 136 } else if (*p == 0xff) { 137 if (1 < p_end - p) 138 { 139 ff_dlog(avctx, "Junk at end of packet\n"); 140 } 141 pc->packet_index = p - pc->packet_buf; 142 pc->in_packet = 0; 143 break; 144 } else { 145 av_log(avctx, AV_LOG_ERROR, "Junk in packet\n"); 146 147 pc->packet_index = p - pc->packet_buf; 148 pc->in_packet = 0; 149 break; 150 } 151 } 152 153 if (out_size > 0) 154 { 155 *poutbuf = pc->packet_buf; 156 *poutbuf_size = out_size; 157 pc->packet_start = *poutbuf_size; 158 } 159 160 if (s->pts == AV_NOPTS_VALUE) 161 s->pts = s->last_pts; 162 163 return buf_size; 164} 165 166const AVCodecParser ff_dvbsub_parser = { 167 .codec_ids = { AV_CODEC_ID_DVB_SUBTITLE }, 168 .priv_data_size = sizeof(DVBSubParseContext), 169 .parser_parse = dvbsub_parse, 170}; 171