|
Packit |
5e46da |
/*
|
|
Packit |
5e46da |
* This file is part of libbluray
|
|
Packit |
5e46da |
* Copyright (C) 2009-2010 John Stebbins
|
|
Packit |
5e46da |
* Copyright (C) 2012-2013 Petri Hintukainen <phintuka@users.sourceforge.net>
|
|
Packit |
5e46da |
*
|
|
Packit |
5e46da |
* This library is free software; you can redistribute it and/or
|
|
Packit |
5e46da |
* modify it under the terms of the GNU Lesser General Public
|
|
Packit |
5e46da |
* License as published by the Free Software Foundation; either
|
|
Packit |
5e46da |
* version 2.1 of the License, or (at your option) any later version.
|
|
Packit |
5e46da |
*
|
|
Packit |
5e46da |
* This library is distributed in the hope that it will be useful,
|
|
Packit |
5e46da |
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
Packit |
5e46da |
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
Packit |
5e46da |
* Lesser General Public License for more details.
|
|
Packit |
5e46da |
*
|
|
Packit |
5e46da |
* You should have received a copy of the GNU Lesser General Public
|
|
Packit |
5e46da |
* License along with this library. If not, see
|
|
Packit |
5e46da |
* <http://www.gnu.org/licenses/>.
|
|
Packit |
5e46da |
*/
|
|
Packit |
5e46da |
|
|
Packit |
5e46da |
#if HAVE_CONFIG_H
|
|
Packit |
5e46da |
#include "config.h"
|
|
Packit |
5e46da |
#endif
|
|
Packit |
5e46da |
|
|
Packit |
5e46da |
#include "clpi_parse.h"
|
|
Packit |
5e46da |
|
|
Packit |
5e46da |
#include "extdata_parse.h"
|
|
Packit |
5e46da |
#include "bdmv_parse.h"
|
|
Packit |
5e46da |
|
|
Packit |
5e46da |
#include "disc/disc.h"
|
|
Packit |
5e46da |
|
|
Packit |
5e46da |
#include "file/file.h"
|
|
Packit |
5e46da |
#include "util/bits.h"
|
|
Packit |
5e46da |
#include "util/macro.h"
|
|
Packit |
5e46da |
#include "util/logging.h"
|
|
Packit |
5e46da |
|
|
Packit |
5e46da |
#include <stdlib.h>
|
|
Packit |
5e46da |
#include <string.h>
|
|
Packit |
5e46da |
|
|
Packit |
5e46da |
#define CLPI_SIG1 ('H' << 24 | 'D' << 16 | 'M' << 8 | 'V')
|
|
Packit |
5e46da |
|
|
Packit |
5e46da |
static int
|
|
Packit |
5e46da |
_parse_stream_attr(BITSTREAM *bits, CLPI_PROG_STREAM *ss)
|
|
Packit |
5e46da |
{
|
|
Packit |
5e46da |
int64_t pos;
|
|
Packit |
5e46da |
int len;
|
|
Packit |
5e46da |
|
|
Packit |
5e46da |
if (!bs_is_align(bits, 0x07)) {
|
|
Packit |
5e46da |
BD_DEBUG(DBG_NAV | DBG_CRIT, "_parse_stream_attr(): Stream alignment error\n");
|
|
Packit |
5e46da |
}
|
|
Packit |
5e46da |
|
|
Packit |
5e46da |
len = bs_read(bits, 8);
|
|
Packit |
5e46da |
pos = bs_pos(bits) >> 3;
|
|
Packit |
5e46da |
|
|
Packit |
5e46da |
ss->lang[0] = '\0';
|
|
Packit |
5e46da |
ss->coding_type = bs_read(bits, 8);
|
|
Packit |
5e46da |
switch (ss->coding_type) {
|
|
Packit |
5e46da |
case 0x01:
|
|
Packit |
5e46da |
case 0x02:
|
|
Packit |
5e46da |
case 0xea:
|
|
Packit |
5e46da |
case 0x1b:
|
|
Packit |
5e46da |
case 0x20:
|
|
Packit |
5e46da |
case 0x24:
|
|
Packit |
5e46da |
ss->format = bs_read(bits, 4);
|
|
Packit |
5e46da |
ss->rate = bs_read(bits, 4);
|
|
Packit |
5e46da |
ss->aspect = bs_read(bits, 4);
|
|
Packit |
5e46da |
bs_skip(bits, 2);
|
|
Packit |
5e46da |
ss->oc_flag = bs_read(bits, 1);
|
|
Packit |
5e46da |
bs_skip(bits, 1);
|
|
Packit |
5e46da |
break;
|
|
Packit |
5e46da |
|
|
Packit |
5e46da |
case 0x03:
|
|
Packit |
5e46da |
case 0x04:
|
|
Packit |
5e46da |
case 0x80:
|
|
Packit |
5e46da |
case 0x81:
|
|
Packit |
5e46da |
case 0x82:
|
|
Packit |
5e46da |
case 0x83:
|
|
Packit |
5e46da |
case 0x84:
|
|
Packit |
5e46da |
case 0x85:
|
|
Packit |
5e46da |
case 0x86:
|
|
Packit |
5e46da |
case 0xa1:
|
|
Packit |
5e46da |
case 0xa2:
|
|
Packit |
5e46da |
ss->format = bs_read(bits, 4);
|
|
Packit |
5e46da |
ss->rate = bs_read(bits, 4);
|
|
Packit |
5e46da |
bs_read_string(bits, ss->lang, 3);
|
|
Packit |
5e46da |
break;
|
|
Packit |
5e46da |
|
|
Packit |
5e46da |
case 0x90:
|
|
Packit |
5e46da |
case 0x91:
|
|
Packit |
5e46da |
case 0xa0:
|
|
Packit |
5e46da |
bs_read_string(bits, ss->lang, 3);
|
|
Packit |
5e46da |
break;
|
|
Packit |
5e46da |
|
|
Packit |
5e46da |
case 0x92:
|
|
Packit |
5e46da |
ss->char_code = bs_read(bits, 8);
|
|
Packit |
5e46da |
bs_read_string(bits, ss->lang, 3);
|
|
Packit |
5e46da |
break;
|
|
Packit |
5e46da |
|
|
Packit |
5e46da |
default:
|
|
Packit |
5e46da |
BD_DEBUG(DBG_NAV | DBG_CRIT, "_parse_stream_attr(): unrecognized coding type %02x\n", ss->coding_type);
|
|
Packit |
5e46da |
break;
|
|
Packit |
5e46da |
};
|
|
Packit |
5e46da |
ss->lang[3] = '\0';
|
|
Packit |
5e46da |
|
|
Packit |
5e46da |
// Skip over any padding
|
|
Packit |
5e46da |
if (bs_seek_byte(bits, pos + len) < 0) {
|
|
Packit |
5e46da |
return 0;
|
|
Packit |
5e46da |
}
|
|
Packit |
5e46da |
return 1;
|
|
Packit |
5e46da |
}
|
|
Packit |
5e46da |
|
|
Packit |
5e46da |
static int
|
|
Packit |
5e46da |
_parse_header(BITSTREAM *bits, CLPI_CL *cl)
|
|
Packit |
5e46da |
{
|
|
Packit |
5e46da |
cl->type_indicator = CLPI_SIG1;
|
|
Packit |
5e46da |
if (!bdmv_parse_header(bits, cl->type_indicator, &cl->type_indicator2)) {
|
|
Packit |
5e46da |
return 0;
|
|
Packit |
5e46da |
}
|
|
Packit |
5e46da |
|
|
Packit |
5e46da |
if (bs_avail(bits) < 5 * 32) {
|
|
Packit |
5e46da |
BD_DEBUG(DBG_NAV | DBG_CRIT, "_parse_header: unexpected end of file\n");
|
|
Packit |
5e46da |
return 0;
|
|
Packit |
5e46da |
}
|
|
Packit |
5e46da |
|
|
Packit |
5e46da |
cl->sequence_info_start_addr = bs_read(bits, 32);
|
|
Packit |
5e46da |
cl->program_info_start_addr = bs_read(bits, 32);
|
|
Packit |
5e46da |
cl->cpi_start_addr = bs_read(bits, 32);
|
|
Packit |
5e46da |
cl->clip_mark_start_addr = bs_read(bits, 32);
|
|
Packit |
5e46da |
cl->ext_data_start_addr = bs_read(bits, 32);
|
|
Packit |
5e46da |
return 1;
|
|
Packit |
5e46da |
}
|
|
Packit |
5e46da |
|
|
Packit |
5e46da |
static int
|
|
Packit |
5e46da |
_parse_clipinfo(BITSTREAM *bits, CLPI_CL *cl)
|
|
Packit |
5e46da |
{
|
|
Packit |
5e46da |
int64_t pos;
|
|
Packit |
5e46da |
int len;
|
|
Packit |
5e46da |
int ii;
|
|
Packit |
5e46da |
|
|
Packit |
5e46da |
if (bs_seek_byte(bits, 40) < 0) {
|
|
Packit |
5e46da |
return 0;
|
|
Packit |
5e46da |
}
|
|
Packit |
5e46da |
|
|
Packit |
5e46da |
// ClipInfo len
|
|
Packit |
5e46da |
bs_skip(bits, 32);
|
|
Packit |
5e46da |
// reserved
|
|
Packit |
5e46da |
bs_skip(bits, 16);
|
|
Packit |
5e46da |
cl->clip.clip_stream_type = bs_read(bits, 8);
|
|
Packit |
5e46da |
cl->clip.application_type = bs_read(bits, 8);
|
|
Packit |
5e46da |
// skip reserved 31 bits
|
|
Packit |
5e46da |
bs_skip(bits, 31);
|
|
Packit |
5e46da |
cl->clip.is_atc_delta = bs_read(bits, 1);
|
|
Packit |
5e46da |
cl->clip.ts_recording_rate = bs_read(bits, 32);
|
|
Packit |
5e46da |
cl->clip.num_source_packets = bs_read(bits, 32);
|
|
Packit |
5e46da |
|
|
Packit |
5e46da |
// Skip reserved 128 bytes
|
|
Packit |
5e46da |
bs_skip(bits, 128 * 8);
|
|
Packit |
5e46da |
|
|
Packit |
5e46da |
// ts type info block
|
|
Packit |
5e46da |
len = bs_read(bits, 16);
|
|
Packit |
5e46da |
pos = bs_pos(bits) >> 3;
|
|
Packit |
5e46da |
if (len) {
|
|
Packit |
5e46da |
cl->clip.ts_type_info.validity = bs_read(bits, 8);
|
|
Packit |
5e46da |
bs_read_string(bits, cl->clip.ts_type_info.format_id, 4);
|
|
Packit |
5e46da |
// Seek past the stuff we don't know anything about
|
|
Packit |
5e46da |
if (bs_seek_byte(bits, pos + len) < 0) {
|
|
Packit |
5e46da |
return 0;
|
|
Packit |
5e46da |
}
|
|
Packit |
5e46da |
}
|
|
Packit |
5e46da |
if (cl->clip.is_atc_delta) {
|
|
Packit |
5e46da |
// Skip reserved bytes
|
|
Packit |
5e46da |
bs_skip(bits, 8);
|
|
Packit |
5e46da |
cl->clip.atc_delta_count = bs_read(bits, 8);
|
|
Packit |
5e46da |
cl->clip.atc_delta =
|
|
Packit |
5e46da |
malloc(cl->clip.atc_delta_count * sizeof(CLPI_ATC_DELTA));
|
|
Packit |
5e46da |
if (cl->clip.atc_delta_count && !cl->clip.atc_delta) {
|
|
Packit |
5e46da |
BD_DEBUG(DBG_CRIT, "out of memory\n");
|
|
Packit |
5e46da |
return 0;
|
|
Packit |
5e46da |
}
|
|
Packit |
5e46da |
for (ii = 0; ii < cl->clip.atc_delta_count; ii++) {
|
|
Packit |
5e46da |
cl->clip.atc_delta[ii].delta = bs_read(bits, 32);
|
|
Packit |
5e46da |
bs_read_string(bits, cl->clip.atc_delta[ii].file_id, 5);
|
|
Packit |
5e46da |
bs_read_string(bits, cl->clip.atc_delta[ii].file_code, 4);
|
|
Packit |
5e46da |
bs_skip(bits, 8);
|
|
Packit |
5e46da |
}
|
|
Packit |
5e46da |
}
|
|
Packit |
5e46da |
|
|
Packit |
5e46da |
// font info
|
|
Packit |
5e46da |
if (cl->clip.application_type == 6 /* Sub TS for a sub-path of Text subtitle */) {
|
|
Packit |
5e46da |
CLPI_FONT_INFO *fi = &cl->clip.font_info;
|
|
Packit |
5e46da |
bs_skip(bits, 8);
|
|
Packit |
5e46da |
fi->font_count = bs_read(bits, 8);
|
|
Packit |
5e46da |
if (fi->font_count) {
|
|
Packit |
5e46da |
fi->font = malloc(fi->font_count * sizeof(CLPI_FONT));
|
|
Packit |
5e46da |
if (!fi->font) {
|
|
Packit |
5e46da |
BD_DEBUG(DBG_CRIT, "out of memory\n");
|
|
Packit |
5e46da |
return 0;
|
|
Packit |
5e46da |
}
|
|
Packit |
5e46da |
for (ii = 0; ii < fi->font_count; ii++) {
|
|
Packit |
5e46da |
bs_read_string(bits, fi->font[ii].file_id, 5);
|
|
Packit |
5e46da |
bs_skip(bits, 8);
|
|
Packit |
5e46da |
}
|
|
Packit |
5e46da |
}
|
|
Packit |
5e46da |
}
|
|
Packit |
5e46da |
|
|
Packit |
5e46da |
return 1;
|
|
Packit |
5e46da |
}
|
|
Packit |
5e46da |
|
|
Packit |
5e46da |
static int
|
|
Packit |
5e46da |
_parse_sequence(BITSTREAM *bits, CLPI_CL *cl)
|
|
Packit |
5e46da |
{
|
|
Packit |
5e46da |
int ii, jj;
|
|
Packit |
5e46da |
|
|
Packit |
5e46da |
if (bs_seek_byte(bits, cl->sequence_info_start_addr) < 0) {
|
|
Packit |
5e46da |
return 0;
|
|
Packit |
5e46da |
}
|
|
Packit |
5e46da |
|
|
Packit |
5e46da |
// Skip the length field, and a reserved byte
|
|
Packit |
5e46da |
bs_skip(bits, 5 * 8);
|
|
Packit |
5e46da |
// Then get the number of sequences
|
|
Packit |
5e46da |
cl->sequence.num_atc_seq = bs_read(bits, 8);
|
|
Packit |
5e46da |
|
|
Packit |
5e46da |
CLPI_ATC_SEQ *atc_seq;
|
|
Packit |
5e46da |
atc_seq = calloc(cl->sequence.num_atc_seq, sizeof(CLPI_ATC_SEQ));
|
|
Packit |
5e46da |
cl->sequence.atc_seq = atc_seq;
|
|
Packit |
5e46da |
if (cl->sequence.num_atc_seq && !atc_seq) {
|
|
Packit |
5e46da |
BD_DEBUG(DBG_CRIT, "out of memory\n");
|
|
Packit |
5e46da |
return 0;
|
|
Packit |
5e46da |
}
|
|
Packit |
5e46da |
for (ii = 0; ii < cl->sequence.num_atc_seq; ii++) {
|
|
Packit |
5e46da |
atc_seq[ii].spn_atc_start = bs_read(bits, 32);
|
|
Packit |
5e46da |
atc_seq[ii].num_stc_seq = bs_read(bits, 8);
|
|
Packit |
5e46da |
atc_seq[ii].offset_stc_id = bs_read(bits, 8);
|
|
Packit |
5e46da |
|
|
Packit |
5e46da |
CLPI_STC_SEQ *stc_seq;
|
|
Packit |
5e46da |
stc_seq = malloc(atc_seq[ii].num_stc_seq * sizeof(CLPI_STC_SEQ));
|
|
Packit |
5e46da |
if (atc_seq[ii].num_stc_seq && !stc_seq) {
|
|
Packit |
5e46da |
BD_DEBUG(DBG_CRIT, "out of memory\n");
|
|
Packit |
5e46da |
return 0;
|
|
Packit |
5e46da |
}
|
|
Packit |
5e46da |
atc_seq[ii].stc_seq = stc_seq;
|
|
Packit |
5e46da |
for (jj = 0; jj < atc_seq[ii].num_stc_seq; jj++) {
|
|
Packit |
5e46da |
stc_seq[jj].pcr_pid = bs_read(bits, 16);
|
|
Packit |
5e46da |
stc_seq[jj].spn_stc_start = bs_read(bits, 32);
|
|
Packit |
5e46da |
stc_seq[jj].presentation_start_time = bs_read(bits, 32);
|
|
Packit |
5e46da |
stc_seq[jj].presentation_end_time = bs_read(bits, 32);
|
|
Packit |
5e46da |
}
|
|
Packit |
5e46da |
}
|
|
Packit |
5e46da |
return 1;
|
|
Packit |
5e46da |
}
|
|
Packit |
5e46da |
|
|
Packit |
5e46da |
static int
|
|
Packit |
5e46da |
_parse_program(BITSTREAM *bits, CLPI_PROG_INFO *program)
|
|
Packit |
5e46da |
{
|
|
Packit |
5e46da |
int ii, jj;
|
|
Packit |
5e46da |
|
|
Packit |
5e46da |
// Skip the length field, and a reserved byte
|
|
Packit |
5e46da |
bs_skip(bits, 5 * 8);
|
|
Packit |
5e46da |
// Then get the number of sequences
|
|
Packit |
5e46da |
program->num_prog = bs_read(bits, 8);
|
|
Packit |
5e46da |
|
|
Packit |
5e46da |
CLPI_PROG *progs;
|
|
Packit |
5e46da |
progs = calloc(program->num_prog, sizeof(CLPI_PROG));
|
|
Packit |
5e46da |
program->progs = progs;
|
|
Packit |
5e46da |
if (program->num_prog && !progs) {
|
|
Packit |
5e46da |
BD_DEBUG(DBG_CRIT, "out of memory\n");
|
|
Packit |
5e46da |
return 0;
|
|
Packit |
5e46da |
}
|
|
Packit |
5e46da |
for (ii = 0; ii < program->num_prog; ii++) {
|
|
Packit |
5e46da |
progs[ii].spn_program_sequence_start = bs_read(bits, 32);
|
|
Packit |
5e46da |
progs[ii].program_map_pid = bs_read(bits, 16);
|
|
Packit |
5e46da |
progs[ii].num_streams = bs_read(bits, 8);
|
|
Packit |
5e46da |
progs[ii].num_groups = bs_read(bits, 8);
|
|
Packit |
5e46da |
|
|
Packit |
5e46da |
CLPI_PROG_STREAM *ps;
|
|
Packit |
5e46da |
ps = calloc(progs[ii].num_streams, sizeof(CLPI_PROG_STREAM));
|
|
Packit |
5e46da |
if (progs[ii].num_streams && !ps) {
|
|
Packit |
5e46da |
BD_DEBUG(DBG_CRIT, "out of memory\n");
|
|
Packit |
5e46da |
return 0;
|
|
Packit |
5e46da |
}
|
|
Packit |
5e46da |
progs[ii].streams = ps;
|
|
Packit |
5e46da |
for (jj = 0; jj < progs[ii].num_streams; jj++) {
|
|
Packit |
5e46da |
ps[jj].pid = bs_read(bits, 16);
|
|
Packit |
5e46da |
if (!_parse_stream_attr(bits, &ps[jj])) {
|
|
Packit |
5e46da |
return 0;
|
|
Packit |
5e46da |
}
|
|
Packit |
5e46da |
}
|
|
Packit |
5e46da |
}
|
|
Packit |
5e46da |
return 1;
|
|
Packit |
5e46da |
}
|
|
Packit |
5e46da |
|
|
Packit |
5e46da |
static int
|
|
Packit |
5e46da |
_parse_program_info(BITSTREAM *bits, CLPI_CL *cl)
|
|
Packit |
5e46da |
{
|
|
Packit |
5e46da |
if (bs_seek_byte(bits, cl->program_info_start_addr) < 0) {
|
|
Packit |
5e46da |
return 0;
|
|
Packit |
5e46da |
}
|
|
Packit |
5e46da |
|
|
Packit |
5e46da |
return _parse_program(bits, &cl->program);
|
|
Packit |
5e46da |
}
|
|
Packit |
5e46da |
|
|
Packit |
5e46da |
static int
|
|
Packit |
5e46da |
_parse_ep_map_stream(BITSTREAM *bits, CLPI_EP_MAP_ENTRY *ee)
|
|
Packit |
5e46da |
{
|
|
Packit |
5e46da |
uint32_t fine_start;
|
|
Packit |
5e46da |
int ii;
|
|
Packit |
5e46da |
CLPI_EP_COARSE * coarse;
|
|
Packit |
5e46da |
CLPI_EP_FINE * fine;
|
|
Packit |
5e46da |
|
|
Packit |
5e46da |
if (bs_seek_byte(bits, ee->ep_map_stream_start_addr) < 0) {
|
|
Packit |
5e46da |
return 0;
|
|
Packit |
5e46da |
}
|
|
Packit |
5e46da |
fine_start = bs_read(bits, 32);
|
|
Packit |
5e46da |
|
|
Packit |
5e46da |
if (bs_avail(bits)/(8*8) < ee->num_ep_coarse) {
|
|
Packit |
5e46da |
BD_DEBUG(DBG_HDMV|DBG_CRIT, "clpi_parse: unexpected EOF (EP coarse)\n");
|
|
Packit |
5e46da |
return 0;
|
|
Packit |
5e46da |
}
|
|
Packit |
5e46da |
|
|
Packit |
5e46da |
coarse = malloc(ee->num_ep_coarse * sizeof(CLPI_EP_COARSE));
|
|
Packit |
5e46da |
ee->coarse = coarse;
|
|
Packit |
5e46da |
if (ee->num_ep_coarse && !coarse) {
|
|
Packit |
5e46da |
BD_DEBUG(DBG_CRIT, "out of memory\n");
|
|
Packit |
5e46da |
return 0;
|
|
Packit |
5e46da |
}
|
|
Packit |
5e46da |
for (ii = 0; ii < ee->num_ep_coarse; ii++) {
|
|
Packit |
5e46da |
coarse[ii].ref_ep_fine_id = bs_read(bits, 18);
|
|
Packit |
5e46da |
coarse[ii].pts_ep = bs_read(bits, 14);
|
|
Packit |
5e46da |
coarse[ii].spn_ep = bs_read(bits, 32);
|
|
Packit |
5e46da |
}
|
|
Packit |
5e46da |
|
|
Packit |
5e46da |
if (bs_seek_byte(bits, ee->ep_map_stream_start_addr+fine_start) < 0) {
|
|
Packit |
5e46da |
return 0;
|
|
Packit |
5e46da |
}
|
|
Packit |
5e46da |
|
|
Packit |
5e46da |
if (bs_avail(bits)/(8*4) < ee->num_ep_fine) {
|
|
Packit |
5e46da |
BD_DEBUG(DBG_HDMV|DBG_CRIT, "clpi_parse: unexpected EOF (EP fine)\n");
|
|
Packit |
5e46da |
return 0;
|
|
Packit |
5e46da |
}
|
|
Packit |
5e46da |
|
|
Packit |
5e46da |
fine = malloc(ee->num_ep_fine * sizeof(CLPI_EP_FINE));
|
|
Packit |
5e46da |
ee->fine = fine;
|
|
Packit |
5e46da |
if (ee->num_ep_fine && !fine) {
|
|
Packit |
5e46da |
BD_DEBUG(DBG_CRIT, "out of memory\n");
|
|
Packit |
5e46da |
return 0;
|
|
Packit |
5e46da |
}
|
|
Packit |
5e46da |
for (ii = 0; ii < ee->num_ep_fine; ii++) {
|
|
Packit |
5e46da |
fine[ii].is_angle_change_point = bs_read(bits, 1);
|
|
Packit |
5e46da |
fine[ii].i_end_position_offset = bs_read(bits, 3);
|
|
Packit |
5e46da |
fine[ii].pts_ep = bs_read(bits, 11);
|
|
Packit |
5e46da |
fine[ii].spn_ep = bs_read(bits, 17);
|
|
Packit |
5e46da |
}
|
|
Packit |
5e46da |
return 1;
|
|
Packit |
5e46da |
}
|
|
Packit |
5e46da |
|
|
Packit |
5e46da |
static int
|
|
Packit |
5e46da |
_parse_cpi(BITSTREAM *bits, CLPI_CPI *cpi)
|
|
Packit |
5e46da |
{
|
|
Packit |
5e46da |
int ii;
|
|
Packit |
5e46da |
uint32_t ep_map_pos, len;
|
|
Packit |
5e46da |
|
|
Packit |
5e46da |
len = bs_read(bits, 32);
|
|
Packit |
5e46da |
if (len == 0) {
|
|
Packit |
5e46da |
return 1;
|
|
Packit |
5e46da |
}
|
|
Packit |
5e46da |
|
|
Packit |
5e46da |
bs_skip(bits, 12);
|
|
Packit |
5e46da |
cpi->type = bs_read(bits, 4);
|
|
Packit |
5e46da |
ep_map_pos = (uint32_t)(bs_pos(bits) >> 3);
|
|
Packit |
5e46da |
|
|
Packit |
5e46da |
// EP Map starts here
|
|
Packit |
5e46da |
bs_skip(bits, 8);
|
|
Packit |
5e46da |
cpi->num_stream_pid = bs_read(bits, 8);
|
|
Packit |
5e46da |
|
|
Packit |
5e46da |
CLPI_EP_MAP_ENTRY *entry;
|
|
Packit |
5e46da |
entry = calloc(cpi->num_stream_pid, sizeof(CLPI_EP_MAP_ENTRY));
|
|
Packit |
5e46da |
cpi->entry = entry;
|
|
Packit |
5e46da |
if (cpi->num_stream_pid && !entry) {
|
|
Packit |
5e46da |
BD_DEBUG(DBG_CRIT, "out of memory\n");
|
|
Packit |
5e46da |
return 0;
|
|
Packit |
5e46da |
}
|
|
Packit |
5e46da |
for (ii = 0; ii < cpi->num_stream_pid; ii++) {
|
|
Packit |
5e46da |
entry[ii].pid = bs_read(bits, 16);
|
|
Packit |
5e46da |
bs_skip(bits, 10);
|
|
Packit |
5e46da |
entry[ii].ep_stream_type = bs_read(bits, 4);
|
|
Packit |
5e46da |
entry[ii].num_ep_coarse = bs_read(bits, 16);
|
|
Packit |
5e46da |
entry[ii].num_ep_fine = bs_read(bits, 18);
|
|
Packit |
5e46da |
entry[ii].ep_map_stream_start_addr = bs_read(bits, 32) + ep_map_pos;
|
|
Packit |
5e46da |
}
|
|
Packit |
5e46da |
for (ii = 0; ii < cpi->num_stream_pid; ii++) {
|
|
Packit |
5e46da |
if (!_parse_ep_map_stream(bits, &cpi->entry[ii])) {
|
|
Packit |
5e46da |
return 0;
|
|
Packit |
5e46da |
}
|
|
Packit |
5e46da |
}
|
|
Packit |
5e46da |
return 1;
|
|
Packit |
5e46da |
}
|
|
Packit |
5e46da |
|
|
Packit |
5e46da |
static int
|
|
Packit |
5e46da |
_parse_cpi_info(BITSTREAM *bits, CLPI_CL *cl)
|
|
Packit |
5e46da |
{
|
|
Packit |
5e46da |
if (bs_seek_byte(bits, cl->cpi_start_addr) < 0) {
|
|
Packit |
5e46da |
return 0;
|
|
Packit |
5e46da |
}
|
|
Packit |
5e46da |
|
|
Packit |
5e46da |
return _parse_cpi(bits, &cl->cpi);
|
|
Packit |
5e46da |
}
|
|
Packit |
5e46da |
|
|
Packit |
5e46da |
uint32_t
|
|
Packit |
5e46da |
clpi_find_stc_spn(const CLPI_CL *cl, uint8_t stc_id)
|
|
Packit |
5e46da |
{
|
|
Packit |
5e46da |
int ii;
|
|
Packit |
5e46da |
CLPI_ATC_SEQ *atc;
|
|
Packit |
5e46da |
|
|
Packit |
5e46da |
for (ii = 0; ii < cl->sequence.num_atc_seq; ii++) {
|
|
Packit |
5e46da |
atc = &cl->sequence.atc_seq[ii];
|
|
Packit |
5e46da |
if (stc_id < atc->offset_stc_id + atc->num_stc_seq) {
|
|
Packit |
5e46da |
return atc->stc_seq[stc_id - atc->offset_stc_id].spn_stc_start;
|
|
Packit |
5e46da |
}
|
|
Packit |
5e46da |
}
|
|
Packit |
5e46da |
return 0;
|
|
Packit |
5e46da |
}
|
|
Packit |
5e46da |
|
|
Packit |
5e46da |
// Looks up the start packet number for the timestamp
|
|
Packit |
5e46da |
// Returns the spn for the entry that is closest to but
|
|
Packit |
5e46da |
// before the given timestamp
|
|
Packit |
5e46da |
uint32_t
|
|
Packit |
5e46da |
clpi_lookup_spn(const CLPI_CL *cl, uint32_t timestamp, int before, uint8_t stc_id)
|
|
Packit |
5e46da |
{
|
|
Packit |
5e46da |
const CLPI_EP_MAP_ENTRY *entry;
|
|
Packit |
5e46da |
const CLPI_CPI *cpi = &cl->cpi;
|
|
Packit |
5e46da |
int ii, jj;
|
|
Packit |
5e46da |
uint32_t coarse_pts, pts; // 45khz timestamps
|
|
Packit |
5e46da |
uint32_t spn, coarse_spn, stc_spn;
|
|
Packit |
5e46da |
int start, end;
|
|
Packit |
5e46da |
int ref;
|
|
Packit |
5e46da |
|
|
Packit |
5e46da |
if (cpi->num_stream_pid < 1 || !cpi->entry) {
|
|
Packit |
5e46da |
if (before) {
|
|
Packit |
5e46da |
return 0;
|
|
Packit |
5e46da |
}
|
|
Packit |
5e46da |
return cl->clip.num_source_packets;
|
|
Packit |
5e46da |
}
|
|
Packit |
5e46da |
|
|
Packit |
5e46da |
// Assumes that there is only one pid of interest
|
|
Packit |
5e46da |
entry = &cpi->entry[0];
|
|
Packit |
5e46da |
|
|
Packit |
5e46da |
// Use sequence info to find spn_stc_start before doing
|
|
Packit |
5e46da |
// PTS search. The spn_stc_start defines the point in
|
|
Packit |
5e46da |
// the EP map to start searching.
|
|
Packit |
5e46da |
stc_spn = clpi_find_stc_spn(cl, stc_id);
|
|
Packit |
5e46da |
for (ii = 0; ii < entry->num_ep_coarse; ii++) {
|
|
Packit |
5e46da |
ref = entry->coarse[ii].ref_ep_fine_id;
|
|
Packit |
5e46da |
if (entry->coarse[ii].spn_ep >= stc_spn) {
|
|
Packit |
5e46da |
// The desired starting point is either after this point
|
|
Packit |
5e46da |
// or in the middle of the previous coarse entry
|
|
Packit |
5e46da |
break;
|
|
Packit |
5e46da |
}
|
|
Packit |
5e46da |
}
|
|
Packit |
5e46da |
if (ii >= entry->num_ep_coarse) {
|
|
Packit |
5e46da |
return cl->clip.num_source_packets;
|
|
Packit |
5e46da |
}
|
|
Packit |
5e46da |
pts = ((uint64_t)(entry->coarse[ii].pts_ep & ~0x01) << 18) +
|
|
Packit |
5e46da |
((uint64_t)entry->fine[ref].pts_ep << 8);
|
|
Packit |
5e46da |
if (pts > timestamp && ii) {
|
|
Packit |
5e46da |
// The starting point and desired PTS is in the previous coarse entry
|
|
Packit |
5e46da |
ii--;
|
|
Packit |
5e46da |
coarse_pts = (uint32_t)(entry->coarse[ii].pts_ep & ~0x01) << 18;
|
|
Packit |
5e46da |
coarse_spn = entry->coarse[ii].spn_ep;
|
|
Packit |
5e46da |
start = entry->coarse[ii].ref_ep_fine_id;
|
|
Packit |
5e46da |
end = entry->coarse[ii+1].ref_ep_fine_id;
|
|
Packit |
5e46da |
// Find a fine entry that has bothe spn > stc_spn and ptc > timestamp
|
|
Packit |
5e46da |
for (jj = start; jj < end; jj++) {
|
|
Packit |
5e46da |
|
|
Packit |
5e46da |
pts = coarse_pts + ((uint32_t)entry->fine[jj].pts_ep << 8);
|
|
Packit |
5e46da |
spn = (coarse_spn & ~0x1FFFF) + entry->fine[jj].spn_ep;
|
|
Packit |
5e46da |
if (stc_spn >= spn && pts > timestamp)
|
|
Packit |
5e46da |
break;
|
|
Packit |
5e46da |
}
|
|
Packit |
5e46da |
goto done;
|
|
Packit |
5e46da |
}
|
|
Packit |
5e46da |
|
|
Packit |
5e46da |
// If we've gotten this far, the desired timestamp is somewhere
|
|
Packit |
5e46da |
// after the coarse entry we found the stc_spn in.
|
|
Packit |
5e46da |
start = ii;
|
|
Packit |
5e46da |
for (ii = start; ii < entry->num_ep_coarse; ii++) {
|
|
Packit |
5e46da |
ref = entry->coarse[ii].ref_ep_fine_id;
|
|
Packit |
5e46da |
pts = ((uint64_t)(entry->coarse[ii].pts_ep & ~0x01) << 18) +
|
|
Packit |
5e46da |
((uint64_t)entry->fine[ref].pts_ep << 8);
|
|
Packit |
5e46da |
if (pts > timestamp) {
|
|
Packit |
5e46da |
break;
|
|
Packit |
5e46da |
}
|
|
Packit |
5e46da |
}
|
|
Packit |
5e46da |
// If the timestamp is before the first entry, then return
|
|
Packit |
5e46da |
// the beginning of the clip
|
|
Packit |
5e46da |
if (ii == 0) {
|
|
Packit |
5e46da |
return 0;
|
|
Packit |
5e46da |
}
|
|
Packit |
5e46da |
ii--;
|
|
Packit |
5e46da |
coarse_pts = (uint32_t)(entry->coarse[ii].pts_ep & ~0x01) << 18;
|
|
Packit |
5e46da |
start = entry->coarse[ii].ref_ep_fine_id;
|
|
Packit |
5e46da |
if (ii < entry->num_ep_coarse - 1) {
|
|
Packit |
5e46da |
end = entry->coarse[ii+1].ref_ep_fine_id;
|
|
Packit |
5e46da |
} else {
|
|
Packit |
5e46da |
end = entry->num_ep_fine;
|
|
Packit |
5e46da |
}
|
|
Packit |
5e46da |
for (jj = start; jj < end; jj++) {
|
|
Packit |
5e46da |
|
|
Packit |
5e46da |
pts = coarse_pts + ((uint32_t)entry->fine[jj].pts_ep << 8);
|
|
Packit |
5e46da |
if (pts > timestamp)
|
|
Packit |
5e46da |
break;
|
|
Packit |
5e46da |
}
|
|
Packit |
5e46da |
|
|
Packit |
5e46da |
done:
|
|
Packit |
5e46da |
if (before) {
|
|
Packit |
5e46da |
jj--;
|
|
Packit |
5e46da |
}
|
|
Packit |
5e46da |
if (jj == end) {
|
|
Packit |
5e46da |
ii++;
|
|
Packit |
5e46da |
if (ii >= entry->num_ep_coarse) {
|
|
Packit |
5e46da |
// End of file
|
|
Packit |
5e46da |
return cl->clip.num_source_packets;
|
|
Packit |
5e46da |
}
|
|
Packit |
5e46da |
jj = entry->coarse[ii].ref_ep_fine_id;
|
|
Packit |
5e46da |
}
|
|
Packit |
5e46da |
spn = (entry->coarse[ii].spn_ep & ~0x1FFFF) + entry->fine[jj].spn_ep;
|
|
Packit |
5e46da |
return spn;
|
|
Packit |
5e46da |
}
|
|
Packit |
5e46da |
|
|
Packit |
5e46da |
// Looks up the start packet number that is closest to the requested packet
|
|
Packit |
5e46da |
// Returns the spn for the entry that is closest to but
|
|
Packit |
5e46da |
// before the given packet
|
|
Packit |
5e46da |
uint32_t
|
|
Packit |
5e46da |
clpi_access_point(const CLPI_CL *cl, uint32_t pkt, int next, int angle_change, uint32_t *time)
|
|
Packit |
5e46da |
{
|
|
Packit |
5e46da |
const CLPI_EP_MAP_ENTRY *entry;
|
|
Packit |
5e46da |
const CLPI_CPI *cpi = &cl->cpi;
|
|
Packit |
5e46da |
int ii, jj;
|
|
Packit |
5e46da |
uint32_t coarse_spn, spn;
|
|
Packit |
5e46da |
int start, end;
|
|
Packit |
5e46da |
int ref;
|
|
Packit |
5e46da |
|
|
Packit |
5e46da |
// Assumes that there is only one pid of interest
|
|
Packit |
5e46da |
entry = &cpi->entry[0];
|
|
Packit |
5e46da |
|
|
Packit |
5e46da |
for (ii = 0; ii < entry->num_ep_coarse; ii++) {
|
|
Packit |
5e46da |
ref = entry->coarse[ii].ref_ep_fine_id;
|
|
Packit |
5e46da |
spn = (entry->coarse[ii].spn_ep & ~0x1FFFF) + entry->fine[ref].spn_ep;
|
|
Packit |
5e46da |
if (spn > pkt) {
|
|
Packit |
5e46da |
break;
|
|
Packit |
5e46da |
}
|
|
Packit |
5e46da |
}
|
|
Packit |
5e46da |
// If the timestamp is before the first entry, then return
|
|
Packit |
5e46da |
// the beginning of the clip
|
|
Packit |
5e46da |
if (ii == 0) {
|
|
Packit |
5e46da |
*time = 0;
|
|
Packit |
5e46da |
return 0;
|
|
Packit |
5e46da |
}
|
|
Packit |
5e46da |
ii--;
|
|
Packit |
5e46da |
coarse_spn = (entry->coarse[ii].spn_ep & ~0x1FFFF);
|
|
Packit |
5e46da |
start = entry->coarse[ii].ref_ep_fine_id;
|
|
Packit |
5e46da |
if (ii < entry->num_ep_coarse - 1) {
|
|
Packit |
5e46da |
end = entry->coarse[ii+1].ref_ep_fine_id;
|
|
Packit |
5e46da |
} else {
|
|
Packit |
5e46da |
end = entry->num_ep_fine;
|
|
Packit |
5e46da |
}
|
|
Packit |
5e46da |
for (jj = start; jj < end; jj++) {
|
|
Packit |
5e46da |
|
|
Packit |
5e46da |
spn = coarse_spn + entry->fine[jj].spn_ep;
|
|
Packit |
5e46da |
if (spn >= pkt) {
|
|
Packit |
5e46da |
break;
|
|
Packit |
5e46da |
}
|
|
Packit |
5e46da |
}
|
|
Packit |
5e46da |
if (jj == end && next) {
|
|
Packit |
5e46da |
ii++;
|
|
Packit |
5e46da |
jj = 0;
|
|
Packit |
5e46da |
} else if (spn != pkt && !next) {
|
|
Packit |
5e46da |
jj--;
|
|
Packit |
5e46da |
}
|
|
Packit |
5e46da |
if (ii == entry->num_ep_coarse) {
|
|
Packit |
5e46da |
*time = 0;
|
|
Packit |
5e46da |
return cl->clip.num_source_packets;
|
|
Packit |
5e46da |
}
|
|
Packit |
5e46da |
coarse_spn = (entry->coarse[ii].spn_ep & ~0x1FFFF);
|
|
Packit |
5e46da |
if (angle_change) {
|
|
Packit |
5e46da |
// Keep looking till there's an angle change point
|
|
Packit |
5e46da |
for (; jj < end; jj++) {
|
|
Packit |
5e46da |
|
|
Packit |
5e46da |
if (entry->fine[jj].is_angle_change_point) {
|
|
Packit |
5e46da |
*time = ((uint64_t)(entry->coarse[ii].pts_ep & ~0x01) << 18) +
|
|
Packit |
5e46da |
((uint64_t)entry->fine[jj].pts_ep << 8);
|
|
Packit |
5e46da |
return coarse_spn + entry->fine[jj].spn_ep;
|
|
Packit |
5e46da |
}
|
|
Packit |
5e46da |
}
|
|
Packit |
5e46da |
for (ii++; ii < entry->num_ep_coarse; ii++) {
|
|
Packit |
5e46da |
start = entry->coarse[ii].ref_ep_fine_id;
|
|
Packit |
5e46da |
if (ii < entry->num_ep_coarse - 1) {
|
|
Packit |
5e46da |
end = entry->coarse[ii+1].ref_ep_fine_id;
|
|
Packit |
5e46da |
} else {
|
|
Packit |
5e46da |
end = entry->num_ep_fine;
|
|
Packit |
5e46da |
}
|
|
Packit |
5e46da |
for (jj = start; jj < end; jj++) {
|
|
Packit |
5e46da |
|
|
Packit |
5e46da |
if (entry->fine[jj].is_angle_change_point) {
|
|
Packit |
5e46da |
*time = ((uint64_t)(entry->coarse[ii].pts_ep & ~0x01) << 18) +
|
|
Packit |
5e46da |
((uint64_t)entry->fine[jj].pts_ep << 8);
|
|
Packit |
5e46da |
return coarse_spn + entry->fine[jj].spn_ep;
|
|
Packit |
5e46da |
}
|
|
Packit |
5e46da |
}
|
|
Packit |
5e46da |
}
|
|
Packit |
5e46da |
*time = 0;
|
|
Packit |
5e46da |
return cl->clip.num_source_packets;
|
|
Packit |
5e46da |
}
|
|
Packit |
5e46da |
*time = ((uint64_t)(entry->coarse[ii].pts_ep & ~0x01) << 18) +
|
|
Packit |
5e46da |
((uint64_t)entry->fine[jj].pts_ep << 8);
|
|
Packit |
5e46da |
return coarse_spn + entry->fine[jj].spn_ep;
|
|
Packit |
5e46da |
}
|
|
Packit |
5e46da |
|
|
Packit |
5e46da |
static int
|
|
Packit |
5e46da |
_parse_extent_start_points(BITSTREAM *bits, CLPI_EXTENT_START *es)
|
|
Packit |
5e46da |
{
|
|
Packit |
5e46da |
unsigned int ii;
|
|
Packit |
5e46da |
|
|
Packit |
5e46da |
bs_skip(bits, 32); // length
|
|
Packit |
5e46da |
es->num_point = bs_read(bits, 32);
|
|
Packit |
5e46da |
|
|
Packit |
5e46da |
es->point = calloc(es->num_point, sizeof(uint32_t));
|
|
Packit |
5e46da |
if (es->num_point && !es->point) {
|
|
Packit |
5e46da |
es->num_point = 0;
|
|
Packit |
5e46da |
BD_DEBUG(DBG_CRIT, "out of memory\n");
|
|
Packit |
5e46da |
return 0;
|
|
Packit |
5e46da |
}
|
|
Packit |
5e46da |
for (ii = 0; ii < es->num_point; ii++) {
|
|
Packit |
5e46da |
es->point[ii] = bs_read(bits, 32);
|
|
Packit |
5e46da |
}
|
|
Packit |
5e46da |
|
|
Packit |
5e46da |
return 1;
|
|
Packit |
5e46da |
}
|
|
Packit |
5e46da |
|
|
Packit |
5e46da |
static int _parse_clpi_extension(BITSTREAM *bits, int id1, int id2, void *handle)
|
|
Packit |
5e46da |
{
|
|
Packit |
5e46da |
CLPI_CL *cl = (CLPI_CL*)handle;
|
|
Packit |
5e46da |
|
|
Packit |
5e46da |
if (id1 == 1) {
|
|
Packit |
5e46da |
if (id2 == 2) {
|
|
Packit |
5e46da |
// LPCM down mix coefficient
|
|
Packit |
5e46da |
//_parse_lpcm_down_mix_coeff(bits, &cl->lpcm_down_mix_coeff);
|
|
Packit |
5e46da |
return 0;
|
|
Packit |
5e46da |
}
|
|
Packit |
5e46da |
}
|
|
Packit |
5e46da |
|
|
Packit |
5e46da |
if (id1 == 2) {
|
|
Packit |
5e46da |
if (id2 == 4) {
|
|
Packit |
5e46da |
// Extent start point
|
|
Packit |
5e46da |
return _parse_extent_start_points(bits, &cl->extent_start);
|
|
Packit |
5e46da |
}
|
|
Packit |
5e46da |
if (id2 == 5) {
|
|
Packit |
5e46da |
// ProgramInfo SS
|
|
Packit |
5e46da |
return _parse_program(bits, &cl->program_ss);
|
|
Packit |
5e46da |
}
|
|
Packit |
5e46da |
if (id2 == 6) {
|
|
Packit |
5e46da |
// CPI SS
|
|
Packit |
5e46da |
return _parse_cpi(bits, &cl->cpi_ss);
|
|
Packit |
5e46da |
}
|
|
Packit |
5e46da |
}
|
|
Packit |
5e46da |
|
|
Packit |
5e46da |
BD_DEBUG(DBG_NAV | DBG_CRIT, "_parse_clpi_extension(): unhandled extension %d.%d\n", id1, id2);
|
|
Packit |
5e46da |
return 0;
|
|
Packit |
5e46da |
}
|
|
Packit |
5e46da |
|
|
Packit |
5e46da |
static void
|
|
Packit |
5e46da |
_clean_program(CLPI_PROG_INFO *p)
|
|
Packit |
5e46da |
{
|
|
Packit |
5e46da |
int ii;
|
|
Packit |
5e46da |
|
|
Packit |
5e46da |
if (p && p->progs) {
|
|
Packit |
5e46da |
for (ii = 0; ii < p->num_prog; ii++) {
|
|
Packit |
5e46da |
X_FREE(p->progs[ii].streams);
|
|
Packit |
5e46da |
}
|
|
Packit |
5e46da |
X_FREE(p->progs);
|
|
Packit |
5e46da |
}
|
|
Packit |
5e46da |
}
|
|
Packit |
5e46da |
|
|
Packit |
5e46da |
static void
|
|
Packit |
5e46da |
_clean_cpi(CLPI_CPI *cpi)
|
|
Packit |
5e46da |
{
|
|
Packit |
5e46da |
int ii;
|
|
Packit |
5e46da |
|
|
Packit |
5e46da |
if (cpi && cpi->entry) {
|
|
Packit |
5e46da |
for (ii = 0; ii < cpi->num_stream_pid; ii++) {
|
|
Packit |
5e46da |
X_FREE(cpi->entry[ii].coarse);
|
|
Packit |
5e46da |
X_FREE(cpi->entry[ii].fine);
|
|
Packit |
5e46da |
}
|
|
Packit |
5e46da |
X_FREE(cpi->entry);
|
|
Packit |
5e46da |
}
|
|
Packit |
5e46da |
}
|
|
Packit |
5e46da |
|
|
Packit |
5e46da |
static void
|
|
Packit |
5e46da |
_clpi_free(CLPI_CL *cl)
|
|
Packit |
5e46da |
{
|
|
Packit |
5e46da |
int ii;
|
|
Packit |
5e46da |
|
|
Packit |
5e46da |
X_FREE(cl->clip.atc_delta);
|
|
Packit |
5e46da |
X_FREE(cl->clip.font_info.font);
|
|
Packit |
5e46da |
|
|
Packit |
5e46da |
if (cl->sequence.atc_seq) {
|
|
Packit |
5e46da |
for (ii = 0; ii < cl->sequence.num_atc_seq; ii++) {
|
|
Packit |
5e46da |
X_FREE(cl->sequence.atc_seq[ii].stc_seq);
|
|
Packit |
5e46da |
}
|
|
Packit |
5e46da |
|
|
Packit |
5e46da |
X_FREE(cl->sequence.atc_seq);
|
|
Packit |
5e46da |
}
|
|
Packit |
5e46da |
|
|
Packit |
5e46da |
_clean_program(&cl->program);
|
|
Packit |
5e46da |
_clean_cpi(&cl->cpi);
|
|
Packit |
5e46da |
|
|
Packit |
5e46da |
X_FREE(cl->extent_start.point);
|
|
Packit |
5e46da |
|
|
Packit |
5e46da |
_clean_program(&cl->program_ss);
|
|
Packit |
5e46da |
_clean_cpi(&cl->cpi_ss);
|
|
Packit |
5e46da |
|
|
Packit |
5e46da |
X_FREE(cl);
|
|
Packit |
5e46da |
}
|
|
Packit |
5e46da |
|
|
Packit |
5e46da |
void
|
|
Packit |
5e46da |
clpi_free(CLPI_CL **cl)
|
|
Packit |
5e46da |
{
|
|
Packit |
5e46da |
if (*cl) {
|
|
Packit |
5e46da |
_clpi_free(*cl);
|
|
Packit |
5e46da |
*cl = NULL;
|
|
Packit |
5e46da |
}
|
|
Packit |
5e46da |
}
|
|
Packit |
5e46da |
|
|
Packit |
5e46da |
static CLPI_CL*
|
|
Packit |
5e46da |
_clpi_parse(BD_FILE_H *fp)
|
|
Packit |
5e46da |
{
|
|
Packit |
5e46da |
BITSTREAM bits;
|
|
Packit |
5e46da |
CLPI_CL *cl;
|
|
Packit |
5e46da |
|
|
Packit |
5e46da |
if (bs_init(&bits, fp) < 0) {
|
|
Packit |
5e46da |
BD_DEBUG(DBG_NAV, "?????.clpi: read error\n");
|
|
Packit |
5e46da |
return NULL;
|
|
Packit |
5e46da |
}
|
|
Packit |
5e46da |
|
|
Packit |
5e46da |
cl = calloc(1, sizeof(CLPI_CL));
|
|
Packit |
5e46da |
if (cl == NULL) {
|
|
Packit |
5e46da |
BD_DEBUG(DBG_CRIT, "out of memory\n");
|
|
Packit |
5e46da |
return NULL;
|
|
Packit |
5e46da |
}
|
|
Packit |
5e46da |
|
|
Packit |
5e46da |
if (!_parse_header(&bits, cl)) {
|
|
Packit |
5e46da |
_clpi_free(cl);
|
|
Packit |
5e46da |
return NULL;
|
|
Packit |
5e46da |
}
|
|
Packit |
5e46da |
|
|
Packit |
5e46da |
if (cl->ext_data_start_addr > 0) {
|
|
Packit |
5e46da |
bdmv_parse_extension_data(&bits,
|
|
Packit |
5e46da |
cl->ext_data_start_addr,
|
|
Packit |
5e46da |
_parse_clpi_extension,
|
|
Packit |
5e46da |
cl);
|
|
Packit |
5e46da |
}
|
|
Packit |
5e46da |
|
|
Packit |
5e46da |
if (!_parse_clipinfo(&bits, cl)) {
|
|
Packit |
5e46da |
_clpi_free(cl);
|
|
Packit |
5e46da |
return NULL;
|
|
Packit |
5e46da |
}
|
|
Packit |
5e46da |
if (!_parse_sequence(&bits, cl)) {
|
|
Packit |
5e46da |
_clpi_free(cl);
|
|
Packit |
5e46da |
return NULL;
|
|
Packit |
5e46da |
}
|
|
Packit |
5e46da |
if (!_parse_program_info(&bits, cl)) {
|
|
Packit |
5e46da |
_clpi_free(cl);
|
|
Packit |
5e46da |
return NULL;
|
|
Packit |
5e46da |
}
|
|
Packit |
5e46da |
if (!_parse_cpi_info(&bits, cl)) {
|
|
Packit |
5e46da |
_clpi_free(cl);
|
|
Packit |
5e46da |
return NULL;
|
|
Packit |
5e46da |
}
|
|
Packit |
5e46da |
|
|
Packit |
5e46da |
return cl;
|
|
Packit |
5e46da |
}
|
|
Packit |
5e46da |
|
|
Packit |
5e46da |
CLPI_CL*
|
|
Packit |
5e46da |
clpi_parse(const char *path)
|
|
Packit |
5e46da |
{
|
|
Packit |
5e46da |
BD_FILE_H *fp;
|
|
Packit |
5e46da |
CLPI_CL *cl;
|
|
Packit |
5e46da |
|
|
Packit |
5e46da |
fp = file_open(path, "rb");
|
|
Packit |
5e46da |
if (!fp) {
|
|
Packit |
5e46da |
BD_DEBUG(DBG_NAV | DBG_CRIT, "Failed to open %s\n", path);
|
|
Packit |
5e46da |
return NULL;
|
|
Packit |
5e46da |
}
|
|
Packit |
5e46da |
|
|
Packit |
5e46da |
cl = _clpi_parse(fp);
|
|
Packit |
5e46da |
file_close(fp);
|
|
Packit |
5e46da |
return cl;
|
|
Packit |
5e46da |
}
|
|
Packit |
5e46da |
|
|
Packit |
5e46da |
static CLPI_CL*
|
|
Packit |
5e46da |
_clpi_get(BD_DISC *disc, const char *dir, const char *file)
|
|
Packit |
5e46da |
{
|
|
Packit |
5e46da |
BD_FILE_H *fp;
|
|
Packit |
5e46da |
CLPI_CL *cl;
|
|
Packit |
5e46da |
|
|
Packit |
5e46da |
fp = disc_open_file(disc, dir, file);
|
|
Packit |
5e46da |
if (!fp) {
|
|
Packit |
5e46da |
return NULL;
|
|
Packit |
5e46da |
}
|
|
Packit |
5e46da |
|
|
Packit |
5e46da |
cl = _clpi_parse(fp);
|
|
Packit |
5e46da |
file_close(fp);
|
|
Packit |
5e46da |
return cl;
|
|
Packit |
5e46da |
}
|
|
Packit |
5e46da |
|
|
Packit |
5e46da |
CLPI_CL*
|
|
Packit |
5e46da |
clpi_get(BD_DISC *disc, const char *file)
|
|
Packit |
5e46da |
{
|
|
Packit |
5e46da |
CLPI_CL *cl;
|
|
Packit |
5e46da |
|
|
Packit |
5e46da |
cl = _clpi_get(disc, "BDMV" DIR_SEP "CLIPINF", file);
|
|
Packit |
5e46da |
if (cl) {
|
|
Packit |
5e46da |
return cl;
|
|
Packit |
5e46da |
}
|
|
Packit |
5e46da |
|
|
Packit |
5e46da |
/* if failed, try backup file */
|
|
Packit |
5e46da |
cl = _clpi_get(disc, "BDMV" DIR_SEP "BACKUP" DIR_SEP "CLIPINF", file);
|
|
Packit |
5e46da |
return cl;
|
|
Packit |
5e46da |
}
|
|
Packit |
5e46da |
|
|
Packit |
5e46da |
CLPI_CL*
|
|
Packit |
5e46da |
clpi_copy(const CLPI_CL* src_cl)
|
|
Packit |
5e46da |
{
|
|
Packit |
5e46da |
CLPI_CL* dest_cl = NULL;
|
|
Packit |
5e46da |
int ii, jj;
|
|
Packit |
5e46da |
|
|
Packit |
5e46da |
if (src_cl) {
|
|
Packit |
5e46da |
dest_cl = (CLPI_CL*) calloc(1, sizeof(CLPI_CL));
|
|
Packit |
5e46da |
if (!dest_cl) {
|
|
Packit |
5e46da |
goto fail;
|
|
Packit |
5e46da |
}
|
|
Packit |
5e46da |
dest_cl->clip.clip_stream_type = src_cl->clip.clip_stream_type;
|
|
Packit |
5e46da |
dest_cl->clip.application_type = src_cl->clip.application_type;
|
|
Packit |
5e46da |
dest_cl->clip.is_atc_delta = src_cl->clip.is_atc_delta;
|
|
Packit |
5e46da |
dest_cl->clip.atc_delta_count = src_cl->clip.atc_delta_count;
|
|
Packit |
5e46da |
dest_cl->clip.ts_recording_rate = src_cl->clip.ts_recording_rate;
|
|
Packit |
5e46da |
dest_cl->clip.num_source_packets = src_cl->clip.num_source_packets;
|
|
Packit |
5e46da |
dest_cl->clip.ts_type_info.validity = src_cl->clip.ts_type_info.validity;
|
|
Packit |
5e46da |
memcpy(dest_cl->clip.ts_type_info.format_id, src_cl->clip.ts_type_info.format_id, 5);
|
|
Packit |
5e46da |
dest_cl->clip.atc_delta = malloc(src_cl->clip.atc_delta_count * sizeof(CLPI_ATC_DELTA));
|
|
Packit |
5e46da |
if (src_cl->clip.atc_delta_count && !dest_cl->clip.atc_delta) {
|
|
Packit |
5e46da |
goto fail;
|
|
Packit |
5e46da |
}
|
|
Packit |
5e46da |
for (ii = 0; ii < src_cl->clip.atc_delta_count; ii++) {
|
|
Packit |
5e46da |
dest_cl->clip.atc_delta[ii].delta = src_cl->clip.atc_delta[ii].delta;
|
|
Packit |
5e46da |
memcpy(dest_cl->clip.atc_delta[ii].file_id, src_cl->clip.atc_delta[ii].file_id, 6);
|
|
Packit |
5e46da |
memcpy(dest_cl->clip.atc_delta[ii].file_code, src_cl->clip.atc_delta[ii].file_code, 5);
|
|
Packit |
5e46da |
}
|
|
Packit |
5e46da |
|
|
Packit |
5e46da |
dest_cl->sequence.num_atc_seq = src_cl->sequence.num_atc_seq;
|
|
Packit |
5e46da |
dest_cl->sequence.atc_seq = calloc(src_cl->sequence.num_atc_seq, sizeof(CLPI_ATC_SEQ));
|
|
Packit |
5e46da |
if (dest_cl->sequence.num_atc_seq && !dest_cl->sequence.atc_seq) {
|
|
Packit |
5e46da |
goto fail;
|
|
Packit |
5e46da |
}
|
|
Packit |
5e46da |
for (ii = 0; ii < src_cl->sequence.num_atc_seq; ii++) {
|
|
Packit |
5e46da |
dest_cl->sequence.atc_seq[ii].spn_atc_start = src_cl->sequence.atc_seq[ii].spn_atc_start;
|
|
Packit |
5e46da |
dest_cl->sequence.atc_seq[ii].offset_stc_id = src_cl->sequence.atc_seq[ii].offset_stc_id;
|
|
Packit |
5e46da |
dest_cl->sequence.atc_seq[ii].num_stc_seq = src_cl->sequence.atc_seq[ii].num_stc_seq;
|
|
Packit |
5e46da |
dest_cl->sequence.atc_seq[ii].stc_seq = malloc(src_cl->sequence.atc_seq[ii].num_stc_seq * sizeof(CLPI_STC_SEQ));
|
|
Packit |
5e46da |
if (dest_cl->sequence.atc_seq[ii].num_stc_seq && !dest_cl->sequence.atc_seq[ii].stc_seq) {
|
|
Packit |
5e46da |
goto fail;
|
|
Packit |
5e46da |
}
|
|
Packit |
5e46da |
for (jj = 0; jj < src_cl->sequence.atc_seq[ii].num_stc_seq; jj++) {
|
|
Packit |
5e46da |
dest_cl->sequence.atc_seq[ii].stc_seq[jj].spn_stc_start = src_cl->sequence.atc_seq[ii].stc_seq[jj].spn_stc_start;
|
|
Packit |
5e46da |
dest_cl->sequence.atc_seq[ii].stc_seq[jj].pcr_pid = src_cl->sequence.atc_seq[ii].stc_seq[jj].pcr_pid;
|
|
Packit |
5e46da |
dest_cl->sequence.atc_seq[ii].stc_seq[jj].presentation_start_time = src_cl->sequence.atc_seq[ii].stc_seq[jj].presentation_start_time;
|
|
Packit |
5e46da |
dest_cl->sequence.atc_seq[ii].stc_seq[jj].presentation_end_time = src_cl->sequence.atc_seq[ii].stc_seq[jj].presentation_end_time;
|
|
Packit |
5e46da |
}
|
|
Packit |
5e46da |
}
|
|
Packit |
5e46da |
|
|
Packit |
5e46da |
dest_cl->program.num_prog = src_cl->program.num_prog;
|
|
Packit |
5e46da |
dest_cl->program.progs = calloc(src_cl->program.num_prog, sizeof(CLPI_PROG));
|
|
Packit |
5e46da |
if (dest_cl->program.num_prog && !dest_cl->program.progs) {
|
|
Packit |
5e46da |
goto fail;
|
|
Packit |
5e46da |
}
|
|
Packit |
5e46da |
for (ii = 0; ii < src_cl->program.num_prog; ii++) {
|
|
Packit |
5e46da |
dest_cl->program.progs[ii].spn_program_sequence_start = src_cl->program.progs[ii].spn_program_sequence_start;
|
|
Packit |
5e46da |
dest_cl->program.progs[ii].program_map_pid = src_cl->program.progs[ii].program_map_pid;
|
|
Packit |
5e46da |
dest_cl->program.progs[ii].num_streams = src_cl->program.progs[ii].num_streams;
|
|
Packit |
5e46da |
dest_cl->program.progs[ii].num_groups = src_cl->program.progs[ii].num_groups;
|
|
Packit |
5e46da |
dest_cl->program.progs[ii].streams = malloc(src_cl->program.progs[ii].num_streams * sizeof(CLPI_PROG_STREAM));
|
|
Packit |
5e46da |
if (src_cl->program.progs[ii].num_streams && !dest_cl->program.progs[ii].streams) {
|
|
Packit |
5e46da |
goto fail;
|
|
Packit |
5e46da |
}
|
|
Packit |
5e46da |
for (jj = 0; jj < src_cl->program.progs[ii].num_streams; jj++) {
|
|
Packit |
5e46da |
dest_cl->program.progs[ii].streams[jj].coding_type = src_cl->program.progs[ii].streams[jj].coding_type;
|
|
Packit |
5e46da |
dest_cl->program.progs[ii].streams[jj].pid = src_cl->program.progs[ii].streams[jj].pid;
|
|
Packit |
5e46da |
dest_cl->program.progs[ii].streams[jj].format = src_cl->program.progs[ii].streams[jj].format;
|
|
Packit |
5e46da |
dest_cl->program.progs[ii].streams[jj].rate = src_cl->program.progs[ii].streams[jj].rate;
|
|
Packit |
5e46da |
dest_cl->program.progs[ii].streams[jj].aspect = src_cl->program.progs[ii].streams[jj].aspect;
|
|
Packit |
5e46da |
dest_cl->program.progs[ii].streams[jj].oc_flag = src_cl->program.progs[ii].streams[jj].oc_flag;
|
|
Packit |
5e46da |
dest_cl->program.progs[ii].streams[jj].char_code = src_cl->program.progs[ii].streams[jj].char_code;
|
|
Packit |
5e46da |
memcpy(dest_cl->program.progs[ii].streams[jj].lang,src_cl->program.progs[ii].streams[jj].lang,4);
|
|
Packit |
5e46da |
}
|
|
Packit |
5e46da |
}
|
|
Packit |
5e46da |
|
|
Packit |
5e46da |
dest_cl->cpi.num_stream_pid = src_cl->cpi.num_stream_pid;
|
|
Packit |
5e46da |
dest_cl->cpi.entry = calloc(src_cl->cpi.num_stream_pid, sizeof(CLPI_EP_MAP_ENTRY));
|
|
Packit |
5e46da |
if (dest_cl->cpi.num_stream_pid && !dest_cl->cpi.entry) {
|
|
Packit |
5e46da |
goto fail;
|
|
Packit |
5e46da |
}
|
|
Packit |
5e46da |
for (ii = 0; ii < dest_cl->cpi.num_stream_pid; ii++) {
|
|
Packit |
5e46da |
dest_cl->cpi.entry[ii].pid = src_cl->cpi.entry[ii].pid;
|
|
Packit |
5e46da |
dest_cl->cpi.entry[ii].ep_stream_type = src_cl->cpi.entry[ii].ep_stream_type;
|
|
Packit |
5e46da |
dest_cl->cpi.entry[ii].num_ep_coarse = src_cl->cpi.entry[ii].num_ep_coarse;
|
|
Packit |
5e46da |
dest_cl->cpi.entry[ii].num_ep_fine = src_cl->cpi.entry[ii].num_ep_fine;
|
|
Packit |
5e46da |
dest_cl->cpi.entry[ii].ep_map_stream_start_addr = src_cl->cpi.entry[ii].ep_map_stream_start_addr;
|
|
Packit |
5e46da |
dest_cl->cpi.entry[ii].coarse = malloc(src_cl->cpi.entry[ii].num_ep_coarse * sizeof(CLPI_EP_COARSE));
|
|
Packit |
5e46da |
if (dest_cl->cpi.entry[ii].num_ep_coarse && !dest_cl->cpi.entry[ii].coarse) {
|
|
Packit |
5e46da |
goto fail;
|
|
Packit |
5e46da |
}
|
|
Packit |
5e46da |
for (jj = 0; jj < src_cl->cpi.entry[ii].num_ep_coarse; jj++) {
|
|
Packit |
5e46da |
dest_cl->cpi.entry[ii].coarse[jj].ref_ep_fine_id = src_cl->cpi.entry[ii].coarse[jj].ref_ep_fine_id;
|
|
Packit |
5e46da |
dest_cl->cpi.entry[ii].coarse[jj].pts_ep = src_cl->cpi.entry[ii].coarse[jj].pts_ep;
|
|
Packit |
5e46da |
dest_cl->cpi.entry[ii].coarse[jj].spn_ep = src_cl->cpi.entry[ii].coarse[jj].spn_ep;
|
|
Packit |
5e46da |
}
|
|
Packit |
5e46da |
dest_cl->cpi.entry[ii].fine = malloc(src_cl->cpi.entry[ii].num_ep_fine * sizeof(CLPI_EP_FINE));
|
|
Packit |
5e46da |
if (dest_cl->cpi.entry[ii].num_ep_fine && !dest_cl->cpi.entry[ii].fine) {
|
|
Packit |
5e46da |
goto fail;
|
|
Packit |
5e46da |
}
|
|
Packit |
5e46da |
for (jj = 0; jj < src_cl->cpi.entry[ii].num_ep_fine; jj++) {
|
|
Packit |
5e46da |
dest_cl->cpi.entry[ii].fine[jj].is_angle_change_point = src_cl->cpi.entry[ii].fine[jj].is_angle_change_point;
|
|
Packit |
5e46da |
dest_cl->cpi.entry[ii].fine[jj].i_end_position_offset = src_cl->cpi.entry[ii].fine[jj].i_end_position_offset;
|
|
Packit |
5e46da |
dest_cl->cpi.entry[ii].fine[jj].pts_ep = src_cl->cpi.entry[ii].fine[jj].pts_ep;
|
|
Packit |
5e46da |
dest_cl->cpi.entry[ii].fine[jj].spn_ep = src_cl->cpi.entry[ii].fine[jj].spn_ep;
|
|
Packit |
5e46da |
}
|
|
Packit |
5e46da |
}
|
|
Packit |
5e46da |
|
|
Packit |
5e46da |
dest_cl->clip.font_info.font_count = src_cl->clip.font_info.font_count;
|
|
Packit |
5e46da |
if (dest_cl->clip.font_info.font_count) {
|
|
Packit |
5e46da |
dest_cl->clip.font_info.font = malloc(dest_cl->clip.font_info.font_count * sizeof(CLPI_FONT));
|
|
Packit |
5e46da |
if (!dest_cl->clip.font_info.font) {
|
|
Packit |
5e46da |
goto fail;
|
|
Packit |
5e46da |
}
|
|
Packit |
5e46da |
memcpy(dest_cl->clip.font_info.font, src_cl->clip.font_info.font, dest_cl->clip.font_info.font_count * sizeof(CLPI_FONT));
|
|
Packit |
5e46da |
}
|
|
Packit |
5e46da |
}
|
|
Packit |
5e46da |
|
|
Packit |
5e46da |
return dest_cl;
|
|
Packit |
5e46da |
|
|
Packit |
5e46da |
fail:
|
|
Packit |
5e46da |
BD_DEBUG(DBG_CRIT, "out of memory\n");
|
|
Packit |
5e46da |
clpi_free(&dest_cl);
|
|
Packit |
5e46da |
return NULL;
|
|
Packit |
5e46da |
}
|