📄 dvdnvpck.c
字号:
/*****************************************************************************
******************************************************************************
** **
** Copyright (c) 2002 Videon Central, Inc. **
** All rights reserved. **
** **
** The computer program contained herein contains proprietary information **
** which is the property of Videon Central, Inc. The program may be used **
** and/or copied only with the written permission of Videon Central, Inc. **
** or in accordance with the terms and conditions stipulated in the **
** agreement/contract under which the programs have been supplied. **
** **
******************************************************************************
*****************************************************************************/
/**
* @file dvdnvpck.c
*
* DVD Navigation-Pack Parser.
*
* $Id: dvdnvpck.c,v 1.25 2006/10/26 18:35:27 eric Exp $
*/
#include <stdio.h>
#include "vdvd_types.h"
#include "dvd_vmgi.h" /* Video Manager Information file structure defs */
#include "dvd_pgci.h" /* includes dvd_cmd.h */
#include "dvdnvpck.h" /* Navi-pack structure definitions */
#include "timer.h"
#include "dbgprint.h"
#include "utility.h"
#ifdef DMALLOC
#include "dmalloc.h"
#endif
nvpck_struct nvpck[NAV_BUFFER_SIZE];
UBYTE ssbuf[2048];
/* Lookup table for logical button number given the group number and
absolute position within the button table (relative to zero). */
const UBYTE lbtn[MAX_BTNGR_NS][MAX_BTN_NS] =
{
{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36},
{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18},
{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12}
};
BOOLEAN parse_pci(UBYTE * buf);
BOOLEAN parse_dsi(UBYTE * buf);
/**
* parse_nvpck()
* Read in the navigation packet & decode it
*
* @param pbPCIPacket - pointer to PCI packet buffer
* @param pbDSIPacket - pointer to DSI packet buffer
*
* @return SUCCESS or FAILURE
*
* @date 03/24/2003 rbehe prototype modified, and parse seems to be succeeding.
*/
BOOLEAN parse_nvpck(BYTE *pbPCIPacket, BYTE *pbDSIPacket)
{
/*
* We should have 979+7+1017+7 bytes in DSI/PCI buffer = 2010, but the
* granularity of the read is 8 bytes, so it would indicate 2008 bytes.
* We should be OK as long as we have more than this but not overflow
*/
/* read the navi-pack into the sector buffer */
/*
* PCI is 979 bytes + 1 byte for sub-stream ID = 0x03D4 first seven bytes
* should be 00 00 01 BF 03 D4 00 private_stream_2 start
* code___//_//_//_// || || || packet_length___//_// || sub_stream_id
* __//
*/
if (parse_pci(pbPCIPacket) == FAILURE)
{
DbgPrint(("parse_nvpck: parse_pci FAILURE\n"));
return (FAILURE);
}
/*
* DSI is 1017 bytes + 1 byte for sub-stream ID = 0x03FA next bytes
* agfter PCI should be 00 00 01 BF 03 FA 01 private_stream_2 start
* code___//_//_//_// || || || packet_length___//_// || sub_stream_id
* __//
*/
if (parse_dsi(pbDSIPacket) == FAILURE)
{
DbgPrint(("parse_dsi() - FAILURE\n"));
return (FAILURE);
}
if (nvpck[LATEST_LOCAL].pci_gi.nv_pck_lbn != nvpck[LATEST_LOCAL].dsi_gi.nv_pck_lbn)
{
DbgPrint(("PCI, DSI Packet mismatch! pci=%lx, dsi=%lx\n",
(unsigned long)nvpck[LATEST_LOCAL].pci_gi.nv_pck_lbn, (unsigned long)nvpck[LATEST_LOCAL].dsi_gi.nv_pck_lbn));
return (FAILURE);
}
return (SUCCESS);
}
/**
** Name: parse_pci
**
** Description: parse the PCI information from the NV_PCK
**
** Arguments: buf - pointer to array of bytes where PCI resides
**
** Returns: SUCCESS or FAILURE
**
* Functionality:
* Presentation Control Information (PCI) is the Navigation Data to control
* the presentation of a VOB Unit (VOBU).
*
**/
BOOLEAN parse_pci(UBYTE * buf)
{
USHORT n, i, j;
/* parse the PCI_GI for a total of 60 bytes */
n = 7;
/* parse NV_PCK_LBN in PCI */
nvpck[LATEST_LOCAL].pci_gi.nv_pck_lbn = MAKE_DWORD(&buf[n]);
n += 4;
nvpck[LATEST_LOCAL].pci_gi.apstb = buf[n] >> 6;
/* skip over reserved bytes in VOBU_CAT & beyond */
n += 4;
/* get VOBU_UOP_CTL */
for (i = 0; i < 4; i++)
{
nvpck[LATEST_LOCAL].pci_gi.vobu_uop_ctl[i] = buf[n++];
}
/* get VOBU_S_PTM */
nvpck[LATEST_LOCAL].pci_gi.vobu_s_ptm = MAKE_DWORD(&buf[n]);
n += 4;
/* get VOBU_E_PTM */
nvpck[LATEST_LOCAL].pci_gi.vobu_e_ptm = MAKE_DWORD(&buf[n]);
n += 4;
/* get VOBU_SE_E_PTM */
nvpck[LATEST_LOCAL].pci_gi.vobu_se_e_ptm = MAKE_DWORD(&buf[n]);
n += 4;
nvpck[LATEST_LOCAL].pci_gi.c_eltm = MAKE_DWORD(&buf[n]);
/* skip over Cell Elapse Time and reserved bytes */
n += 4 + 32; /* 32 bytes reserved */
/* parse the NSML_AGLI for a total of 36 bytes */
for (i = 0; i < MAX_ANGLES; i++, n += 4)
{
nvpck[LATEST_LOCAL].nsml_agli[i] = MAKE_DWORD(&buf[n]);
}
/* initialize highlight */
nvpck[LATEST_LOCAL].hl_gi.hli_s_ptm = 0;
nvpck[LATEST_LOCAL].hl_gi.hli_e_ptm = 0;
nvpck[LATEST_LOCAL].hl_gi.btn_sl_e_ptm = 0;
nvpck[LATEST_LOCAL].hl_gi.btngr_ns = 0;
nvpck[LATEST_LOCAL].hl_gi.btngr1_dsp_ty = 0;
nvpck[LATEST_LOCAL].hl_gi.btngr2_dsp_ty = 0;
nvpck[LATEST_LOCAL].hl_gi.btngr3_dsp_ty = 0;
nvpck[LATEST_LOCAL].hl_gi.btn_ofn = 0;
nvpck[LATEST_LOCAL].hl_gi.btn_ns = 0;
nvpck[LATEST_LOCAL].hl_gi.nsl_btn_ns = 0;
nvpck[LATEST_LOCAL].hl_gi.fosl_btnn = 0;
nvpck[LATEST_LOCAL].hl_gi.foac_btnn = 0;
/* parse the HLI for a total of 694 bytes */
/* starting with 22 bytes of HL_GI */
n++;
nvpck[LATEST_LOCAL].hl_gi.hli_ss = buf[n] & 0x03;
if (nvpck[LATEST_LOCAL].hl_gi.hli_ss == 0)
{
/* the rest of the HLI is to be invalid, not a failure - we're just done */
return (SUCCESS);
}
n += 1;
/* get HLI_S_PTM */
nvpck[LATEST_LOCAL].hl_gi.hli_s_ptm = MAKE_DWORD(&buf[n]);
n += 4;
/* get HLI_E_PTM */
nvpck[LATEST_LOCAL].hl_gi.hli_e_ptm = MAKE_DWORD(&buf[n]);
n += 4;
/* get BTN_SL_E_PTM */
nvpck[LATEST_LOCAL].hl_gi.btn_sl_e_ptm = MAKE_DWORD(&buf[n]);
n += 4;
/* get BTN_MD stuff */
nvpck[LATEST_LOCAL].hl_gi.btngr_ns = (buf[n] >> 4) & 0x03;
nvpck[LATEST_LOCAL].hl_gi.btngr1_dsp_ty = buf[n] & 0x07;
n += 1;
nvpck[LATEST_LOCAL].hl_gi.btngr2_dsp_ty = (buf[n] >> 4) & 0x07;
nvpck[LATEST_LOCAL].hl_gi.btngr3_dsp_ty = buf[n] & 0x07;
n += 1;
/* get BTN_OFN */
nvpck[LATEST_LOCAL].hl_gi.btn_ofn = buf[n];
n += 1;
/* get BTN_Ns */
nvpck[LATEST_LOCAL].hl_gi.btn_ns = buf[n] & 0x3F;
n += 1;
/* check for invalid button information */
if ( ( (nvpck[LATEST_LOCAL].hl_gi.btngr_ns == 0) ) ||
( (nvpck[LATEST_LOCAL].hl_gi.btngr_ns == 1) && (nvpck[LATEST_LOCAL].hl_gi.btn_ns > MAX_BTN_NS ) ) ||
( (nvpck[LATEST_LOCAL].hl_gi.btngr_ns == 2) && (nvpck[LATEST_LOCAL].hl_gi.btn_ns > MAX_BTN_NS / 2) ) ||
( (nvpck[LATEST_LOCAL].hl_gi.btngr_ns == 3) && (nvpck[LATEST_LOCAL].hl_gi.btn_ns > MAX_BTN_NS / 3) ) )
{
nvpck[LATEST_LOCAL].hl_gi.hli_ss = 0;
return (SUCCESS);
}
/* get NSL_BTN_Ns */
nvpck[LATEST_LOCAL].hl_gi.nsl_btn_ns = buf[n] & 0x3F;
n += 2; /* reserved byte here */
/* check for invalid button information */
if ( ( (nvpck[LATEST_LOCAL].hl_gi.btngr_ns == 1) && (nvpck[LATEST_LOCAL].hl_gi.nsl_btn_ns > MAX_BTN_NS ) ) ||
( (nvpck[LATEST_LOCAL].hl_gi.btngr_ns == 2) && (nvpck[LATEST_LOCAL].hl_gi.nsl_btn_ns > MAX_BTN_NS / 2) ) ||
( (nvpck[LATEST_LOCAL].hl_gi.btngr_ns == 3) && (nvpck[LATEST_LOCAL].hl_gi.nsl_btn_ns > MAX_BTN_NS / 3) ) )
{
nvpck[LATEST_LOCAL].hl_gi.hli_ss = 0;
return (SUCCESS);
}
/* get FOSL_BTNN */
/* set SPRM(8) to the value of FOSL_BTNN at the time of HLI_S_PTM */
nvpck[LATEST_LOCAL].hl_gi.fosl_btnn = buf[n] & 0x3F;
n += 1;
/* get FOAC_BTNN */
nvpck[LATEST_LOCAL].hl_gi.foac_btnn = buf[n] & 0x3F;
n += 1;
/* next is 8 bytes x 3 groups of Button Color Information Table */
for (i = 0; i < 3; i++)
{
/* get SL_COLI for each group */
for (j = 0; j < 4; j++)
{
nvpck[LATEST_LOCAL].btn_colit[i].sl_coli[j] = buf[n++];
}
/* get AC_COLI for each group */
for (j = 0; j < 4; j++)
{
nvpck[LATEST_LOCAL].btn_colit[i].ac_coli[j] = buf[n++];
}
}
/*
* Next we have 18 bytes x 36 of Button Information Tables. This could be
* arranged as one 36 BTNIs group mode, two 18 BTNIs group mode or three
* 12 BTNIs group mode.
*/
for (i = 0; i < MAX_BTN_NS; i++) /* for each button */
{
/* first parse the Button Position Information (6 bytes) */
for (j = 0; j < SIZEOF_BTN_POSI; j++)
{
nvpck[LATEST_LOCAL].btn_posi[i][j] = buf[n + j];
}
n += SIZEOF_BTN_POSI;
/* then parse the Adjacent Button Position Information (4 bytes) */
nvpck[LATEST_LOCAL].ajbtn_posi[i].upper_btn = buf[n++] & 0x3F;
nvpck[LATEST_LOCAL].ajbtn_posi[i].lower_btn = buf[n++] & 0x3F;
nvpck[LATEST_LOCAL].ajbtn_posi[i].left_btn = buf[n++] & 0x3F;
nvpck[LATEST_LOCAL].ajbtn_posi[i].right_btn = buf[n++] & 0x3F;
/* finally parse the Button Command (8 bytes) */
for (j = 0; j < SIZEOF_CMD; j++)
{
nvpck[LATEST_LOCAL].btn_cmd[i][j] = buf[n++];
}
}
/* skip ahead by how many fewer than 36 buttons we parsed above */
n += 18 * (36 - nvpck[LATEST_LOCAL].hl_gi.btn_ns);
/* parse the RECI for a total of 189 bytes */
return (SUCCESS); /* don't really care about Recording Information
* right now */
}
/**
** Name: parse_dsi
**
** Description: parse the DSI information from the NV_PCK
**
** Arguments: buf - pointer to array of bytes where DSI resides
**
** Returns: SUCCESS or FAILURE
**
* Structures:
*
* Pseudocode:
*
* Functionality:
* Data Search Information (DSI) is the Navigation Data to search and carry
* out Seamless playback of the VOB Unit (VOBU).
*
**/
BOOLEAN parse_dsi(UBYTE * buf)
{
USHORT n, i;
/* parse the DSI_GI for a total of 32 bytes */
n = 7;
/* get NV_PCK_SCR */
nvpck[LATEST_LOCAL].dsi_gi.nv_pck_scr = MAKE_DWORD(&buf[n]);
n += 4;
/* get NV_PCK_LBN */
nvpck[LATEST_LOCAL].dsi_gi.nv_pck_lbn = MAKE_DWORD(&buf[n]);
n += 4;
/* get VOBU_EA */
nvpck[LATEST_LOCAL].dsi_gi.vobu_ea = MAKE_DWORD(&buf[n]);
n += 4;
/* get VOBU_1STREF_EA */
nvpck[LATEST_LOCAL].dsi_gi.vobu_1stref_ea = MAKE_DWORD(&buf[n]);
n += 4;
/* get VOBU_2NDREF_EA */
nvpck[LATEST_LOCAL].dsi_gi.vobu_2ndref_ea = MAKE_DWORD(&buf[n]);
n += 4;
/* get VOBU_3RDREF_EA */
nvpck[LATEST_LOCAL].dsi_gi.vobu_3rdref_ea = MAKE_DWORD(&buf[n]);
n += 4;
/* get VOBU_VOB_IDN */
nvpck[LATEST_LOCAL].dsi_gi.vobu_vob_idn = MAKE_WORD(&buf[n]);
n += 3; /* reserved byte follows VOBU_VOB_IDN */
/* get VOBU_C_IDN */
nvpck[LATEST_LOCAL].dsi_gi.vobu_c_idn = buf[n];
n += 1;
/* dump Cell Elapse Time on the floor */
n += 4;
/* next parse the SML_PBI for a total of 148 bytes */
/* starting with VOBU_SML_CAT */
nvpck[LATEST_LOCAL].sml_pbi.vobu_sml_cat = MAKE_WORD(&buf[n]);
n += 2; /* skip reserved byte */
/* get ILVU_EA */
nvpck[LATEST_LOCAL].sml_pbi.ilvu_ea = MAKE_DWORD(&buf[n]);
n += 4;
/* get NXT_ILVU_SA */
nvpck[LATEST_LOCAL].sml_pbi.nxt_ilvu_sa = MAKE_DWORD(&buf[n]);
n += 4;
/* get NXT_ILVU_SZ */
nvpck[LATEST_LOCAL].sml_pbi.nxt_ilvu_sz = MAKE_WORD(&buf[n]);
n += 2;
/* get VOB_V_S_PTM */
nvpck[LATEST_LOCAL].sml_pbi.vob_v_s_ptm = MAKE_DWORD(&buf[n]);
n += 4;
/* get VOB_V_E_PTM */
nvpck[LATEST_LOCAL].sml_pbi.vob_v_e_ptm = MAKE_DWORD(&buf[n]);
n += 4;
for (i = 0; i < 8; i++)
{
/* get VOB_A_STP_PTM1 for each audio stream number */
nvpck[LATEST_LOCAL].sml_pbi.vob_a_stp_ptm1[i] = MAKE_DWORD(&buf[n]);
n += 4;
/* get VOB_A_STP_PTM2 for each audio stream number */
nvpck[LATEST_LOCAL].sml_pbi.vob_a_stp_ptm2[i] = MAKE_DWORD(&buf[n]);
n += 4;
}
for (i = 0; i < 8; i++)
{
/* get VOB_A_GAP_LEN1 for each audio stream number */
nvpck[LATEST_LOCAL].sml_pbi.vob_a_gap_len1[i] = MAKE_DWORD(&buf[n]);
n += 4;
/* get VOB_A_GAP_LEN2 for each audio stream number */
nvpck[LATEST_LOCAL].sml_pbi.vob_a_gap_len2[i] = MAKE_DWORD(&buf[n]);
n += 4;
}
/* next parse the SML_AGLI for a total of 54 bytes */
for (i = 0; i < MAX_ANGLES; i++)
{
nvpck[LATEST_LOCAL].sml_agli[i].agl_c_dsta = MAKE_DWORD(&buf[n]);
n += 4;
nvpck[LATEST_LOCAL].sml_agli[i].agl_c_sz = MAKE_WORD(&buf[n]);
n += 2;
}
/* next parse the VOBU_SRI for a total of 168 bytes */
for (i = 0; i < 42; i++)
{
nvpck[LATEST_LOCAL].vobu_sri[i] = MAKE_DWORD(&buf[n]);
n += 4;
}
/* finally parse the SYNCI for a total of 144 bytes */
for (i = 0; i < 8; i++)
{
nvpck[LATEST_LOCAL].synci.a_synca[i] = MAKE_WORD(&buf[n]);
n += 2;
}
for (i = 0; i < 32; i++)
{
nvpck[LATEST_LOCAL].synci.sp_synca[i] = MAKE_DWORD(&buf[n]);
n += 4;
}
return (SUCCESS);
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -