Libav 0.7.1
|
00001 /* 00002 * DVB subtitle parser for Libav 00003 * Copyright (c) 2005 Ian Caulfield 00004 * 00005 * This file is part of Libav. 00006 * 00007 * Libav is free software; you can redistribute it and/or 00008 * modify it under the terms of the GNU Lesser General Public 00009 * License as published by the Free Software Foundation; either 00010 * version 2.1 of the License, or (at your option) any later version. 00011 * 00012 * Libav is distributed in the hope that it will be useful, 00013 * but WITHOUT ANY WARRANTY; without even the implied warranty of 00014 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 00015 * Lesser General Public License for more details. 00016 * 00017 * You should have received a copy of the GNU Lesser General Public 00018 * License along with Libav; if not, write to the Free Software 00019 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 00020 */ 00021 #include "avcodec.h" 00022 #include "dsputil.h" 00023 #include "get_bits.h" 00024 00025 /* Parser (mostly) copied from dvdsub.c */ 00026 00027 #define PARSE_BUF_SIZE (65536) 00028 00029 00030 /* parser definition */ 00031 typedef struct DVBSubParseContext { 00032 uint8_t *packet_buf; 00033 int packet_start; 00034 int packet_index; 00035 int in_packet; 00036 } DVBSubParseContext; 00037 00038 static av_cold int dvbsub_parse_init(AVCodecParserContext *s) 00039 { 00040 DVBSubParseContext *pc = s->priv_data; 00041 pc->packet_buf = av_malloc(PARSE_BUF_SIZE); 00042 00043 return 0; 00044 } 00045 00046 static int dvbsub_parse(AVCodecParserContext *s, 00047 AVCodecContext *avctx, 00048 const uint8_t **poutbuf, int *poutbuf_size, 00049 const uint8_t *buf, int buf_size) 00050 { 00051 DVBSubParseContext *pc = s->priv_data; 00052 uint8_t *p, *p_end; 00053 int i, len, buf_pos = 0; 00054 00055 av_dlog(avctx, "DVB parse packet pts=%"PRIx64", lpts=%"PRIx64", cpts=%"PRIx64":\n", 00056 s->pts, s->last_pts, s->cur_frame_pts[s->cur_frame_start_index]); 00057 00058 for (i=0; i < buf_size; i++) 00059 { 00060 av_dlog(avctx, "%02x ", buf[i]); 00061 if (i % 16 == 15) 00062 av_dlog(avctx, "\n"); 00063 } 00064 00065 if (i % 16 != 0) 00066 av_dlog(avctx, "\n"); 00067 00068 *poutbuf = NULL; 00069 *poutbuf_size = 0; 00070 00071 s->fetch_timestamp = 1; 00072 00073 if (s->last_pts != s->pts && s->pts != AV_NOPTS_VALUE) /* Start of a new packet */ 00074 { 00075 if (pc->packet_index != pc->packet_start) 00076 { 00077 av_dlog(avctx, "Discarding %d bytes\n", 00078 pc->packet_index - pc->packet_start); 00079 } 00080 00081 pc->packet_start = 0; 00082 pc->packet_index = 0; 00083 00084 if (buf_size < 2 || buf[0] != 0x20 || buf[1] != 0x00) { 00085 av_dlog(avctx, "Bad packet header\n"); 00086 return -1; 00087 } 00088 00089 buf_pos = 2; 00090 00091 pc->in_packet = 1; 00092 } else { 00093 if (pc->packet_start != 0) 00094 { 00095 if (pc->packet_index != pc->packet_start) 00096 { 00097 memmove(pc->packet_buf, pc->packet_buf + pc->packet_start, 00098 pc->packet_index - pc->packet_start); 00099 00100 pc->packet_index -= pc->packet_start; 00101 pc->packet_start = 0; 00102 } else { 00103 pc->packet_start = 0; 00104 pc->packet_index = 0; 00105 } 00106 } 00107 } 00108 00109 if (buf_size - buf_pos + pc->packet_index > PARSE_BUF_SIZE) 00110 return -1; 00111 00112 /* if not currently in a packet, discard data */ 00113 if (pc->in_packet == 0) 00114 return buf_size; 00115 00116 memcpy(pc->packet_buf + pc->packet_index, buf + buf_pos, buf_size - buf_pos); 00117 pc->packet_index += buf_size - buf_pos; 00118 00119 p = pc->packet_buf; 00120 p_end = pc->packet_buf + pc->packet_index; 00121 00122 while (p < p_end) 00123 { 00124 if (*p == 0x0f) 00125 { 00126 if (p + 6 <= p_end) 00127 { 00128 len = AV_RB16(p + 4); 00129 00130 if (p + len + 6 <= p_end) 00131 { 00132 *poutbuf_size += len + 6; 00133 00134 p += len + 6; 00135 } else 00136 break; 00137 } else 00138 break; 00139 } else if (*p == 0xff) { 00140 if (p + 1 < p_end) 00141 { 00142 av_dlog(avctx, "Junk at end of packet\n"); 00143 } 00144 pc->packet_index = p - pc->packet_buf; 00145 pc->in_packet = 0; 00146 break; 00147 } else { 00148 av_log(avctx, AV_LOG_ERROR, "Junk in packet\n"); 00149 00150 pc->packet_index = p - pc->packet_buf; 00151 pc->in_packet = 0; 00152 break; 00153 } 00154 } 00155 00156 if (*poutbuf_size > 0) 00157 { 00158 *poutbuf = pc->packet_buf; 00159 pc->packet_start = *poutbuf_size; 00160 } 00161 00162 if (s->pts == AV_NOPTS_VALUE) 00163 s->pts = s->last_pts; 00164 00165 return buf_size; 00166 } 00167 00168 static av_cold void dvbsub_parse_close(AVCodecParserContext *s) 00169 { 00170 DVBSubParseContext *pc = s->priv_data; 00171 av_freep(&pc->packet_buf); 00172 } 00173 00174 AVCodecParser ff_dvbsub_parser = { 00175 { CODEC_ID_DVB_SUBTITLE }, 00176 sizeof(DVBSubParseContext), 00177 dvbsub_parse_init, 00178 dvbsub_parse, 00179 dvbsub_parse_close, 00180 };