Lines 32-37
Link Here
|
32 |
* |
32 |
* |
33 |
* Date Author |
33 |
* Date Author |
34 |
* ---- ------ |
34 |
* ---- ------ |
|
|
35 |
* |
36 |
* 8-Apr-2009 Petri Hintukainen <phi@sdf-eu.org> |
37 |
* - support for 192-byte packets (HDMV/BluRay) |
38 |
* - support for audio inside PES PID 0xfd (HDMV/BluRay) |
35 |
* |
39 |
* |
36 |
* 28-Nov-2004 Mike Lampard <mlampard> |
40 |
* 28-Nov-2004 Mike Lampard <mlampard> |
37 |
* - Added support for PMT sections larger than 1 ts packet |
41 |
* - Added support for PMT sections larger than 1 ts packet |
Lines 172-180
Link Here
|
172 |
#define SYNC_BYTE 0x47 |
176 |
#define SYNC_BYTE 0x47 |
173 |
|
177 |
|
174 |
#define MIN_SYNCS 3 |
178 |
#define MIN_SYNCS 3 |
175 |
#define NPKT_PER_READ 100 |
179 |
#define NPKT_PER_READ 96 // 96*188 = 94*192 |
176 |
|
180 |
|
177 |
#define BUF_SIZE (NPKT_PER_READ * PKT_SIZE) |
181 |
#define BUF_SIZE (NPKT_PER_READ * (PKT_SIZE + 4)) |
178 |
|
182 |
|
179 |
#define MAX_PES_BUF_SIZE 2048 |
183 |
#define MAX_PES_BUF_SIZE 2048 |
180 |
|
184 |
|
Lines 220-225
Link Here
|
220 |
ISO_14496_PART10_VIDEO = 0x1b, /* ISO/IEC 14496-10 Video (MPEG-4 part 10/AVC, aka H.264) */ |
224 |
ISO_14496_PART10_VIDEO = 0x1b, /* ISO/IEC 14496-10 Video (MPEG-4 part 10/AVC, aka H.264) */ |
221 |
STREAM_VIDEO_MPEG = 0x80, |
225 |
STREAM_VIDEO_MPEG = 0x80, |
222 |
STREAM_AUDIO_AC3 = 0x81, |
226 |
STREAM_AUDIO_AC3 = 0x81, |
|
|
227 |
STREAM_SPU_HDMV = 0x90, |
223 |
} streamType; |
228 |
} streamType; |
224 |
|
229 |
|
225 |
#define WRAP_THRESHOLD 270000 |
230 |
#define WRAP_THRESHOLD 270000 |
Lines 287-292
Link Here
|
287 |
input_plugin_t *input; |
292 |
input_plugin_t *input; |
288 |
|
293 |
|
289 |
int status; |
294 |
int status; |
|
|
295 |
|
296 |
int hdmv; /* -1 = unknown, 0 = mpeg-ts, 1 = hdmv/m2ts */ |
297 |
int pkt_size; /* TS packet size */ |
298 |
int pkt_offset; /* TS packet offset */ |
290 |
|
299 |
|
291 |
int blockSize; |
300 |
int blockSize; |
292 |
int rate; |
301 |
int rate; |
Lines 446-457
Link Here
|
446 |
} |
455 |
} |
447 |
|
456 |
|
448 |
/* Send a BUF_SPU_DVB to let xine know of that channel. */ |
457 |
/* Send a BUF_SPU_DVB to let xine know of that channel. */ |
449 |
static void demux_send_special_spu_buf( demux_ts_t *this, int spu_channel ) |
458 |
static void demux_send_special_spu_buf( demux_ts_t *this, uint32_t spu_type, int spu_channel ) |
450 |
{ |
459 |
{ |
451 |
buf_element_t *buf; |
460 |
buf_element_t *buf; |
452 |
|
461 |
|
453 |
buf = this->video_fifo->buffer_pool_alloc( this->video_fifo ); |
462 |
buf = this->video_fifo->buffer_pool_alloc( this->video_fifo ); |
454 |
buf->type = BUF_SPU_DVB|spu_channel; |
463 |
buf->type = spu_type|spu_channel; |
455 |
buf->content = buf->mem; |
464 |
buf->content = buf->mem; |
456 |
buf->size = 0; |
465 |
buf->size = 0; |
457 |
this->video_fifo->put( this->video_fifo, buf ); |
466 |
this->video_fifo->put( this->video_fifo, buf ); |
Lines 741-747
Link Here
|
741 |
p += header_len + 9; |
750 |
p += header_len + 9; |
742 |
packet_len -= header_len + 3; |
751 |
packet_len -= header_len + 3; |
743 |
|
752 |
|
744 |
if (stream_id == 0xbd) { |
753 |
if (stream_id == 0xbd || stream_id == 0xfd /* HDMV */) { |
745 |
|
754 |
|
746 |
int spu_id; |
755 |
int spu_id; |
747 |
|
756 |
|
Lines 1291-1296
Link Here
|
1291 |
return; |
1300 |
return; |
1292 |
} |
1301 |
} |
1293 |
|
1302 |
|
|
|
1303 |
#ifdef TS_PMT_LOG |
1304 |
printf ("demux_ts: PMT: pid: 0x%.4x stream_type: 0x%.2x info_length: %d", |
1305 |
pid, stream[0], stream_info_length); |
1306 |
if (stream_info_length > 0) { |
1307 |
printf (" info: "); |
1308 |
int ind; |
1309 |
for (ind = 5; ind < coded_length; ind++) |
1310 |
printf ("%.2x ", stream[ind]); |
1311 |
for (ind = 5; ind < coded_length; ind++) |
1312 |
printf ("%c", stream[ind] >= 32 && stream[ind] < 127 ? stream[ind] : '.'); |
1313 |
} |
1314 |
printf ("\n"); |
1315 |
#endif |
1316 |
|
1294 |
/* |
1317 |
/* |
1295 |
* Squirrel away the first audio and the first video stream. TBD: there |
1318 |
* Squirrel away the first audio and the first video stream. TBD: there |
1296 |
* should really be a way to select the stream of interest. |
1319 |
* should really be a way to select the stream of interest. |
Lines 1413-1419
Link Here
|
1413 |
lang->media_index = this->media_num; |
1436 |
lang->media_index = this->media_num; |
1414 |
this->media[this->media_num].type = no; |
1437 |
this->media[this->media_num].type = no; |
1415 |
demux_ts_pes_new(this, this->media_num, pid, this->video_fifo, stream[0]); |
1438 |
demux_ts_pes_new(this, this->media_num, pid, this->video_fifo, stream[0]); |
1416 |
demux_send_special_spu_buf( this, no ); |
1439 |
demux_send_special_spu_buf( this, BUF_SPU_DVB, no ); |
1417 |
#ifdef TS_LOG |
1440 |
#ifdef TS_LOG |
1418 |
printf("demux_ts: DVBSUB: pid 0x%.4x: %s page %ld %ld type %2.2x\n", |
1441 |
printf("demux_ts: DVBSUB: pid 0x%.4x: %s page %ld %ld type %2.2x\n", |
1419 |
pid, lang->desc.lang, |
1442 |
pid, lang->desc.lang, |
Lines 1426-1431
Link Here
|
1426 |
} |
1449 |
} |
1427 |
break; |
1450 |
break; |
1428 |
|
1451 |
|
|
|
1452 |
case STREAM_SPU_HDMV: |
1453 |
if (this->hdmv > 0) { |
1454 |
if (pid >= 0x1200 && pid < 0x1300) { |
1455 |
#if 0 /* disabled: no HDMV SPU decoder yet */ |
1456 |
/* HDMV Presentation Graphics / SPU */ |
1457 |
demux_ts_spu_lang *lang = &this->spu_langs[this->spu_langs_count]; |
1458 |
|
1459 |
memset(lang->desc.lang, 0, sizeof(lang->desc.lang)); |
1460 |
/*memcpy(lang->desc.lang, &stream[pos], 3);*/ |
1461 |
/*lang->desc.lang[3] = 0;*/ |
1462 |
lang->pid = pid; |
1463 |
lang->media_index = this->media_num; |
1464 |
this->media[this->media_num].type = this->spu_langs_count; |
1465 |
demux_ts_pes_new(this, this->media_num, pid, this->video_fifo, stream[0]); |
1466 |
demux_send_special_spu_buf( this, BUF_SPU_HDMV, this->spu_langs_count ); |
1467 |
this->spu_langs_count++; |
1468 |
#endif |
1469 |
#ifdef TS_PMT_LOG |
1470 |
printf("demux_ts: HDMV subtitle stream_type: 0x%.2x pid: 0x%.4x\n", |
1471 |
stream[0], pid); |
1472 |
#endif |
1473 |
break; |
1474 |
} |
1475 |
} |
1476 |
/* fall thru */ |
1429 |
default: |
1477 |
default: |
1430 |
|
1478 |
|
1431 |
/* This following section handles all the cases where the audio track info is stored in PMT user info with stream id >= 0x80 |
1479 |
/* This following section handles all the cases where the audio track info is stored in PMT user info with stream id >= 0x80 |
Lines 1454-1461
Link Here
|
1454 |
this->media[this->media_num].type = this->audio_tracks_count; |
1502 |
this->media[this->media_num].type = this->audio_tracks_count; |
1455 |
demux_ts_get_lang_desc(this, this->audio_tracks[this->audio_tracks_count].lang, |
1503 |
demux_ts_get_lang_desc(this, this->audio_tracks[this->audio_tracks_count].lang, |
1456 |
stream + 5, stream_info_length); |
1504 |
stream + 5, stream_info_length); |
|
|
1505 |
#ifdef TS_PMT_LOG |
1506 |
printf ("demux_ts: PMT AC3? audio stream_type: 0x%.2x pid: 0x%.4x " |
1507 |
"format_identifier: 0x%.8x lang: %s\n", |
1508 |
stream[0], pid, format_identifier, |
1509 |
this->audio_tracks[this->audio_tracks_count].lang); |
1510 |
#endif |
1457 |
this->audio_tracks_count++; |
1511 |
this->audio_tracks_count++; |
1458 |
break; |
1512 |
break; |
|
|
1513 |
} else { |
1514 |
#ifdef TS_PMT_LOG |
1515 |
printf ("demux_ts: PMT unknown stream_type: 0x%.2x pid: 0x%.4x " |
1516 |
"format_identifier: 0x%.8x\n", |
1517 |
stream[0], pid, format_identifier); |
1518 |
#endif |
1459 |
} |
1519 |
} |
1460 |
} |
1520 |
} |
1461 |
} else { |
1521 |
} else { |
Lines 1512-1521
Link Here
|
1512 |
xprintf (this->stream->xine, XINE_VERBOSITY_DEBUG, "demux_ts: about to resync!\n"); |
1572 |
xprintf (this->stream->xine, XINE_VERBOSITY_DEBUG, "demux_ts: about to resync!\n"); |
1513 |
|
1573 |
|
1514 |
for (p=0; p < npkt_read; p++) { |
1574 |
for (p=0; p < npkt_read; p++) { |
1515 |
for(n=0; n < PKT_SIZE; n++) { |
1575 |
for(n=0; n < this->pkt_size; n++) { |
1516 |
sync_ok = 1; |
1576 |
sync_ok = 1; |
1517 |
for (i=0; i < MIN(MIN_SYNCS, npkt_read - p); i++) { |
1577 |
for (i=0; i < MIN(MIN_SYNCS, npkt_read - p); i++) { |
1518 |
if (buf[n + ((i+p) * PKT_SIZE)] != SYNC_BYTE) { |
1578 |
if (buf[this->pkt_offset + n + ((i+p) * this->pkt_size)] != SYNC_BYTE) { |
1519 |
sync_ok = 0; |
1579 |
sync_ok = 0; |
1520 |
break; |
1580 |
break; |
1521 |
} |
1581 |
} |
Lines 1527-1539
Link Here
|
1527 |
|
1587 |
|
1528 |
if (sync_ok) { |
1588 |
if (sync_ok) { |
1529 |
/* Found sync, fill in */ |
1589 |
/* Found sync, fill in */ |
1530 |
memmove(&buf[0], &buf[n + p * PKT_SIZE], |
1590 |
memmove(&buf[0], &buf[n + p * this->pkt_size], |
1531 |
((PKT_SIZE * (npkt_read - p)) - n)); |
1591 |
((this->pkt_size * (npkt_read - p)) - n)); |
1532 |
read_length = this->input->read(this->input, |
1592 |
read_length = this->input->read(this->input, |
1533 |
&buf[(PKT_SIZE * (npkt_read - p)) - n], |
1593 |
&buf[(this->pkt_size * (npkt_read - p)) - n], |
1534 |
n + p * PKT_SIZE); |
1594 |
n + p * this->pkt_size); |
1535 |
/* FIXME: when read_length is not as required... we now stop demuxing */ |
1595 |
/* FIXME: when read_length is not as required... we now stop demuxing */ |
1536 |
if (read_length != (n + p * PKT_SIZE)) { |
1596 |
if (read_length != (n + p * this->pkt_size)) { |
1537 |
xprintf (this->stream->xine, XINE_VERBOSITY_DEBUG, |
1597 |
xprintf (this->stream->xine, XINE_VERBOSITY_DEBUG, |
1538 |
"demux_ts_tsync_correct: sync found, but read failed\n"); |
1598 |
"demux_ts_tsync_correct: sync found, but read failed\n"); |
1539 |
return 0; |
1599 |
return 0; |
Lines 1552-1557
Link Here
|
1552 |
|
1612 |
|
1553 |
sync_ok = 1; |
1613 |
sync_ok = 1; |
1554 |
|
1614 |
|
|
|
1615 |
if (this->hdmv) { |
1616 |
this->pkt_size = PKT_SIZE + 4; /* ts packet + 4-byte header */ |
1617 |
this->pkt_offset = 4; |
1618 |
for (i=0; i < MIN(MIN_SYNCS, npkt_read - 3); i++) { |
1619 |
if (buf[this->pkt_offset + i * this->pkt_size] != SYNC_BYTE) { |
1620 |
sync_ok = 0; |
1621 |
break; |
1622 |
} |
1623 |
} |
1624 |
if (sync_ok) { |
1625 |
if (this->hdmv < 0) { |
1626 |
/* fix npkt_read (packet size is 192, not 188) */ |
1627 |
this->npkt_read = npkt_read * PKT_SIZE / this->pkt_size; |
1628 |
} |
1629 |
this->hdmv = 1; |
1630 |
return sync_ok; |
1631 |
} |
1632 |
if (this->hdmv > 0) |
1633 |
return sync_correct(this, buf, npkt_read); |
1634 |
|
1635 |
/* plain ts */ |
1636 |
this->hdmv = 0; |
1637 |
this->pkt_size = PKT_SIZE; |
1638 |
this->pkt_offset = 0; |
1639 |
} |
1640 |
|
1555 |
for (i=0; i < MIN(MIN_SYNCS, npkt_read); i++) { |
1641 |
for (i=0; i < MIN(MIN_SYNCS, npkt_read); i++) { |
1556 |
if (buf[i * PKT_SIZE] != SYNC_BYTE) { |
1642 |
if (buf[i * PKT_SIZE] != SYNC_BYTE) { |
1557 |
sync_ok = 0; |
1643 |
sync_ok = 0; |
Lines 1575-1589
Link Here
|
1575 |
/* NEW: handle read returning less packets than NPKT_PER_READ... */ |
1661 |
/* NEW: handle read returning less packets than NPKT_PER_READ... */ |
1576 |
do { |
1662 |
do { |
1577 |
read_length = this->input->read(this->input, this->buf, |
1663 |
read_length = this->input->read(this->input, this->buf, |
1578 |
PKT_SIZE * NPKT_PER_READ); |
1664 |
this->pkt_size * NPKT_PER_READ); |
1579 |
if (read_length < 0 || read_length % PKT_SIZE) { |
1665 |
if (read_length < 0 || read_length % this->pkt_size) { |
1580 |
xprintf (this->stream->xine, XINE_VERBOSITY_DEBUG, |
1666 |
xprintf (this->stream->xine, XINE_VERBOSITY_DEBUG, |
1581 |
"demux_ts: read returned %d bytes (not a multiple of %d!)\n", |
1667 |
"demux_ts: read returned %d bytes (not a multiple of %d!)\n", |
1582 |
read_length, PKT_SIZE); |
1668 |
read_length, this->pkt_size); |
1583 |
this->status = DEMUX_FINISHED; |
1669 |
this->status = DEMUX_FINISHED; |
1584 |
return NULL; |
1670 |
return NULL; |
1585 |
} |
1671 |
} |
1586 |
this->npkt_read = read_length / PKT_SIZE; |
1672 |
this->npkt_read = read_length / this->pkt_size; |
1587 |
|
1673 |
|
1588 |
#ifdef TS_READ_STATS |
1674 |
#ifdef TS_READ_STATS |
1589 |
this->rstat[this->npkt_read]++; |
1675 |
this->rstat[this->npkt_read]++; |
Lines 1610-1616
Link Here
|
1610 |
return NULL; |
1696 |
return NULL; |
1611 |
} |
1697 |
} |
1612 |
} |
1698 |
} |
1613 |
return_pointer = &(this->buf)[PKT_SIZE * this->packet_number]; |
1699 |
return_pointer = &(this->buf)[this->pkt_offset + this->pkt_size * this->packet_number]; |
1614 |
this->packet_number++; |
1700 |
this->packet_number++; |
1615 |
return return_pointer; |
1701 |
return return_pointer; |
1616 |
} |
1702 |
} |
Lines 1758-1764
Link Here
|
1758 |
/* |
1844 |
/* |
1759 |
* Discard packets that are obviously bad. |
1845 |
* Discard packets that are obviously bad. |
1760 |
*/ |
1846 |
*/ |
1761 |
if (sync_byte != 0x47) { |
1847 |
if (sync_byte != SYNC_BYTE) { |
1762 |
xprintf (this->stream->xine, XINE_VERBOSITY_DEBUG, |
1848 |
xprintf (this->stream->xine, XINE_VERBOSITY_DEBUG, |
1763 |
"demux error! invalid ts sync byte %.2x\n", sync_byte); |
1849 |
"demux error! invalid ts sync byte %.2x\n", sync_byte); |
1764 |
return; |
1850 |
return; |
Lines 2170-2200
Link Here
|
2170 |
} |
2256 |
} |
2171 |
} |
2257 |
} |
2172 |
|
2258 |
|
|
|
2259 |
static int detect_ts(uint8_t *buf, size_t len, int ts_size) |
2260 |
{ |
2261 |
int i, j; |
2262 |
int try_again, ts_detected = 0; |
2263 |
size_t packs = len / ts_size - 2; |
2173 |
|
2264 |
|
2174 |
static demux_plugin_t *open_plugin (demux_class_t *class_gen, |
2265 |
for (i = 0; i < ts_size; i++) { |
2175 |
xine_stream_t *stream, |
|
|
2176 |
input_plugin_t *input) { |
2177 |
|
2178 |
demux_ts_t *this; |
2179 |
int i; |
2180 |
|
2181 |
switch (stream->content_detection_method) { |
2182 |
|
2183 |
case METHOD_BY_CONTENT: { |
2184 |
uint8_t buf[2069]; |
2185 |
int i, j; |
2186 |
int try_again, ts_detected; |
2187 |
|
2188 |
if (!_x_demux_read_header(input, buf, 2069)) |
2189 |
return NULL; |
2190 |
|
2191 |
ts_detected = 0; |
2192 |
|
2193 |
for (i = 0; i < 188; i++) { |
2194 |
try_again = 0; |
2266 |
try_again = 0; |
2195 |
if (buf[i] == 0x47) { |
2267 |
if (buf[i] == SYNC_BYTE) { |
2196 |
for (j = 1; j <= 10; j++) { |
2268 |
for (j = 1; j < packs; j++) { |
2197 |
if (buf[i + j*188] != 0x47) { |
2269 |
if (buf[i + j*ts_size] != SYNC_BYTE) { |
2198 |
try_again = 1; |
2270 |
try_again = 1; |
2199 |
break; |
2271 |
break; |
2200 |
} |
2272 |
} |
Lines 2208-2220
Link Here
|
2208 |
} |
2280 |
} |
2209 |
} |
2281 |
} |
2210 |
|
2282 |
|
2211 |
if (!ts_detected) |
2283 |
return ts_detected; |
|
|
2284 |
} |
2285 |
|
2286 |
static demux_plugin_t *open_plugin (demux_class_t *class_gen, |
2287 |
xine_stream_t *stream, |
2288 |
input_plugin_t *input) { |
2289 |
|
2290 |
demux_ts_t *this; |
2291 |
int i; |
2292 |
int hdmv = -1; |
2293 |
|
2294 |
switch (stream->content_detection_method) { |
2295 |
|
2296 |
case METHOD_BY_CONTENT: { |
2297 |
uint8_t buf[2069]; |
2298 |
|
2299 |
if (!_x_demux_read_header(input, buf, sizeof(buf))) |
2300 |
return NULL; |
2301 |
|
2302 |
if (detect_ts(buf, sizeof(buf), PKT_SIZE)) |
2303 |
hdmv = 0; |
2304 |
else if (detect_ts(buf, sizeof(buf), PKT_SIZE+4)) |
2305 |
hdmv = 1; |
2306 |
else |
2212 |
return NULL; |
2307 |
return NULL; |
2213 |
} |
2308 |
} |
2214 |
break; |
2309 |
break; |
2215 |
|
2310 |
|
2216 |
case METHOD_BY_EXTENSION: { |
2311 |
case METHOD_BY_EXTENSION: { |
2217 |
const char *const mrl = input->get_mrl (input); |
2312 |
const char *const mrl = input->get_mrl (input); |
|
|
2313 |
|
2314 |
if (_x_demux_check_extension (mrl, "m2ts mts")) |
2315 |
hdmv = 1; |
2316 |
else |
2317 |
hdmv = 0; |
2218 |
|
2318 |
|
2219 |
/* check extension */ |
2319 |
/* check extension */ |
2220 |
const char *const extensions = class_gen->get_extensions (class_gen); |
2320 |
const char *const extensions = class_gen->get_extensions (class_gen); |
Lines 2302-2307
Link Here
|
2302 |
/* dvb */ |
2402 |
/* dvb */ |
2303 |
this->event_queue = xine_event_new_queue (this->stream); |
2403 |
this->event_queue = xine_event_new_queue (this->stream); |
2304 |
|
2404 |
|
|
|
2405 |
/* HDMV */ |
2406 |
this->hdmv = hdmv; |
2407 |
this->pkt_offset = (hdmv > 0) ? 4 : 0; |
2408 |
this->pkt_size = PKT_SIZE + this->pkt_offset; |
2409 |
|
2305 |
this->numPreview=0; |
2410 |
this->numPreview=0; |
2306 |
|
2411 |
|
2307 |
return &this->demux_plugin; |
2412 |
return &this->demux_plugin; |
Lines 2320-2326
Link Here
|
2320 |
} |
2425 |
} |
2321 |
|
2426 |
|
2322 |
static const char *get_extensions (demux_class_t *this_gen) { |
2427 |
static const char *get_extensions (demux_class_t *this_gen) { |
2323 |
return "ts m2t trp"; |
2428 |
return "ts m2t trp m2ts mts"; |
2324 |
} |
2429 |
} |
2325 |
|
2430 |
|
2326 |
static const char *get_mimetypes (demux_class_t *this_gen) { |
2431 |
static const char *get_mimetypes (demux_class_t *this_gen) { |