00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
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
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
00075
00076
00077
00078
00079
00080
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
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
00117 if (p->size < p->len + len) {
00118 p->size *= 2;
00119 p->buf = realloc(p->buf, p->size);
00120 }
00121
00122
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
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 }