|
MythTV
0.26-pre
|
00001 /* 00002 * This file is part of libbluray 00003 * Copyright (C) 2010 hpi1 00004 * 00005 * This library is free software; you can redistribute it and/or 00006 * modify it under the terms of the GNU Lesser General Public 00007 * License as published by the Free Software Foundation; either 00008 * version 2.1 of the License, or (at your option) any later version. 00009 * 00010 * This library is distributed in the hope that it will be useful, 00011 * but WITHOUT ANY WARRANTY; without even the implied warranty of 00012 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 00013 * Lesser General Public License for more details. 00014 * 00015 * You should have received a copy of the GNU Lesser General Public 00016 * License along with this library. If not, see 00017 * <http://www.gnu.org/licenses/>. 00018 */ 00019 00020 #include "m2ts_demux.h" 00021 #include "pes_buffer.h" 00022 00023 #include "util/logging.h" 00024 #include "util/macro.h" 00025 00026 #include <stdlib.h> 00027 #include <string.h> 00028 00029 /*#define M2TS_TRACE(...) BD_DEBUG(DBG_CRIT,__VA_ARGS__)*/ 00030 #define M2TS_TRACE(...) do {} while(0) 00031 00032 /* 00033 * 00034 */ 00035 00036 struct m2ts_demux_s 00037 { 00038 uint16_t pid; 00039 uint32_t pes_length; 00040 PES_BUFFER *buf; 00041 }; 00042 00043 M2TS_DEMUX *m2ts_demux_init(uint16_t pid) 00044 { 00045 M2TS_DEMUX *p = calloc(1, sizeof(*p)); 00046 00047 if (p) { 00048 p->pid = pid; 00049 } 00050 00051 return p; 00052 } 00053 00054 void m2ts_demux_free(M2TS_DEMUX **p) 00055 { 00056 if (p && *p) { 00057 pes_buffer_free(&(*p)->buf); 00058 X_FREE(*p); 00059 } 00060 } 00061 00062 static int64_t _parse_timestamp(uint8_t *p) 00063 { 00064 int64_t ts; 00065 ts = ((int64_t)(p[0] & 0x0E)) << 29; 00066 ts |= p[1] << 22; 00067 ts |= (p[2] & 0xFE) << 14; 00068 ts |= p[3] << 7; 00069 ts |= (p[4] & 0xFE) >> 1; 00070 return ts; 00071 } 00072 00073 /* 00074 * _add_ts() 00075 * - add ts payload to buffer. 00076 * - parse PES header if pusi is set. 00077 * - return: 00078 * < 0 error (incorrect PES header) 00079 * = 0 PES packet continue 00080 * > 0 PES packet payload length from PES header 00081 */ 00082 static int _add_ts(PES_BUFFER *p, unsigned pusi, uint8_t *buf, unsigned len) 00083 { 00084 int result = 0; 00085 00086 if (pusi) { 00087 // Parse PES header 00088 unsigned pes_length = buf[4] << 8 | buf[5]; 00089 unsigned pts_exists = buf[7] & 0x80; 00090 unsigned dts_exists = buf[7] & 0x40; 00091 unsigned hdr_len = buf[8] + 9; 00092 00093 if (buf[0] || buf[1] || buf[2] != 1) { 00094 BD_DEBUG(DBG_DECODE, "invalid PES header (00 00 01)"); 00095 return -1; 00096 } 00097 00098 if (len < hdr_len) { 00099 BD_DEBUG(DBG_DECODE, "invalid BDAV TS (PES header not in single TS packet)\n"); 00100 return -1; 00101 } 00102 00103 if (pts_exists) { 00104 p->pts = _parse_timestamp(buf + 9); 00105 } 00106 if (dts_exists) { 00107 p->dts = _parse_timestamp(buf + 14); 00108 } 00109 00110 buf += hdr_len; 00111 len -= hdr_len; 00112 00113 result = pes_length + 6 - hdr_len; 00114 } 00115 00116 // realloc 00117 if (p->size < p->len + len) { 00118 p->size *= 2; 00119 p->buf = realloc(p->buf, p->size); 00120 } 00121 00122 // append 00123 memcpy(p->buf + p->len, buf, len); 00124 p->len += len; 00125 00126 return result; 00127 } 00128 00129 PES_BUFFER *m2ts_demux(M2TS_DEMUX *p, uint8_t *buf) 00130 { 00131 uint8_t *end = buf + 6144; 00132 PES_BUFFER *result = NULL; 00133 00134 if (!buf) { 00135 // flush 00136 result = p->buf; 00137 p->buf = NULL; 00138 return result; 00139 } 00140 00141 for (; buf < end; buf += 192) { 00142 00143 unsigned tp_error = buf[4+1] & 0x80; 00144 unsigned pusi = buf[4+1] & 0x40; 00145 uint16_t pid = ((buf[4+1] & 0x1f) << 8) | buf[4+2]; 00146 unsigned payload_exists = buf[4+3] & 0x10; 00147 int payload_offset = (buf[4+3] & 0x20) ? buf[4+4] + 5 : 4; 00148 00149 if (buf[4] != 0x47) { 00150 BD_DEBUG(DBG_DECODE, "missing sync byte. scrambled data ?\n"); 00151 return NULL; 00152 } 00153 if (pid != p->pid) { 00154 M2TS_TRACE("skipping packet (pid %d)\n", pid); 00155 continue; 00156 } 00157 if (tp_error) { 00158 BD_DEBUG(DBG_DECODE, "skipping packet (transport error)\n"); 00159 continue; 00160 } 00161 if (!payload_exists) { 00162 M2TS_TRACE("skipping packet (no payload)\n"); 00163 continue; 00164 } 00165 if (payload_offset >= 188) { 00166 BD_DEBUG(DBG_DECODE, "skipping packet (invalid payload start address)\n"); 00167 continue; 00168 } 00169 00170 if (pusi) { 00171 if (p->buf) { 00172 BD_DEBUG(DBG_DECODE, "PES length mismatch: have %d, expected %d\n", 00173 p->buf->len, p->pes_length); 00174 pes_buffer_free(&p->buf); 00175 } 00176 p->buf = pes_buffer_alloc(0xffff); 00177 } 00178 00179 if (!p->buf) { 00180 BD_DEBUG(DBG_DECODE, "skipping packet (no pusi seen)\n"); 00181 continue; 00182 } 00183 00184 int r = _add_ts(p->buf, pusi, buf + 4 + payload_offset, 188 - payload_offset); 00185 if (r) { 00186 if (r < 0) { 00187 BD_DEBUG(DBG_DECODE, "skipping block (PES header error)\n"); 00188 pes_buffer_free(&p->buf); 00189 continue; 00190 } 00191 p->pes_length = r; 00192 } 00193 00194 if (p->buf->len == p->pes_length) { 00195 M2TS_TRACE("PES complete (%d bytes)\n", p->pes_length); 00196 pes_buffer_append(&result, p->buf); 00197 p->buf = NULL; 00198 } 00199 } 00200 00201 return result; 00202 }
1.7.6.1