| 1 | /*************************************************************************** |
|---|
| 2 | * (c)2007-2011 Broadcom Corporation |
|---|
| 3 | * |
|---|
| 4 | * This program is the proprietary software of Broadcom Corporation and/or its licensors, |
|---|
| 5 | * and may only be used, duplicated, modified or distributed pursuant to the terms and |
|---|
| 6 | * conditions of a separate, written license agreement executed between you and Broadcom |
|---|
| 7 | * (an "Authorized License"). Except as set forth in an Authorized License, Broadcom grants |
|---|
| 8 | * no license (express or implied), right to use, or waiver of any kind with respect to the |
|---|
| 9 | * Software, and Broadcom expressly reserves all rights in and to the Software and all |
|---|
| 10 | * intellectual property rights therein. IF YOU HAVE NO AUTHORIZED LICENSE, THEN YOU |
|---|
| 11 | * HAVE NO RIGHT TO USE THIS SOFTWARE IN ANY WAY, AND SHOULD IMMEDIATELY |
|---|
| 12 | * NOTIFY BROADCOM AND DISCONTINUE ALL USE OF THE SOFTWARE. |
|---|
| 13 | * |
|---|
| 14 | * Except as expressly set forth in the Authorized License, |
|---|
| 15 | * |
|---|
| 16 | * 1. This program, including its structure, sequence and organization, constitutes the valuable trade |
|---|
| 17 | * secrets of Broadcom, and you shall use all reasonable efforts to protect the confidentiality thereof, |
|---|
| 18 | * and to use this information only in connection with your use of Broadcom integrated circuit products. |
|---|
| 19 | * |
|---|
| 20 | * 2. TO THE MAXIMUM EXTENT PERMITTED BY LAW, THE SOFTWARE IS PROVIDED "AS IS" |
|---|
| 21 | * AND WITH ALL FAULTS AND BROADCOM MAKES NO PROMISES, REPRESENTATIONS OR |
|---|
| 22 | * WARRANTIES, EITHER EXPRESS, IMPLIED, STATUTORY, OR OTHERWISE, WITH RESPECT TO |
|---|
| 23 | * THE SOFTWARE. BROADCOM SPECIFICALLY DISCLAIMS ANY AND ALL IMPLIED WARRANTIES |
|---|
| 24 | * OF TITLE, MERCHANTABILITY, NONINFRINGEMENT, FITNESS FOR A PARTICULAR PURPOSE, |
|---|
| 25 | * LACK OF VIRUSES, ACCURACY OR COMPLETENESS, QUIET ENJOYMENT, QUIET POSSESSION |
|---|
| 26 | * OR CORRESPONDENCE TO DESCRIPTION. YOU ASSUME THE ENTIRE RISK ARISING OUT OF |
|---|
| 27 | * USE OR PERFORMANCE OF THE SOFTWARE. |
|---|
| 28 | * |
|---|
| 29 | * 3. TO THE MAXIMUM EXTENT PERMITTED BY LAW, IN NO EVENT SHALL BROADCOM OR ITS |
|---|
| 30 | * LICENSORS BE LIABLE FOR (i) CONSEQUENTIAL, INCIDENTAL, SPECIAL, INDIRECT, OR |
|---|
| 31 | * EXEMPLARY DAMAGES WHATSOEVER ARISING OUT OF OR IN ANY WAY RELATING TO YOUR |
|---|
| 32 | * USE OF OR INABILITY TO USE THE SOFTWARE EVEN IF BROADCOM HAS BEEN ADVISED OF |
|---|
| 33 | * THE POSSIBILITY OF SUCH DAMAGES; OR (ii) ANY AMOUNT IN EXCESS OF THE AMOUNT |
|---|
| 34 | * ACTUALLY PAID FOR THE SOFTWARE ITSELF OR U.S. $1, WHICHEVER IS GREATER. THESE |
|---|
| 35 | * LIMITATIONS SHALL APPLY NOTWITHSTANDING ANY FAILURE OF ESSENTIAL PURPOSE OF |
|---|
| 36 | * ANY LIMITED REMEDY. |
|---|
| 37 | * |
|---|
| 38 | * $brcm_Workfile: nexus_playpump.c $ |
|---|
| 39 | * $brcm_Revision: 114 $ |
|---|
| 40 | * $brcm_Date: 12/20/11 1:43p $ |
|---|
| 41 | * |
|---|
| 42 | * Module Description: |
|---|
| 43 | * |
|---|
| 44 | * Revision History: |
|---|
| 45 | * |
|---|
| 46 | * $brcm_Log: /nexus/modules/transport/7400/src/nexus_playpump.c $ |
|---|
| 47 | * |
|---|
| 48 | * 114 12/20/11 1:43p vsilyaev |
|---|
| 49 | * SW7425-2034: Used 32-bit type for program id (pid) types |
|---|
| 50 | * |
|---|
| 51 | * 113 12/19/11 10:06a erickson |
|---|
| 52 | * SW7425-1795: validate driver-side CPU accessibility of playback fifo |
|---|
| 53 | * |
|---|
| 54 | * 112 12/9/11 5:22p bandrews |
|---|
| 55 | * SW7550-772: merge to main |
|---|
| 56 | * |
|---|
| 57 | * SW7550-772/1 12/9/11 4:07p bandrews |
|---|
| 58 | * SW7550-772: change playpump to always use the default timebase, instead |
|---|
| 59 | * of possibly using no timebase |
|---|
| 60 | * |
|---|
| 61 | * 111 12/5/11 10:43a erickson |
|---|
| 62 | * SW7231-497: allow NEXUS_PlaypumpOpenSettings.fifoSize = 0 for |
|---|
| 63 | * scatter/gather-only usage |
|---|
| 64 | * |
|---|
| 65 | * 110 11/29/11 11:39a erickson |
|---|
| 66 | * SW7420-2129: get current default heap using NEXUS_P_DefaultHeap |
|---|
| 67 | * |
|---|
| 68 | * 109 11/2/11 3:55p mward |
|---|
| 69 | * SW7346-523: Fix compile error if !BXPT_HAS_32BIT_PB_TIMESTAMPS. |
|---|
| 70 | * |
|---|
| 71 | * 108 10/31/11 7:48p bandrews |
|---|
| 72 | * SW7231-391: merge to main |
|---|
| 73 | * |
|---|
| 74 | * SW7420-2078/3 10/28/11 3:49p bandrews |
|---|
| 75 | * SW7231-391: update timebase to a pointer |
|---|
| 76 | * |
|---|
| 77 | * SW7420-2078/2 10/27/11 8:07p bandrews |
|---|
| 78 | * SW7231-391: merge from main |
|---|
| 79 | * |
|---|
| 80 | * 107 10/28/11 1:27p erickson |
|---|
| 81 | * SW7346-523: extend NEXUS_TransportTimestamp to handle 32 bit timestamps |
|---|
| 82 | * and to be more explicit about 28/30 bit timestamps |
|---|
| 83 | * |
|---|
| 84 | * 106 10/26/11 9:30a erickson |
|---|
| 85 | * SW7346-525: apply pacingOffsetAdjustDisable using XPT PI, not PB0-only |
|---|
| 86 | * register write |
|---|
| 87 | * |
|---|
| 88 | * 105 10/17/11 11:38a gmullen |
|---|
| 89 | * SW7425-1383: Merged to main |
|---|
| 90 | * |
|---|
| 91 | * SW7425-1383/2 10/14/11 4:09p gmullen |
|---|
| 92 | * SW7425-1383: Updated per David's suggestions |
|---|
| 93 | * |
|---|
| 94 | * SW7425-1383/1 10/11/11 3:45p gmullen |
|---|
| 95 | * SW7425-1383: Added API to return the chip-specific allPass PID channel |
|---|
| 96 | * number |
|---|
| 97 | * |
|---|
| 98 | * SW7420-2078/1 10/25/11 5:22p bandrews |
|---|
| 99 | * SW7231-391: update parser band and timebase implementations to use |
|---|
| 100 | * handles everywhere, even for legacy enum usage |
|---|
| 101 | * |
|---|
| 102 | * 104 9/14/11 12:11p jtna |
|---|
| 103 | * SW7420-2054: enforce boundsHeap for scatter-gather |
|---|
| 104 | * |
|---|
| 105 | * 103 9/8/11 10:56a erickson |
|---|
| 106 | * SW7408-284: add comment explaining 32/30_2U/28_4P timestamp modes for |
|---|
| 107 | * live, playback and record |
|---|
| 108 | * |
|---|
| 109 | * 102 9/2/11 12:40p erickson |
|---|
| 110 | * SW7420-1995: unregister handles from objdb when doing automatic close |
|---|
| 111 | * |
|---|
| 112 | * 101 8/2/11 2:53p erickson |
|---|
| 113 | * SW7420-1978: use BXPT_PB_SYNC_MPEG for TS for all silicon |
|---|
| 114 | * |
|---|
| 115 | * 100 7/21/11 7:06p jtna |
|---|
| 116 | * SW7125-1015: assert pNumConsumed in |
|---|
| 117 | * NEXUS_Playpump_SubmitScatterGatherDescriptor() |
|---|
| 118 | * |
|---|
| 119 | * 99 7/21/11 2:28p jtna |
|---|
| 120 | * SW7125-1015: added NEXUS_Playpump_SubmitScatterGatherDescriptor() |
|---|
| 121 | * |
|---|
| 122 | * 98 5/12/11 3:41p jtna |
|---|
| 123 | * SW7550-739: replace all instances of 'NEXUS_HAS_DMA && |
|---|
| 124 | * NEXUS_HAS_SECURITY' with 'NEXUS_ENCRYPTED_DVR_WITH_M2M'. replace some |
|---|
| 125 | * instances of 'NEXUS_HAS_DMA' with 'NEXUS_NUM_DMA_CHANNELS' |
|---|
| 126 | * |
|---|
| 127 | * 97 3/8/11 6:08p vsilyaev |
|---|
| 128 | * SW7422-101: Updated logic of handling continuityCountEnabled, so per |
|---|
| 129 | * band and per pid settings are combined with logical AND |
|---|
| 130 | * |
|---|
| 131 | * 96 2/28/11 12:00p hongtaoz |
|---|
| 132 | * SW7425-93, SW7425-39: remove hardcoded PES pacing timebase setting |
|---|
| 133 | * which is set properly now by stream mux; |
|---|
| 134 | * |
|---|
| 135 | * 95 2/25/11 4:46p vsilyaev |
|---|
| 136 | * SW7422-107, SW7425-39: Fixed typo |
|---|
| 137 | * |
|---|
| 138 | * 94 2/22/11 7:53p vsilyaev |
|---|
| 139 | * SW7422-107: Added FLV mapping |
|---|
| 140 | * |
|---|
| 141 | * 93 1/28/11 8:55a erickson |
|---|
| 142 | * SW7420-1440: add internal hooks so that NEXUS_PidChannel_Close can |
|---|
| 143 | * close playpump pidchannels (but not playback pidchannels) |
|---|
| 144 | * |
|---|
| 145 | * 92 1/17/11 9:31a erickson |
|---|
| 146 | * SW7425-68: add NEXUS_TransportModuleSettings.mainHeapIndex |
|---|
| 147 | * |
|---|
| 148 | * 91 12/30/10 7:41p vsilyaev |
|---|
| 149 | * SW7425-39: Removed special timestamp mode |
|---|
| 150 | * |
|---|
| 151 | * 90 12/30/10 6:42p vsilyaev |
|---|
| 152 | * SW7425-39: Use special timestamp mode for mux |
|---|
| 153 | * |
|---|
| 154 | * 89 12/28/10 5:44p vsilyaev |
|---|
| 155 | * SW7425-39: Added Mux specific interfaces |
|---|
| 156 | * |
|---|
| 157 | * 88 12/27/10 12:18p erickson |
|---|
| 158 | * SW7425-39: fix warning |
|---|
| 159 | * |
|---|
| 160 | * 87 12/23/10 3:25p vsilyaev |
|---|
| 161 | * SW7425-39: Start/stop playpump inside mux |
|---|
| 162 | * |
|---|
| 163 | * 86 12/16/10 6:12p vsilyaev |
|---|
| 164 | * SW7425-39: Added playpump private API |
|---|
| 165 | * |
|---|
| 166 | * 85 12/16/10 5:05p erickson |
|---|
| 167 | * SW7125-763: restore micropause after flush |
|---|
| 168 | * |
|---|
| 169 | * 84 12/13/10 6:59p vsilyaev |
|---|
| 170 | * SW7425-39: Added support for MUX input |
|---|
| 171 | * |
|---|
| 172 | * 83 12/9/10 9:50a erickson |
|---|
| 173 | * SW7420-1148: fix warning |
|---|
| 174 | * |
|---|
| 175 | * 82 12/7/10 5:46p erickson |
|---|
| 176 | * SW7420-1148: added null_allowed, boundsHeap |
|---|
| 177 | * |
|---|
| 178 | * 81 11/5/10 12:28p gmohile |
|---|
| 179 | * SW7422-20 : Use BXPT_HAS_PID_CHANNEL_PES_FILTERING instead of |
|---|
| 180 | * BXPT_P_MAX_PACKETIZERS_PER_PB |
|---|
| 181 | * |
|---|
| 182 | * 80 11/3/10 4:32p erickson |
|---|
| 183 | * SW7422-20: use BXPT_P_MAX_PACKETIZERS_PER_PB instead of |
|---|
| 184 | * NEXUS_SW_VOB_SUPPORT |
|---|
| 185 | * |
|---|
| 186 | * 79 10/28/10 5:09p erickson |
|---|
| 187 | * SW7422-20: adapt to new XPT PI (backward compat using magnum and nexus |
|---|
| 188 | * macros) |
|---|
| 189 | * |
|---|
| 190 | * 78 10/1/10 9:41a erickson |
|---|
| 191 | * SW7420-1009: support NEXUS_ANY_ID |
|---|
| 192 | * |
|---|
| 193 | * 77 9/13/10 6:02p spothana |
|---|
| 194 | * SW7420-662: Increase the number of playback channels supported |
|---|
| 195 | * |
|---|
| 196 | * 76 8/18/10 12:26p vsilyaev |
|---|
| 197 | * SW3556-1175: Added substream ID mapping for EAC3 audio |
|---|
| 198 | * |
|---|
| 199 | * 75 8/10/10 3:33p erickson |
|---|
| 200 | * SW7420-934: rename NEXUS_Playpump_ReadComplete to |
|---|
| 201 | * NEXUS_Playpump_WriteComplete |
|---|
| 202 | * |
|---|
| 203 | * 74 6/11/10 6:58p mphillip |
|---|
| 204 | * SW7125-463: Allow the user to configure DMA data format in playpump |
|---|
| 205 | * |
|---|
| 206 | * 73 6/7/10 6:23p mphillip |
|---|
| 207 | * SW7550-398: Update examples and transport code to support non-DMA |
|---|
| 208 | * encrypted PVR |
|---|
| 209 | * |
|---|
| 210 | * 72 4/9/10 1:07p jgarrett |
|---|
| 211 | * SW7405-4034: Moving MSDRM PD/ND binaries into nexus as required |
|---|
| 212 | * |
|---|
| 213 | * DrmMakefileUpdates/2 4/9/10 10:40a jgarrett |
|---|
| 214 | * SW7405-4034: Removing stale MSDRM lines regarding ASF decryption |
|---|
| 215 | * |
|---|
| 216 | * DrmMakefileUpdates/1 4/8/10 4:46p jgarrett |
|---|
| 217 | * SW7405-4034: Including binaries for MSDRM (PD/ND) in the nexus builds |
|---|
| 218 | * to avoid link issues |
|---|
| 219 | * |
|---|
| 220 | * 71 1/21/10 5:56p vsilyaev |
|---|
| 221 | * SW3556-1003: Added option to disable timestamp reordering inside bmedia |
|---|
| 222 | * |
|---|
| 223 | * 70 12/29/09 12:51p erickson |
|---|
| 224 | * SW7550-146: allow security module to be initialized after the transport |
|---|
| 225 | * module if HW requires it |
|---|
| 226 | * |
|---|
| 227 | * 69 11/3/09 9:56a erickson |
|---|
| 228 | * SW7405-3308: add TEI error callback |
|---|
| 229 | * |
|---|
| 230 | * 68 10/22/09 4:14p erickson |
|---|
| 231 | * SW7405-3245: fix playpump bprofile support |
|---|
| 232 | * |
|---|
| 233 | * 67 10/1/09 5:03p erickson |
|---|
| 234 | * SW7405-3087: add playpump cc check, add cc error counting per pid |
|---|
| 235 | * |
|---|
| 236 | * 66 8/19/09 1:49p gmohile |
|---|
| 237 | * PR 57814 : Add dvd vob support for 7401 |
|---|
| 238 | * |
|---|
| 239 | * 65 6/11/09 5:05p jtna |
|---|
| 240 | * PR55767: added NEXUS_PlaypumpSettings.timestamp.forceRestamping |
|---|
| 241 | * |
|---|
| 242 | * 64 6/11/09 4:31p jtna |
|---|
| 243 | * PR55817: make check on duplicate channels backward-compatible |
|---|
| 244 | * |
|---|
| 245 | * 63 6/9/09 3:09p jtna |
|---|
| 246 | * PR55767: refactor timestamp record |
|---|
| 247 | * |
|---|
| 248 | * 62 6/8/09 3:47p erickson |
|---|
| 249 | * PR55817: relax the check on duplicate pid channels. they are allowed, |
|---|
| 250 | * as long as they are simultaneously enabled. we still prevent duplicate |
|---|
| 251 | * NEXUS_PidChannelHandle entries. |
|---|
| 252 | * |
|---|
| 253 | * 61 6/3/09 7:12p mward |
|---|
| 254 | * PR 51821: Set the AlwaysResumeFromLastDescriptor = true in |
|---|
| 255 | * NEXUS_Playpump_Open() also, to avoid warnings from XPT. |
|---|
| 256 | * |
|---|
| 257 | * PR51821/1 6/1/09 12:23p vsilyaev |
|---|
| 258 | * PR 51821: Always append chain to the last playback descriptor |
|---|
| 259 | * |
|---|
| 260 | * 59 6/1/09 8:45a erickson |
|---|
| 261 | * PR55461: set PARSER_FORCE_RESTAMP for pcr-based pacing |
|---|
| 262 | * |
|---|
| 263 | * 58 5/28/09 2:41p erickson |
|---|
| 264 | * PR55461: use BXPT_HAS_PCR_PACING |
|---|
| 265 | * |
|---|
| 266 | * 57 5/28/09 11:31a erickson |
|---|
| 267 | * PR55461: add PCR-based pacing |
|---|
| 268 | * |
|---|
| 269 | * 56 5/19/09 3:02p vsilyaev |
|---|
| 270 | * PR 55299: Fixed PES PID mapping for the case of multiple audio tracks |
|---|
| 271 | * |
|---|
| 272 | * 55 5/15/09 12:48p vsilyaev |
|---|
| 273 | * PR 55193: Added function to return last parsed PTS by the media library |
|---|
| 274 | * |
|---|
| 275 | * 54 5/14/09 10:40a jtna |
|---|
| 276 | * PR54515: workaround for playpump_open() dependency on security module |
|---|
| 277 | * |
|---|
| 278 | * 53 4/20/09 10:53a erickson |
|---|
| 279 | * PR53662: rework XPT power management code to call BXPT_P_CanPowerDown |
|---|
| 280 | * before powering down core |
|---|
| 281 | * |
|---|
| 282 | * 52 4/17/09 2:35p katrep |
|---|
| 283 | * PR50207: Reverting back previous changes |
|---|
| 284 | * |
|---|
| 285 | * 50 1/26/09 11:03a vsilyaev |
|---|
| 286 | * PR 51579: Adding originalTransportType to the PlaypumpSettings |
|---|
| 287 | * |
|---|
| 288 | * 49 12/30/08 8:55a vsilyaev |
|---|
| 289 | * PR 50606: Added hooks for hardware support of MPEG1 system streams |
|---|
| 290 | * |
|---|
| 291 | * 48 12/21/08 6:01p nickh |
|---|
| 292 | * PR50605: Fix compile errors when running without Security |
|---|
| 293 | * |
|---|
| 294 | * 47 12/17/08 12:19a erickson |
|---|
| 295 | * PR50231: clean up failed NEXUS_Playpump_Open |
|---|
| 296 | * |
|---|
| 297 | * 46 12/10/08 7:36p vsilyaev |
|---|
| 298 | * PR 48908: Added control of power management |
|---|
| 299 | * |
|---|
| 300 | * 45 12/8/08 2:39p erickson |
|---|
| 301 | * PR49993: added NEXUS_TaskCallback_Destroy |
|---|
| 302 | * |
|---|
| 303 | * 44 12/4/08 3:29p vsilyaev |
|---|
| 304 | * PR 49993: Added code to inform application about errors detected during |
|---|
| 305 | * stream parsing |
|---|
| 306 | * |
|---|
| 307 | * 43 12/2/08 2:23p jgarrett |
|---|
| 308 | * PR 47993: Fixing substream ID mapping to allow proper substream ID's to |
|---|
| 309 | * be passed from the application |
|---|
| 310 | * |
|---|
| 311 | * 42 11/21/08 8:54a erickson |
|---|
| 312 | * PR49531: don't flush if not started |
|---|
| 313 | * |
|---|
| 314 | * 41 10/30/08 10:27p erickson |
|---|
| 315 | * PR47132: added NEXUS_PlaypumpSettings.blindSync |
|---|
| 316 | * |
|---|
| 317 | * 40 10/29/08 1:58p erickson |
|---|
| 318 | * PR47132: set BXPT_Playback_ParserConfig.ErrorInputIgnore and |
|---|
| 319 | * AcceptAdapt00 to true to allow raw data to pass through. no reason to |
|---|
| 320 | * exclude this data, like the current ContCountIgnore default. |
|---|
| 321 | * |
|---|
| 322 | * 39 10/27/08 11:20a erickson |
|---|
| 323 | * PR47232: added pacingTsRangeError to NEXUS_PlaypumpStatus |
|---|
| 324 | * |
|---|
| 325 | * 38 10/24/08 4:41p erickson |
|---|
| 326 | * PR47232: allow timebase to change on the fly |
|---|
| 327 | * |
|---|
| 328 | * 37 10/22/08 11:39a erickson |
|---|
| 329 | * PR48216: allow transport to run with no dma or security modules |
|---|
| 330 | * |
|---|
| 331 | * 36 10/17/08 3:01p katrep |
|---|
| 332 | * PR47951: Add index playpump status structure |
|---|
| 333 | * |
|---|
| 334 | * 35 10/13/08 9:41a erickson |
|---|
| 335 | * PR47232: set BXPT_Playback_ParserConfig.TsMode |
|---|
| 336 | * |
|---|
| 337 | * 34 10/9/08 5:49p erickson |
|---|
| 338 | * PR47232: more timestamp impl |
|---|
| 339 | * |
|---|
| 340 | * 33 10/9/08 10:06a erickson |
|---|
| 341 | * PR47232: set additional timebase setting for |
|---|
| 342 | * NEXUS_PlaypumpSettings.timestamp.timebase |
|---|
| 343 | * |
|---|
| 344 | * 32 10/7/08 11:31p erickson |
|---|
| 345 | * PR47232: extend NEXUS_PlaypumpSettings timestamp settings. reorganized |
|---|
| 346 | * into a nested structure. |
|---|
| 347 | * |
|---|
| 348 | * 31 10/6/08 1:59a erickson |
|---|
| 349 | * PR47232: added NEXUS_Playpump_SetPause for IP STB throttling |
|---|
| 350 | * |
|---|
| 351 | * 30 10/6/08 1:30a erickson |
|---|
| 352 | * PR47232: added NEXUS_PlaypumpSettings.pacingMaxError |
|---|
| 353 | * |
|---|
| 354 | * 29 9/22/08 10:03a erickson |
|---|
| 355 | * PR47145: fix warning |
|---|
| 356 | * |
|---|
| 357 | * 28 9/4/08 12:46p vishk |
|---|
| 358 | * PR 46315: Sample code for PID remapping |
|---|
| 359 | * |
|---|
| 360 | * 27 8/14/08 5:25p katrep |
|---|
| 361 | * PR45674: Fix compiiler warning in kernel mode non debug builds |
|---|
| 362 | * |
|---|
| 363 | * 26 7/29/08 3:07p erickson |
|---|
| 364 | * PR45199: added NEXUS_PlaypumpSettings.maxDataRate |
|---|
| 365 | * |
|---|
| 366 | * 25 7/28/08 3:33p erickson |
|---|
| 367 | * PR45124: fix misspellings |
|---|
| 368 | * |
|---|
| 369 | * 24 7/24/08 7:55a gmullen |
|---|
| 370 | * PR42365: Use MPEG blind sync mode for Directv playback. |
|---|
| 371 | * |
|---|
| 372 | * 23 6/25/08 5:50p vsilyaev |
|---|
| 373 | * PR 41869: Use keySlotHandle instead of keySlot[Number] |
|---|
| 374 | * |
|---|
| 375 | * 22 6/17/08 12:39p vsilyaev |
|---|
| 376 | * PR 42739: Fixed reference counter |
|---|
| 377 | * |
|---|
| 378 | * 21 6/17/08 11:26a vsilyaev |
|---|
| 379 | * PR 42739: Fixed NO PVR build |
|---|
| 380 | * |
|---|
| 381 | * 20 6/17/08 10:53a vsilyaev |
|---|
| 382 | * PR 42739: Added support for duplicate pids |
|---|
| 383 | * |
|---|
| 384 | * 19 6/13/08 6:43p erickson |
|---|
| 385 | * PR43087: fix warnings if NEXUS_NUM_PLAYPUMPS=0 |
|---|
| 386 | * |
|---|
| 387 | * 18 6/3/08 11:57a jgarrett |
|---|
| 388 | * PR 43279: Correcting size argument |
|---|
| 389 | * |
|---|
| 390 | * 17 5/28/08 7:45p jrubio |
|---|
| 391 | * PR43085: fix PLAYPUMP=0 compile |
|---|
| 392 | * |
|---|
| 393 | * 16 5/16/08 1:56p erickson |
|---|
| 394 | * PR42758: add NEXUS_TransportType_eVob support |
|---|
| 395 | * |
|---|
| 396 | * 15 5/14/08 1:25p vsilyaev |
|---|
| 397 | * PR 42119: Preserve PES->TS packetizer settings over |
|---|
| 398 | * Playpump_Stop/Playpump_Start calls. PR 41869: |
|---|
| 399 | * |
|---|
| 400 | * 14 5/9/08 11:34a erickson |
|---|
| 401 | * PR42119: preserve originalTransportType for media-framework streams |
|---|
| 402 | * |
|---|
| 403 | * 13 5/7/08 10:24p vsilyaev |
|---|
| 404 | * PR 41869: Added DMA into the playpump_crypto |
|---|
| 405 | * |
|---|
| 406 | * 12 5/7/08 2:00p vsilyaev |
|---|
| 407 | * PR 41869: Added core for re-packetize MPEG-2 TS data for encrypted PVR |
|---|
| 408 | * |
|---|
| 409 | * 11 5/5/08 1:34p vsilyaev |
|---|
| 410 | * PR 42355: Reset media playRate on stop |
|---|
| 411 | * |
|---|
| 412 | * 10 4/28/08 11:53a erickson |
|---|
| 413 | * PR42197: remove NEXUS_ParserBand_ePlayback enums |
|---|
| 414 | * |
|---|
| 415 | * 9 4/25/08 1:01p erickson |
|---|
| 416 | * PR41951: NEXUS_Playpump_Stop should call flush before stopping |
|---|
| 417 | * PVRlib_Feed_Stop |
|---|
| 418 | * |
|---|
| 419 | * 8 4/18/08 4:03p vsilyaev |
|---|
| 420 | * PR 41868: Added security API to playpump and recpump |
|---|
| 421 | * |
|---|
| 422 | * 7 4/17/08 9:31a erickson |
|---|
| 423 | * PR39994: remove param |
|---|
| 424 | * |
|---|
| 425 | * 6 4/10/08 2:40p erickson |
|---|
| 426 | * PR41557: enable ES packetization for all chips |
|---|
| 427 | * |
|---|
| 428 | * 5 4/9/08 1:09p jgarrett |
|---|
| 429 | * PR 41557: Fixing GetDefaultOpenPidChannelSettings |
|---|
| 430 | * |
|---|
| 431 | * 4 2/28/08 9:44p vsilyaev |
|---|
| 432 | * PR 40103: Used NEXUS_TaskCallback functions for API callbacks |
|---|
| 433 | * |
|---|
| 434 | * 3 2/26/08 10:53a erickson |
|---|
| 435 | * PR34925: default playRate |
|---|
| 436 | * |
|---|
| 437 | * 2 1/21/08 10:42a gmullen |
|---|
| 438 | * PR38854: Set BPVRlib channelNum to playpump instance. |
|---|
| 439 | * |
|---|
| 440 | * 1 1/18/08 2:20p jgarrett |
|---|
| 441 | * PR 38808: Merging to main branch |
|---|
| 442 | * |
|---|
| 443 | **************************************************************************/ |
|---|
| 444 | #include "nexus_transport_module.h" |
|---|
| 445 | #include "nexus_playpump_impl.h" |
|---|
| 446 | #include "bchp_int_id_xpt_pb0.h" |
|---|
| 447 | #include "bchp_int_id_xpt_pb1.h" |
|---|
| 448 | #if NEXUS_NUM_PLAYPUMPS > 2 |
|---|
| 449 | #include "bchp_int_id_xpt_pb2.h" |
|---|
| 450 | #endif |
|---|
| 451 | #if NEXUS_NUM_PLAYPUMPS > 3 |
|---|
| 452 | #include "bchp_int_id_xpt_pb3.h" |
|---|
| 453 | #endif |
|---|
| 454 | #if NEXUS_NUM_PLAYPUMPS > 4 |
|---|
| 455 | #include "bchp_int_id_xpt_pb4.h" |
|---|
| 456 | #endif |
|---|
| 457 | #if NEXUS_NUM_PLAYPUMPS > 5 |
|---|
| 458 | #include "bchp_int_id_xpt_pb5.h" |
|---|
| 459 | #endif |
|---|
| 460 | #if NEXUS_NUM_PLAYPUMPS > 6 |
|---|
| 461 | #include "bchp_int_id_xpt_pb6.h" |
|---|
| 462 | #endif |
|---|
| 463 | #if NEXUS_NUM_PLAYPUMPS > 7 |
|---|
| 464 | #include "bchp_int_id_xpt_pb7.h" |
|---|
| 465 | #endif |
|---|
| 466 | #if NEXUS_HAS_SECURITY |
|---|
| 467 | #include "nexus_security.h" |
|---|
| 468 | #endif |
|---|
| 469 | #include "priv/nexus_timebase_priv.h" |
|---|
| 470 | #include "nexus_class_verification.h" |
|---|
| 471 | |
|---|
| 472 | BDBG_MODULE(nexus_playpump); |
|---|
| 473 | |
|---|
| 474 | BDBG_OBJECT_ID(NEXUS_Playpump); |
|---|
| 475 | |
|---|
| 476 | #define NEXUS_P_PACKETIZER_BASE (0x100) |
|---|
| 477 | |
|---|
| 478 | static BERR_Code NEXUS_Playpump_P_SetParserBand(NEXUS_PlaypumpHandle p, const NEXUS_PlaypumpSettings *pSettings); |
|---|
| 479 | static void NEXUS_Playpump_P_InstallRangeErrIntHandler(NEXUS_PlaypumpHandle p); |
|---|
| 480 | static void NEXUS_Playpump_P_UninstallRangeErrIntHandler(NEXUS_PlaypumpHandle p); |
|---|
| 481 | static NEXUS_Error NEXUS_Playpump_P_SetInterrupts(NEXUS_PlaypumpHandle p, const NEXUS_PlaypumpSettings *pSettings); |
|---|
| 482 | |
|---|
| 483 | void NEXUS_Playpump_GetDefaultOpenSettings(NEXUS_PlaypumpOpenSettings *pSettings) |
|---|
| 484 | { |
|---|
| 485 | BKNI_Memset(pSettings, 0, sizeof(*pSettings)); |
|---|
| 486 | pSettings->streamMuxCompatible = false; |
|---|
| 487 | pSettings->fifoSize = B_PVR_PLAYBACK_BUFFER; |
|---|
| 488 | pSettings->alignment = 12; /* 2^12 = 4096 (I/O block size) alignment */ |
|---|
| 489 | pSettings->numDescriptors = NEXUS_NUM_PLAYBACK_DESC; |
|---|
| 490 | } |
|---|
| 491 | void |
|---|
| 492 | NEXUS_Playpump_GetDefaultSettings(NEXUS_PlaypumpSettings *pSettings) |
|---|
| 493 | { |
|---|
| 494 | BDBG_ASSERT(pSettings); |
|---|
| 495 | BKNI_Memset(pSettings, 0, sizeof(*pSettings)); |
|---|
| 496 | #if NEXUS_NUM_DMA_CHANNELS |
|---|
| 497 | pSettings->securityDmaDataFormat = NEXUS_DmaDataFormat_eMpeg; |
|---|
| 498 | #endif |
|---|
| 499 | pSettings->transportType = NEXUS_TransportType_eTs; |
|---|
| 500 | pSettings->originalTransportType = NEXUS_TransportType_eUnknown; |
|---|
| 501 | pSettings->timestamp.type = NEXUS_TransportTimestampType_eNone; |
|---|
| 502 | pSettings->timestamp.timebase = NEXUS_Timebase_eInvalid; |
|---|
| 503 | pSettings->timestamp.pacingMaxError = 1024; /* HW reset value */ |
|---|
| 504 | pSettings->timestamp.parityCheckDisable = false; /* HW reset value */ |
|---|
| 505 | pSettings->mode = NEXUS_PlaypumpMode_eFifo; |
|---|
| 506 | pSettings->playRate = NEXUS_NORMAL_PLAY_SPEED; |
|---|
| 507 | pSettings->allPass = false; |
|---|
| 508 | pSettings->acceptNullPackets = false; |
|---|
| 509 | pSettings->maxDataRate = 108000000; |
|---|
| 510 | NEXUS_CallbackDesc_Init(&pSettings->dataCallback); |
|---|
| 511 | NEXUS_CallbackDesc_Init(&pSettings->errorCallback); |
|---|
| 512 | return; |
|---|
| 513 | } |
|---|
| 514 | |
|---|
| 515 | NEXUS_PlaypumpHandle |
|---|
| 516 | NEXUS_Playpump_Open(unsigned index, const NEXUS_PlaypumpOpenSettings *pSettings) |
|---|
| 517 | { |
|---|
| 518 | #if NEXUS_NUM_PLAYPUMPS |
|---|
| 519 | NEXUS_PlaypumpHandle p; |
|---|
| 520 | BXPT_Playback_ChannelSettings play_cfg; |
|---|
| 521 | BERR_Code rc; |
|---|
| 522 | BPVRlib_Feed_Settings feed_cfg; |
|---|
| 523 | NEXUS_PlaypumpOpenSettings defaultSettings; |
|---|
| 524 | NEXUS_HeapHandle heap; |
|---|
| 525 | |
|---|
| 526 | if (!pSettings) { |
|---|
| 527 | NEXUS_Playpump_GetDefaultOpenSettings(&defaultSettings); |
|---|
| 528 | pSettings = &defaultSettings; |
|---|
| 529 | } |
|---|
| 530 | if (index == NEXUS_ANY_ID) { |
|---|
| 531 | unsigned i; |
|---|
| 532 | for (i=0;i<NEXUS_NUM_PLAYPUMPS;i++) { |
|---|
| 533 | if (!pTransport->playpump[i].playpump) { |
|---|
| 534 | index = i; |
|---|
| 535 | break; |
|---|
| 536 | } |
|---|
| 537 | } |
|---|
| 538 | if (i == NEXUS_NUM_PLAYPUMPS) { |
|---|
| 539 | rc = BERR_TRACE(NEXUS_NOT_AVAILABLE); |
|---|
| 540 | BDBG_ERR(("no playpump not available")); |
|---|
| 541 | return NULL; |
|---|
| 542 | } |
|---|
| 543 | } |
|---|
| 544 | |
|---|
| 545 | if (index >= NEXUS_NUM_PLAYPUMPS) { |
|---|
| 546 | rc = BERR_TRACE(BERR_INVALID_PARAMETER); |
|---|
| 547 | BDBG_ERR(("playpump[%d] not available", index)); |
|---|
| 548 | return NULL; |
|---|
| 549 | } |
|---|
| 550 | |
|---|
| 551 | if (pTransport->playpump[index].playpump) { |
|---|
| 552 | rc = BERR_TRACE(BERR_INVALID_PARAMETER); |
|---|
| 553 | BDBG_ERR(("playpump[%d] already open", index)); |
|---|
| 554 | return NULL; |
|---|
| 555 | } |
|---|
| 556 | pTransport->playpump[index].playpump = p = BKNI_Malloc(sizeof(*p)); |
|---|
| 557 | if (!p) { |
|---|
| 558 | rc = BERR_TRACE(BERR_OUT_OF_SYSTEM_MEMORY); |
|---|
| 559 | return NULL; |
|---|
| 560 | } |
|---|
| 561 | BKNI_Memset(p, 0, sizeof(*p)); |
|---|
| 562 | BDBG_OBJECT_SET(p, NEXUS_Playpump); |
|---|
| 563 | |
|---|
| 564 | p->index = index; |
|---|
| 565 | p->openSettings = *pSettings; |
|---|
| 566 | p->consumerStarted = false; |
|---|
| 567 | NEXUS_Playpump_GetDefaultSettings(&p->settings); |
|---|
| 568 | p->settings.transportType = NEXUS_TransportType_eTs; |
|---|
| 569 | p->settings.timestamp.type = NEXUS_TransportTimestampType_eNone; |
|---|
| 570 | p->settings.timestamp.pacing = false; |
|---|
| 571 | p->settings.playRate = NEXUS_NORMAL_PLAY_SPEED; |
|---|
| 572 | p->dataCallback = NEXUS_TaskCallback_Create(p, NULL); |
|---|
| 573 | if(!p->dataCallback) { |
|---|
| 574 | rc = BERR_TRACE(BERR_OUT_OF_SYSTEM_MEMORY); |
|---|
| 575 | goto error; |
|---|
| 576 | } |
|---|
| 577 | p->errorCallback = NEXUS_TaskCallback_Create(p, NULL); |
|---|
| 578 | if(!p->errorCallback) { |
|---|
| 579 | rc = BERR_TRACE(BERR_OUT_OF_SYSTEM_MEMORY); |
|---|
| 580 | goto error; |
|---|
| 581 | } |
|---|
| 582 | p->ccErrorCallback = NEXUS_IsrCallback_Create(p, NULL); |
|---|
| 583 | if(!p->ccErrorCallback) { |
|---|
| 584 | rc = BERR_TRACE(BERR_OUT_OF_SYSTEM_MEMORY); |
|---|
| 585 | goto error; |
|---|
| 586 | } |
|---|
| 587 | p->teiErrorCallback = NEXUS_IsrCallback_Create(p, NULL); |
|---|
| 588 | if(!p->teiErrorCallback) { |
|---|
| 589 | rc = BERR_TRACE(BERR_OUT_OF_SYSTEM_MEMORY); |
|---|
| 590 | goto error; |
|---|
| 591 | } |
|---|
| 592 | NEXUS_CallbackDesc_Init(&p->settings.dataCallback); |
|---|
| 593 | NEXUS_CallbackDesc_Init(&p->settings.errorCallback); |
|---|
| 594 | b_pid_map_init(&p->packetizer_map, NEXUS_P_PACKETIZER_BASE); |
|---|
| 595 | |
|---|
| 596 | BLST_S_INIT(&p->pid_list); |
|---|
| 597 | |
|---|
| 598 | p->item_mem = BKNI_Malloc(sizeof(*p->item_mem)*pSettings->numDescriptors); |
|---|
| 599 | if(p->item_mem==NULL) { |
|---|
| 600 | rc = BERR_TRACE(NEXUS_OUT_OF_SYSTEM_MEMORY); |
|---|
| 601 | goto error; |
|---|
| 602 | } |
|---|
| 603 | |
|---|
| 604 | heap = NEXUS_P_DefaultHeap(pSettings->heap); |
|---|
| 605 | if (!heap) { |
|---|
| 606 | heap = g_pCoreHandles->nexusHeap[pTransport->settings.mainHeapIndex]; |
|---|
| 607 | } |
|---|
| 608 | /* some playpump operations require driver CPU accessible to the playback fifo */ |
|---|
| 609 | if (!NEXUS_P_CpuAccessibleHeap(heap)) { |
|---|
| 610 | rc = BERR_TRACE(NEXUS_INVALID_PARAMETER); |
|---|
| 611 | goto error; |
|---|
| 612 | } |
|---|
| 613 | p->heap = NEXUS_Heap_GetMemHandle(heap); |
|---|
| 614 | |
|---|
| 615 | /* fifoSize == 0 is valid for scatter/gather-only mode */ |
|---|
| 616 | if (pSettings->fifoSize) { |
|---|
| 617 | p->buf_noncached = BMEM_AllocAligned(p->heap, pSettings->fifoSize, pSettings->alignment, 0); |
|---|
| 618 | if (!p->buf_noncached) { |
|---|
| 619 | rc = BERR_TRACE(NEXUS_OUT_OF_DEVICE_MEMORY); |
|---|
| 620 | goto error; |
|---|
| 621 | } |
|---|
| 622 | rc = BMEM_Heap_ConvertAddressToCached(p->heap, p->buf_noncached, &p->buf); /* map memory to the cached region */ |
|---|
| 623 | if (rc) {rc=BERR_TRACE(rc); goto error;} |
|---|
| 624 | } |
|---|
| 625 | BDBG_MSG(("alloc buffer %p %d", p->buf, pSettings->fifoSize)); |
|---|
| 626 | |
|---|
| 627 | heap = NEXUS_P_DefaultBoundsHeap(pSettings->boundsHeap); |
|---|
| 628 | if (heap) { |
|---|
| 629 | BMEM_HeapInfo heapInfo; |
|---|
| 630 | BMEM_Heap_Handle boundsHeap = NEXUS_Heap_GetMemHandle(heap); |
|---|
| 631 | BMEM_Heap_GetInfo(boundsHeap, &heapInfo); |
|---|
| 632 | p->boundsHeapSize = heapInfo.zSize; |
|---|
| 633 | rc = BMEM_Heap_ConvertAddressToCached(boundsHeap, heapInfo.pvAddress, &p->boundsHeapAddr); |
|---|
| 634 | if (rc) { |
|---|
| 635 | rc = BERR_TRACE(rc); |
|---|
| 636 | p->boundsHeapAddr = 0; |
|---|
| 637 | p->boundsHeapSize = 0; |
|---|
| 638 | } |
|---|
| 639 | } |
|---|
| 640 | |
|---|
| 641 | b_playpump_p_reset(p); |
|---|
| 642 | |
|---|
| 643 | rc = BXPT_Playback_GetChannelDefaultSettings(pTransport->xpt, index, &play_cfg); |
|---|
| 644 | if (rc) {rc=BERR_TRACE(rc);goto error;} |
|---|
| 645 | |
|---|
| 646 | #if NEXUS_HAS_LEGACY_XPT |
|---|
| 647 | play_cfg.AlwaysResumeFromLastDescriptor = true; |
|---|
| 648 | #endif |
|---|
| 649 | |
|---|
| 650 | rc = BXPT_Playback_OpenChannel(pTransport->xpt, &p->xpt_play, index, &play_cfg); |
|---|
| 651 | if (rc) {rc=BERR_TRACE(rc);goto error;} |
|---|
| 652 | |
|---|
| 653 | rc = NEXUS_Playpump_P_SetParserBand(p, &p->settings); |
|---|
| 654 | if(rc!=BERR_SUCCESS) { rc = BERR_TRACE(rc);goto error;} |
|---|
| 655 | |
|---|
| 656 | BPVRlib_Feed_GetDefaultSettings(&feed_cfg); |
|---|
| 657 | feed_cfg.xptHandle = pTransport->xpt; |
|---|
| 658 | feed_cfg.xptPlayHandle = p->xpt_play; |
|---|
| 659 | feed_cfg.heap = p->heap; |
|---|
| 660 | feed_cfg.intHandle = g_pCoreHandles->bint; |
|---|
| 661 | feed_cfg.numDesc = 32; |
|---|
| 662 | feed_cfg.applicationCnxt = p; |
|---|
| 663 | feed_cfg.useExtndedDesc = pSettings->streamMuxCompatible; |
|---|
| 664 | feed_cfg.descAvaliable_isr = NEXUS_P_Playpump_DescAvail_isr; |
|---|
| 665 | rc = BPVRlib_Feed_Open(&p->play_feed, &feed_cfg); |
|---|
| 666 | if(rc!=BERR_SUCCESS) { rc = BERR_TRACE(rc);goto error;} |
|---|
| 667 | |
|---|
| 668 | rc = BKNI_CreateEvent(&p->descEvent); |
|---|
| 669 | if(rc!=BERR_SUCCESS) { rc = BERR_TRACE(rc);goto error;} |
|---|
| 670 | |
|---|
| 671 | #if B_HAS_PLAYPUMP_IP |
|---|
| 672 | { |
|---|
| 673 | rc = b_playpump_ip_open(&p->ip, p, open_params); |
|---|
| 674 | if (rc) { rc = BERR_TRACE(rc);goto error; } |
|---|
| 675 | } |
|---|
| 676 | #endif |
|---|
| 677 | |
|---|
| 678 | /* init vob remap state */ |
|---|
| 679 | p->vob_remap_state.codec = NEXUS_AudioCodec_eMpeg; |
|---|
| 680 | p->vob_remap_state.track = 0; |
|---|
| 681 | |
|---|
| 682 | p->crypto = b_pump_crypto_create(p); |
|---|
| 683 | #if 0 /* if security module not connected, NULL is normal */ |
|---|
| 684 | if(!p->crypto) { |
|---|
| 685 | rc = BERR_TRACE(NEXUS_UNKNOWN); |
|---|
| 686 | goto error; |
|---|
| 687 | } |
|---|
| 688 | #endif |
|---|
| 689 | |
|---|
| 690 | #if B_HAS_MEDIA |
|---|
| 691 | p->use_media = false; |
|---|
| 692 | p->demux = b_pump_demux_create(p); |
|---|
| 693 | if(!p->demux) { |
|---|
| 694 | rc = BERR_TRACE(NEXUS_UNKNOWN); |
|---|
| 695 | goto error; |
|---|
| 696 | } |
|---|
| 697 | #endif |
|---|
| 698 | |
|---|
| 699 | return p; |
|---|
| 700 | error: |
|---|
| 701 | if (p) { |
|---|
| 702 | if (p->crypto) { |
|---|
| 703 | b_pump_crypto_destroy(p->crypto); |
|---|
| 704 | } |
|---|
| 705 | if (p->play_feed) { |
|---|
| 706 | BPVRlib_Feed_Close(p->play_feed); |
|---|
| 707 | } |
|---|
| 708 | if (p->descEvent) { |
|---|
| 709 | BKNI_DestroyEvent(p->descEvent); |
|---|
| 710 | } |
|---|
| 711 | if (p->xpt_play) { |
|---|
| 712 | BXPT_Playback_CloseChannel(p->xpt_play); |
|---|
| 713 | } |
|---|
| 714 | if (p->buf_noncached) { |
|---|
| 715 | BMEM_Free(p->heap, p->buf_noncached); |
|---|
| 716 | } |
|---|
| 717 | if(p->item_mem) { |
|---|
| 718 | BKNI_Free(p->item_mem); |
|---|
| 719 | } |
|---|
| 720 | if(p->errorCallback) { |
|---|
| 721 | NEXUS_TaskCallback_Destroy(p->errorCallback); |
|---|
| 722 | } |
|---|
| 723 | if(p->ccErrorCallback) { |
|---|
| 724 | NEXUS_IsrCallback_Destroy(p->ccErrorCallback); |
|---|
| 725 | } |
|---|
| 726 | if(p->teiErrorCallback) { |
|---|
| 727 | NEXUS_IsrCallback_Destroy(p->teiErrorCallback); |
|---|
| 728 | } |
|---|
| 729 | if(p->dataCallback) { |
|---|
| 730 | NEXUS_TaskCallback_Destroy(p->dataCallback); |
|---|
| 731 | } |
|---|
| 732 | BKNI_Free(p); |
|---|
| 733 | pTransport->playpump[index].playpump = NULL; |
|---|
| 734 | } |
|---|
| 735 | #else |
|---|
| 736 | BSTD_UNUSED(index); |
|---|
| 737 | BSTD_UNUSED(pSettings); |
|---|
| 738 | #endif |
|---|
| 739 | return NULL; |
|---|
| 740 | } |
|---|
| 741 | |
|---|
| 742 | void NEXUS_Playpump_Close(NEXUS_PlaypumpHandle p) |
|---|
| 743 | { |
|---|
| 744 | BDBG_OBJECT_ASSERT(p, NEXUS_Playpump); |
|---|
| 745 | if (p->state.running) { |
|---|
| 746 | NEXUS_Playpump_Stop(p); |
|---|
| 747 | } |
|---|
| 748 | #if B_HAS_PLAYPUMP_IP |
|---|
| 749 | b_playpump_ip_close(&p->ip); |
|---|
| 750 | #endif |
|---|
| 751 | if (p->crypto) { |
|---|
| 752 | b_pump_crypto_destroy(p->crypto); |
|---|
| 753 | } |
|---|
| 754 | #if B_HAS_MEDIA |
|---|
| 755 | b_pump_demux_destroy(p->demux); |
|---|
| 756 | #endif |
|---|
| 757 | p->state.packetizer = b_play_packetizer_none; |
|---|
| 758 | |
|---|
| 759 | /* force the destroying of the xpt interrupt */ |
|---|
| 760 | p->settings.ccError.callback = NULL; |
|---|
| 761 | p->settings.teiError.callback = NULL; |
|---|
| 762 | NEXUS_Playpump_P_SetInterrupts(p, &p->settings); |
|---|
| 763 | |
|---|
| 764 | BPVRlib_Feed_Close(p->play_feed); |
|---|
| 765 | BKNI_DestroyEvent(p->descEvent); |
|---|
| 766 | BXPT_Playback_CloseChannel(p->xpt_play); |
|---|
| 767 | if (p->buf_noncached) { |
|---|
| 768 | BMEM_Free(p->heap, p->buf_noncached); |
|---|
| 769 | } |
|---|
| 770 | BKNI_Free(p->item_mem); |
|---|
| 771 | p->xpt_play = NULL; |
|---|
| 772 | p->play_feed = NULL; |
|---|
| 773 | #if NEXUS_NUM_PLAYPUMPS |
|---|
| 774 | pTransport->playpump[p->index].playpump = NULL; |
|---|
| 775 | #endif |
|---|
| 776 | NEXUS_IsrCallback_Destroy(p->ccErrorCallback); |
|---|
| 777 | NEXUS_IsrCallback_Destroy(p->teiErrorCallback); |
|---|
| 778 | NEXUS_TaskCallback_Destroy(p->errorCallback); |
|---|
| 779 | NEXUS_TaskCallback_Destroy(p->dataCallback); |
|---|
| 780 | BDBG_OBJECT_DESTROY(p, NEXUS_Playpump); |
|---|
| 781 | BKNI_Free(p); |
|---|
| 782 | } |
|---|
| 783 | |
|---|
| 784 | void NEXUS_Playpump_GetSettings(NEXUS_PlaypumpHandle p, NEXUS_PlaypumpSettings *pSettings) |
|---|
| 785 | { |
|---|
| 786 | BDBG_OBJECT_ASSERT(p, NEXUS_Playpump); |
|---|
| 787 | BDBG_ASSERT(pSettings); |
|---|
| 788 | *pSettings = p->settings; |
|---|
| 789 | return; |
|---|
| 790 | } |
|---|
| 791 | |
|---|
| 792 | static BERR_Code |
|---|
| 793 | NEXUS_Playpump_P_SetParserBand(NEXUS_PlaypumpHandle p, const NEXUS_PlaypumpSettings *pSettings) |
|---|
| 794 | { |
|---|
| 795 | BXPT_Playback_ParserConfig parserConfig; |
|---|
| 796 | BERR_Code rc; |
|---|
| 797 | |
|---|
| 798 | BDBG_OBJECT_ASSERT(p, NEXUS_Playpump); |
|---|
| 799 | BDBG_ASSERT(p->xpt_play); |
|---|
| 800 | |
|---|
| 801 | #if B_HAS_DSS |
|---|
| 802 | rc = BXPT_DirecTvPlayback_SetParserBandMode( p->xpt_play, NEXUS_IS_DSS_MODE(pSettings->transportType)? |
|---|
| 803 | BXPT_ParserMode_eDirecTv : BXPT_ParserMode_eMpeg); /* XXX this shall precced SetParserConfig, since it resets parser configuration */ |
|---|
| 804 | if (rc) return BERR_TRACE(rc); |
|---|
| 805 | #endif |
|---|
| 806 | |
|---|
| 807 | rc = BXPT_Playback_GetParserConfig(p->xpt_play, &parserConfig); |
|---|
| 808 | if (rc) return BERR_TRACE(rc); |
|---|
| 809 | /* for playback, we should just let all data through. if the stream is good, there's no harm. |
|---|
| 810 | if the stream is bad, the decoders must handle this anyway. */ |
|---|
| 811 | #if NEXUS_PARSER_BAND_CC_CHECK |
|---|
| 812 | parserConfig.ContCountIgnore = !pSettings->continuityCountEnabled; |
|---|
| 813 | #else |
|---|
| 814 | if(pSettings->continuityCountEnabled != p->settings.continuityCountEnabled && BLST_S_FIRST(&p->pid_list)!=NULL) { |
|---|
| 815 | BDBG_WRN(("%#lx:continuityCountEnabled wouldn't get applied to aleady opened pids", (unsigned long)p)); |
|---|
| 816 | } |
|---|
| 817 | #endif |
|---|
| 818 | parserConfig.ErrorInputIgnore = (pSettings->teiError.callback == NULL); /* if we want these errors, then transport cannot ignore */ |
|---|
| 819 | parserConfig.AcceptAdapt00 = true; |
|---|
| 820 | parserConfig.AllPass = pSettings->allPass; |
|---|
| 821 | parserConfig.AcceptNulls = pSettings->acceptNullPackets; |
|---|
| 822 | |
|---|
| 823 | #if BXPT_HAS_PCR_PACING |
|---|
| 824 | /* enable PARSER_FORCE_RESTAMP in pcr-pacing mode */ |
|---|
| 825 | parserConfig.ForceRestamping = (pSettings->timestamp.pacing && pSettings->timestamp.pcrPacingPid); |
|---|
| 826 | #endif |
|---|
| 827 | if (pSettings->timestamp.forceRestamping==true) { |
|---|
| 828 | parserConfig.ForceRestamping = true; |
|---|
| 829 | } |
|---|
| 830 | |
|---|
| 831 | parserConfig.UsePcrTimeBase = true; /* eInvalid now means get the default timebase and track it */ |
|---|
| 832 | if (parserConfig.UsePcrTimeBase) { |
|---|
| 833 | NEXUS_TimebaseHandle timebase = NEXUS_Timebase_Resolve_priv(pSettings->timestamp.timebase); |
|---|
| 834 | if (timebase) |
|---|
| 835 | { |
|---|
| 836 | parserConfig.WhichPcrToUse = timebase->hwIndex; |
|---|
| 837 | } |
|---|
| 838 | else |
|---|
| 839 | { |
|---|
| 840 | return BERR_TRACE(NEXUS_INVALID_PARAMETER); |
|---|
| 841 | } |
|---|
| 842 | } |
|---|
| 843 | rc = BXPT_Playback_SetParserConfig(p->xpt_play, &parserConfig); |
|---|
| 844 | if (rc) return BERR_TRACE(rc); |
|---|
| 845 | |
|---|
| 846 | rc = BXPT_Playback_SetBitRate(p->xpt_play, pSettings->maxDataRate); |
|---|
| 847 | if (rc) return BERR_TRACE(rc); |
|---|
| 848 | |
|---|
| 849 | return 0; |
|---|
| 850 | } |
|---|
| 851 | |
|---|
| 852 | |
|---|
| 853 | NEXUS_Error |
|---|
| 854 | NEXUS_Playpump_SetSettings(NEXUS_PlaypumpHandle p, const NEXUS_PlaypumpSettings *pSettings) |
|---|
| 855 | { |
|---|
| 856 | NEXUS_Error rc; |
|---|
| 857 | |
|---|
| 858 | BDBG_OBJECT_ASSERT(p, NEXUS_Playpump); |
|---|
| 859 | BDBG_ASSERT(pSettings); |
|---|
| 860 | |
|---|
| 861 | if (pSettings->playRate == 0) { |
|---|
| 862 | /* playRate == 0 is not pause. It must be non-zero. */ |
|---|
| 863 | return BERR_TRACE(NEXUS_INVALID_PARAMETER); |
|---|
| 864 | } |
|---|
| 865 | |
|---|
| 866 | if(p->state.running && ( |
|---|
| 867 | p->settings.transportType != pSettings->transportType || |
|---|
| 868 | p->settings.timestamp.type != pSettings->timestamp.type || |
|---|
| 869 | p->settings.timestamp.pacing != pSettings->timestamp.pacing || |
|---|
| 870 | #if NEXUS_NUM_DMA_CHANNELS |
|---|
| 871 | p->settings.securityDma != pSettings->securityDma || |
|---|
| 872 | #endif |
|---|
| 873 | #if NEXUS_HAS_SECURITY |
|---|
| 874 | p->settings.securityContext != pSettings->securityContext || |
|---|
| 875 | #endif |
|---|
| 876 | p->settings.mode != pSettings->mode |
|---|
| 877 | )) { |
|---|
| 878 | BDBG_WRN(("NEXUS_Playpump_SetSettings: %lx can't change settings when started", (unsigned long)p)); |
|---|
| 879 | rc = BERR_TRACE(BERR_NOT_SUPPORTED); |
|---|
| 880 | goto err_running; |
|---|
| 881 | } |
|---|
| 882 | |
|---|
| 883 | #if NEXUS_NUM_DMA_CHANNELS |
|---|
| 884 | if (pSettings->securityDma && !pTransport->settings.dma) { |
|---|
| 885 | BDBG_ERR(("Transport module does not have dma module handle.")); |
|---|
| 886 | return BERR_TRACE(BERR_NOT_SUPPORTED); |
|---|
| 887 | } |
|---|
| 888 | #endif |
|---|
| 889 | #if NEXUS_HAS_SECURITY |
|---|
| 890 | if (pSettings->securityContext && !pTransport->settings.security) { |
|---|
| 891 | BDBG_ERR(("Transport module does not have security module handle.")); |
|---|
| 892 | return BERR_TRACE(BERR_NOT_SUPPORTED); |
|---|
| 893 | } |
|---|
| 894 | #endif |
|---|
| 895 | |
|---|
| 896 | if (pSettings->timestamp.pacingMaxError != p->settings.timestamp.pacingMaxError) { |
|---|
| 897 | rc = BXPT_Playback_SetPacingErrorBound(p->xpt_play, pSettings->timestamp.pacingMaxError); |
|---|
| 898 | if (rc) return BERR_TRACE(rc); |
|---|
| 899 | } |
|---|
| 900 | |
|---|
| 901 | if (pSettings->timestamp.timebase != p->settings.timestamp.timebase) { |
|---|
| 902 | BXPT_Playback_ChannelSettings cfg; |
|---|
| 903 | |
|---|
| 904 | rc = BXPT_Playback_GetChannelSettings(p->xpt_play, &cfg); |
|---|
| 905 | if (rc) return BERR_TRACE(rc); |
|---|
| 906 | |
|---|
| 907 | cfg.UsePcrTimeBase = true; /* eInvalid now means get the default timebase and track it */ |
|---|
| 908 | if (cfg.UsePcrTimeBase) { |
|---|
| 909 | NEXUS_TimebaseHandle timebase = NEXUS_Timebase_Resolve_priv(pSettings->timestamp.timebase); |
|---|
| 910 | if (timebase) |
|---|
| 911 | { |
|---|
| 912 | cfg.WhichPcrToUse = timebase->hwIndex; |
|---|
| 913 | } |
|---|
| 914 | else |
|---|
| 915 | { |
|---|
| 916 | return BERR_TRACE(NEXUS_INVALID_PARAMETER); |
|---|
| 917 | } |
|---|
| 918 | } |
|---|
| 919 | |
|---|
| 920 | rc = BXPT_Playback_SetChannelSettings(p->xpt_play, &cfg); |
|---|
| 921 | if (rc) return BERR_TRACE(rc); |
|---|
| 922 | } |
|---|
| 923 | |
|---|
| 924 | if(pSettings->transportType != p->settings.transportType) { |
|---|
| 925 | if(BLST_S_FIRST(&p->pid_list)!=NULL) { |
|---|
| 926 | BDBG_WRN(("NEXUS_Playpump_SetSettings: %lx can't change settings when PIDs are attached", (unsigned long)p)); |
|---|
| 927 | rc = BERR_TRACE(BERR_NOT_SUPPORTED); |
|---|
| 928 | goto err_attached; |
|---|
| 929 | } |
|---|
| 930 | #if B_HAS_MEDIA |
|---|
| 931 | rc = b_pump_demux_set_stream_type(p->demux, pSettings->transportType, &p->use_media); |
|---|
| 932 | if(rc!=NEXUS_SUCCESS) { rc=BERR_TRACE(rc); goto err_media;} |
|---|
| 933 | BDBG_MSG(("NEXUS_Playpump_SetSettings: %s of stream type %u", p->use_media?"media preprocessing":"native processsing", pSettings->transportType)); |
|---|
| 934 | |
|---|
| 935 | if(!p->use_media) { |
|---|
| 936 | bool supported; |
|---|
| 937 | |
|---|
| 938 | if (p->crypto) { |
|---|
| 939 | rc = b_pump_crypto_set_stream_type(p->crypto, pSettings->transportType, &supported); |
|---|
| 940 | if(rc!=NEXUS_SUCCESS) { rc=BERR_TRACE(rc); goto err_crypto;} |
|---|
| 941 | } |
|---|
| 942 | } |
|---|
| 943 | #endif |
|---|
| 944 | } |
|---|
| 945 | |
|---|
| 946 | rc = NEXUS_Playpump_P_SetParserBand(p, pSettings); |
|---|
| 947 | if(rc!=BERR_SUCCESS) { rc = BERR_TRACE(rc);goto err_parser_band;} |
|---|
| 948 | |
|---|
| 949 | #if B_HAS_MEDIA |
|---|
| 950 | if(p->settings.playRate != pSettings->playRate) { |
|---|
| 951 | if (p->state.packetizer==b_play_packetizer_media) { |
|---|
| 952 | b_pump_demux_set_rate(p->demux, pSettings->playRate); |
|---|
| 953 | } |
|---|
| 954 | } |
|---|
| 955 | #endif |
|---|
| 956 | p->settings = *pSettings; |
|---|
| 957 | NEXUS_TaskCallback_Set(p->dataCallback, &p->settings.dataCallback); |
|---|
| 958 | NEXUS_TaskCallback_Set(p->errorCallback, &p->settings.errorCallback); |
|---|
| 959 | NEXUS_Playpump_P_SetInterrupts(p, &p->settings); |
|---|
| 960 | |
|---|
| 961 | #if B_HAS_MEDIA |
|---|
| 962 | err_crypto: |
|---|
| 963 | err_media: |
|---|
| 964 | #endif |
|---|
| 965 | err_parser_band: |
|---|
| 966 | err_running: |
|---|
| 967 | err_attached: |
|---|
| 968 | return rc; |
|---|
| 969 | } |
|---|
| 970 | |
|---|
| 971 | static NEXUS_Error NEXUS_Playpump_P_StartPid(NEXUS_PlaypumpHandle p, NEXUS_P_PlaypumpPidChannel *play_pid) |
|---|
| 972 | { |
|---|
| 973 | NEXUS_Error rc; |
|---|
| 974 | |
|---|
| 975 | #if NEXUS_HAS_SECURITY && (NEXUS_NUM_DMA_CHANNELS==0) |
|---|
| 976 | if (p->settings.securityContext) { |
|---|
| 977 | rc = NEXUS_Security_AddPidChannelToKeySlot(p->settings.securityContext, play_pid->pid_channel->status.pidChannelIndex); |
|---|
| 978 | if (rc) return BERR_TRACE(rc); |
|---|
| 979 | } |
|---|
| 980 | #endif |
|---|
| 981 | |
|---|
| 982 | /* activate packetizer to all pids that needs packetizer */ |
|---|
| 983 | if(play_pid->packetizer.enable) { |
|---|
| 984 | rc = BXPT_Playback_PacketizeStream(p->xpt_play, play_pid->packetizer.context, &play_pid->packetizer.cfg, true); |
|---|
| 985 | if (rc) return BERR_TRACE(rc); |
|---|
| 986 | play_pid->packetizer.active = true; |
|---|
| 987 | } |
|---|
| 988 | |
|---|
| 989 | return 0; |
|---|
| 990 | } |
|---|
| 991 | |
|---|
| 992 | static void NEXUS_Playpump_P_StopPid(NEXUS_PlaypumpHandle p, NEXUS_P_PlaypumpPidChannel *play_pid) |
|---|
| 993 | { |
|---|
| 994 | NEXUS_Error rc; |
|---|
| 995 | |
|---|
| 996 | #if NEXUS_HAS_SECURITY && (NEXUS_NUM_DMA_CHANNELS==0) |
|---|
| 997 | if (p->settings.securityContext) { |
|---|
| 998 | (void)NEXUS_Security_RemovePidChannelFromKeySlot(p->settings.securityContext, play_pid->pid_channel->status.pidChannelIndex); |
|---|
| 999 | } |
|---|
| 1000 | #endif |
|---|
| 1001 | |
|---|
| 1002 | if(play_pid->packetizer.enable) { |
|---|
| 1003 | rc = BXPT_Playback_PacketizeStream(p->xpt_play, play_pid->packetizer.context, &play_pid->packetizer.cfg, false); |
|---|
| 1004 | if (rc!=BERR_SUCCESS) { rc = BERR_TRACE(rc); } |
|---|
| 1005 | play_pid->packetizer.active = false; |
|---|
| 1006 | } |
|---|
| 1007 | } |
|---|
| 1008 | |
|---|
| 1009 | static NEXUS_Error NEXUS_Playpump_Start_priv(NEXUS_PlaypumpHandle p, bool muxInput) |
|---|
| 1010 | { |
|---|
| 1011 | BERR_Code rc; |
|---|
| 1012 | BXPT_Playback_ChannelSettings cfg; |
|---|
| 1013 | NEXUS_TransportType transportType; |
|---|
| 1014 | NEXUS_P_PlaypumpPidChannel *play_pid; |
|---|
| 1015 | |
|---|
| 1016 | BDBG_OBJECT_ASSERT(p, NEXUS_Playpump); |
|---|
| 1017 | |
|---|
| 1018 | if(NEXUS_GetEnv("profile_playpump")) { |
|---|
| 1019 | NEXUS_Profile_Start(); |
|---|
| 1020 | } |
|---|
| 1021 | |
|---|
| 1022 | if (p->state.running) { rc = BERR_TRACE(NEXUS_NOT_SUPPORTED); goto err_state; } |
|---|
| 1023 | |
|---|
| 1024 | /* If we're in allPass, verify that there is one, and only one, PID channel on the playback. Check that the PID |
|---|
| 1025 | channel used is correct too. */ |
|---|
| 1026 | if (p->settings.allPass) |
|---|
| 1027 | { |
|---|
| 1028 | unsigned AllPassPidChannel; |
|---|
| 1029 | NEXUS_P_PlaypumpPidChannel *play_pid; |
|---|
| 1030 | |
|---|
| 1031 | unsigned ChannelCount = 0; |
|---|
| 1032 | bool FoundValidChannel = false; |
|---|
| 1033 | |
|---|
| 1034 | NEXUS_Playpump_GetAllPassPidChannelIndex( p, &AllPassPidChannel ); |
|---|
| 1035 | for(play_pid=BLST_S_FIRST(&p->pid_list); play_pid; play_pid=BLST_S_NEXT(play_pid, link)) |
|---|
| 1036 | { |
|---|
| 1037 | ChannelCount++; |
|---|
| 1038 | if(play_pid->pid_channel->status.pidChannelIndex == AllPassPidChannel) |
|---|
| 1039 | { |
|---|
| 1040 | FoundValidChannel = true; |
|---|
| 1041 | } |
|---|
| 1042 | } |
|---|
| 1043 | |
|---|
| 1044 | if( !ChannelCount || 1 < ChannelCount ) |
|---|
| 1045 | { |
|---|
| 1046 | BDBG_ERR(( "Only 1 PID channel is supported in allPass mode." )); |
|---|
| 1047 | rc = BERR_TRACE(NEXUS_INVALID_PARAMETER); |
|---|
| 1048 | goto error; |
|---|
| 1049 | } |
|---|
| 1050 | |
|---|
| 1051 | if( !FoundValidChannel ) |
|---|
| 1052 | { |
|---|
| 1053 | BDBG_ERR(( "Incorrect PID channel used for allPass. See NEXUS_Playpump_GetAllPassPidChannelIndex()." )); |
|---|
| 1054 | rc = BERR_TRACE(NEXUS_INVALID_PARAMETER); |
|---|
| 1055 | goto error; |
|---|
| 1056 | } |
|---|
| 1057 | } |
|---|
| 1058 | |
|---|
| 1059 | BKNI_Memset(&p->state, 0, sizeof(p->state)); /* wipe-out all temporary state */ |
|---|
| 1060 | BKNI_Memset(&cfg, 0, sizeof(cfg)); |
|---|
| 1061 | |
|---|
| 1062 | NEXUS_Transport_P_IncPowerDown(true); |
|---|
| 1063 | |
|---|
| 1064 | rc = NEXUS_Playpump_P_SetParserBand(p, &p->settings); |
|---|
| 1065 | if(rc!=BERR_SUCCESS) { rc = BERR_TRACE(rc);goto err_parser_band;} |
|---|
| 1066 | |
|---|
| 1067 | transportType = p->settings.transportType; |
|---|
| 1068 | #if B_HAS_MEDIA |
|---|
| 1069 | p->state.packetizer = p->use_media ? b_play_packetizer_media:b_play_packetizer_none; |
|---|
| 1070 | if (p->state.packetizer==b_play_packetizer_media) { |
|---|
| 1071 | transportType = NEXUS_TransportType_eMpeg2Pes; |
|---|
| 1072 | } else |
|---|
| 1073 | #endif |
|---|
| 1074 | #if NEXUS_NUM_DMA_CHANNELS |
|---|
| 1075 | if (p->settings.securityDma && p->crypto) { |
|---|
| 1076 | p->state.packetizer = b_play_packetizer_crypto; |
|---|
| 1077 | } |
|---|
| 1078 | #endif |
|---|
| 1079 | |
|---|
| 1080 | rc = BXPT_Playback_GetChannelSettings(p->xpt_play, &cfg); |
|---|
| 1081 | if (rc) {rc=BERR_TRACE(rc); goto error;} |
|---|
| 1082 | |
|---|
| 1083 | #if NEXUS_HAS_LEGACY_XPT |
|---|
| 1084 | cfg.AlwaysResumeFromLastDescriptor = true; |
|---|
| 1085 | #endif |
|---|
| 1086 | #if B_HAS_NATIVE_MPEG1 |
|---|
| 1087 | /* initialize to the MPEG2 Program Stream Mode */ |
|---|
| 1088 | cfg.PsMode = BXPT_Playback_PS_Mode_MPEG2; |
|---|
| 1089 | cfg.PackHdrConfig = BXPT_Playback_PackHdr_Drop; |
|---|
| 1090 | #endif |
|---|
| 1091 | |
|---|
| 1092 | #if B_PACKETIZE_HSX |
|---|
| 1093 | if (!(transportType == NEXUS_TransportType_eTs || NEXUS_IS_DSS_MODE(transportType))) { |
|---|
| 1094 | cfg.SyncMode = BXPT_PB_SYNC_MPEG_BLIND; /* TS Blind */ |
|---|
| 1095 | cfg.PacketLength = 184; |
|---|
| 1096 | } else |
|---|
| 1097 | #endif |
|---|
| 1098 | switch(transportType) { |
|---|
| 1099 | case NEXUS_TransportType_eEs: |
|---|
| 1100 | cfg.SyncMode = BXPT_PB_SYNC_MPEG_BLIND; /* TS Blind */ |
|---|
| 1101 | cfg.PacketLength = 184; |
|---|
| 1102 | break; |
|---|
| 1103 | #if B_HAS_NATIVE_MPEG1 |
|---|
| 1104 | case NEXUS_TransportType_eMpeg1Ps: |
|---|
| 1105 | cfg.PsMode = BXPT_Playback_PS_Mode_MPEG1; |
|---|
| 1106 | cfg.PackHdrConfig = BXPT_Playback_PackHdr_Drop; |
|---|
| 1107 | /* fallthrough */ |
|---|
| 1108 | #endif |
|---|
| 1109 | case NEXUS_TransportType_eVob: |
|---|
| 1110 | #if !BXPT_HAS_PID_CHANNEL_PES_FILTERING |
|---|
| 1111 | cfg.PackHdrConfig = BXPT_Playback_PackHdr_Payload_Insert; |
|---|
| 1112 | cfg.PacketLength = 0x80; |
|---|
| 1113 | cfg.SyncMode = BXPT_PB_SYNC_MPEG_BLIND; |
|---|
| 1114 | break; |
|---|
| 1115 | #endif |
|---|
| 1116 | /* fall through */ |
|---|
| 1117 | |
|---|
| 1118 | case NEXUS_TransportType_eMpeg2Pes: |
|---|
| 1119 | cfg.SyncMode = BXPT_PB_SYNC_PES; /* TS PES */ |
|---|
| 1120 | break; |
|---|
| 1121 | |
|---|
| 1122 | case NEXUS_TransportType_eTs: |
|---|
| 1123 | cfg.PacketLength = 188; |
|---|
| 1124 | cfg.SyncMode = BXPT_PB_SYNC_MPEG; /* TS mode. This allows HW to search for the 0x47 sync byte. */ |
|---|
| 1125 | break; |
|---|
| 1126 | #if B_HAS_DSS |
|---|
| 1127 | case NEXUS_TransportType_eDssPes: |
|---|
| 1128 | case NEXUS_TransportType_eDssEs: |
|---|
| 1129 | cfg.PacketLength = 130; |
|---|
| 1130 | cfg.SyncMode = BXPT_PB_SYNC_MPEG_BLIND; /* direct TV mode. Use MPEG blind-sync, per DVT's suggestion. PR 42365 */ |
|---|
| 1131 | break; |
|---|
| 1132 | #endif |
|---|
| 1133 | default: |
|---|
| 1134 | rc = BERR_TRACE(NEXUS_UNKNOWN); |
|---|
| 1135 | goto error; |
|---|
| 1136 | } |
|---|
| 1137 | |
|---|
| 1138 | if (p->settings.blindSync) { |
|---|
| 1139 | cfg.SyncMode = BXPT_PB_SYNC_MPEG_BLIND; |
|---|
| 1140 | } |
|---|
| 1141 | |
|---|
| 1142 | switch (p->settings.timestamp.type) { |
|---|
| 1143 | case NEXUS_TransportTimestampType_eNone: |
|---|
| 1144 | cfg.TimestampEn = false; |
|---|
| 1145 | break; |
|---|
| 1146 | case NEXUS_TransportTimestampType_e30_2U_Mod300: |
|---|
| 1147 | cfg.TimestampMode = BXPT_TimestampMode_e30_2U_Mod300; |
|---|
| 1148 | cfg.TimestampEn = true; |
|---|
| 1149 | #if BXPT_HAS_32BIT_PB_TIMESTAMPS |
|---|
| 1150 | cfg.Use32BitTimestamps = false; |
|---|
| 1151 | #endif |
|---|
| 1152 | break; |
|---|
| 1153 | case NEXUS_TransportTimestampType_e30_2U_Binary: |
|---|
| 1154 | cfg.TimestampMode = BXPT_TimestampMode_e30_2U_Binary; |
|---|
| 1155 | cfg.TimestampEn = true; |
|---|
| 1156 | #if BXPT_HAS_32BIT_PB_TIMESTAMPS |
|---|
| 1157 | cfg.Use32BitTimestamps = false; |
|---|
| 1158 | #endif |
|---|
| 1159 | break; |
|---|
| 1160 | #if BXPT_HAS_32BIT_PB_TIMESTAMPS |
|---|
| 1161 | case NEXUS_TransportTimestampType_e32_Mod300: |
|---|
| 1162 | cfg.TimestampMode = BXPT_TimestampMode_e30_2U_Mod300; |
|---|
| 1163 | cfg.TimestampEn = true; |
|---|
| 1164 | cfg.Use32BitTimestamps = true; |
|---|
| 1165 | break; |
|---|
| 1166 | case NEXUS_TransportTimestampType_e32_Binary: |
|---|
| 1167 | cfg.TimestampMode = BXPT_TimestampMode_e30_2U_Binary; |
|---|
| 1168 | cfg.TimestampEn = true; |
|---|
| 1169 | cfg.Use32BitTimestamps = true; |
|---|
| 1170 | /* TODO: enable this when needed |
|---|
| 1171 | case NEXUS_TransportTimestampType_e28_4P_Mod300: |
|---|
| 1172 | rec_cfg.TimestampMode = BXPT_TimestampMode_e28_4P_Mod300; |
|---|
| 1173 | rec_cfg.TimestampEn = true; |
|---|
| 1174 | rec_cfg.Use32BitTimestamps = true; |
|---|
| 1175 | break; |
|---|
| 1176 | */ |
|---|
| 1177 | break; |
|---|
| 1178 | #endif |
|---|
| 1179 | default: |
|---|
| 1180 | rc = BERR_TRACE(NEXUS_NOT_SUPPORTED); |
|---|
| 1181 | goto error; |
|---|
| 1182 | } |
|---|
| 1183 | |
|---|
| 1184 | if (p->settings.timestamp.pcrPacingPid && p->settings.timestamp.pacing) { |
|---|
| 1185 | #if BXPT_HAS_PCR_PACING |
|---|
| 1186 | cfg.PcrPacingPid = p->settings.timestamp.pcrPacingPid; |
|---|
| 1187 | cfg.PcrBasedPacing = true; |
|---|
| 1188 | #else |
|---|
| 1189 | rc = BERR_TRACE(NEXUS_NOT_SUPPORTED); |
|---|
| 1190 | goto error; |
|---|
| 1191 | #endif |
|---|
| 1192 | } |
|---|
| 1193 | |
|---|
| 1194 | cfg.ResetPacing = p->settings.timestamp.resetPacing; |
|---|
| 1195 | cfg.DisableTimestampParityCheck = p->settings.timestamp.parityCheckDisable; |
|---|
| 1196 | cfg.UsePcrTimeBase = true; /* eInvalid now means get the default timebase and track it */ |
|---|
| 1197 | if (cfg.UsePcrTimeBase) { |
|---|
| 1198 | NEXUS_TimebaseHandle timebase = NEXUS_Timebase_Resolve_priv(p->settings.timestamp.timebase); |
|---|
| 1199 | if (timebase) |
|---|
| 1200 | { |
|---|
| 1201 | cfg.WhichPcrToUse = timebase->hwIndex; |
|---|
| 1202 | } |
|---|
| 1203 | else |
|---|
| 1204 | { |
|---|
| 1205 | return BERR_TRACE(NEXUS_INVALID_PARAMETER); |
|---|
| 1206 | } |
|---|
| 1207 | } |
|---|
| 1208 | cfg.PacingOffsetAdjustDisable = p->settings.timestamp.pacingOffsetAdjustDisable; |
|---|
| 1209 | |
|---|
| 1210 | #if BXPT_HAS_TSMUX |
|---|
| 1211 | if(muxInput) { |
|---|
| 1212 | cfg.PesBasedPacing = true; |
|---|
| 1213 | cfg.Use8WordDesc = true; |
|---|
| 1214 | cfg.PesBasedPacing = true; |
|---|
| 1215 | cfg.TimestampMode = BXPT_TimestampMode_e30_2U_Binary; |
|---|
| 1216 | cfg.Use32BitTimestamps = true; |
|---|
| 1217 | cfg.TimestampEn = false; |
|---|
| 1218 | } else { |
|---|
| 1219 | cfg.PesBasedPacing = false; |
|---|
| 1220 | cfg.Use8WordDesc = false; |
|---|
| 1221 | } |
|---|
| 1222 | #else |
|---|
| 1223 | BSTD_UNUSED(muxInput); |
|---|
| 1224 | #endif |
|---|
| 1225 | rc = BXPT_Playback_SetChannelSettings(p->xpt_play, &cfg); |
|---|
| 1226 | if (rc) {rc=BERR_TRACE(rc);goto error;} |
|---|
| 1227 | |
|---|
| 1228 | #if B_HAS_VBI |
|---|
| 1229 | rc = bstream_p_vbi_open(&p->stream); |
|---|
| 1230 | if (rc) goto error; |
|---|
| 1231 | #endif |
|---|
| 1232 | |
|---|
| 1233 | if (p->settings.timestamp.pacing) { |
|---|
| 1234 | rc = BXPT_Playback_ConfigPacing(p->xpt_play, BXPT_PacingControl_eStart); |
|---|
| 1235 | if (rc) goto error; |
|---|
| 1236 | p->state.pacing = true; |
|---|
| 1237 | |
|---|
| 1238 | NEXUS_Playpump_P_InstallRangeErrIntHandler(p); |
|---|
| 1239 | } |
|---|
| 1240 | |
|---|
| 1241 | for(play_pid=BLST_S_FIRST(&p->pid_list);play_pid!=NULL;play_pid=BLST_S_NEXT(play_pid, link)) { |
|---|
| 1242 | rc = NEXUS_Playpump_P_StartPid(p, play_pid); |
|---|
| 1243 | if (rc!=BERR_SUCCESS) { rc = BERR_TRACE(rc); goto error; } |
|---|
| 1244 | } |
|---|
| 1245 | |
|---|
| 1246 | #if B_HAS_MEDIA |
|---|
| 1247 | if (p->state.packetizer==b_play_packetizer_media) { |
|---|
| 1248 | rc = b_pump_demux_start(p->demux); |
|---|
| 1249 | if(rc!=NEXUS_SUCCESS) {rc=BERR_TRACE(rc);goto error;} |
|---|
| 1250 | } else |
|---|
| 1251 | #endif |
|---|
| 1252 | if (p->state.packetizer==b_play_packetizer_crypto) { |
|---|
| 1253 | rc = b_pump_crypto_start(p->crypto); |
|---|
| 1254 | if(rc!=NEXUS_SUCCESS) {rc=BERR_TRACE(rc);goto error;} |
|---|
| 1255 | } else { |
|---|
| 1256 | rc = BPVRlib_Feed_Start(p->play_feed); |
|---|
| 1257 | if (rc) {rc=BERR_TRACE(rc);goto error;} |
|---|
| 1258 | } |
|---|
| 1259 | |
|---|
| 1260 | /* pause playback until first consumer (decode or record) is started. this prevent data from being lost |
|---|
| 1261 | if any amount of time between playback start and rave configuration (which is done at decode start). */ |
|---|
| 1262 | if(!p->consumerStarted) { /* 't pause on Start */ |
|---|
| 1263 | rc = BXPT_Playback_Pause(p->xpt_play); |
|---|
| 1264 | if (rc) {rc=BERR_TRACE(rc);goto error_pause;} |
|---|
| 1265 | } |
|---|
| 1266 | |
|---|
| 1267 | /* We may have a left over event, and we want to ensure that 1 interrupt |
|---|
| 1268 | always means 1 free descriptor in b_playpump_p_xpt_event */ |
|---|
| 1269 | BKNI_ResetEvent(p->descEvent); |
|---|
| 1270 | |
|---|
| 1271 | p->playEventHandle = NEXUS_RegisterEvent(p->descEvent, b_playpump_p_xpt_event, p); |
|---|
| 1272 | if (!p->playEventHandle) {rc=BERR_TRACE(NEXUS_UNKNOWN); goto error_started;} |
|---|
| 1273 | |
|---|
| 1274 | /* Set run state because calling first read */ |
|---|
| 1275 | p->state.running = true; |
|---|
| 1276 | p->state.muxInput = muxInput; |
|---|
| 1277 | |
|---|
| 1278 | if(!muxInput) { |
|---|
| 1279 | /* Request the first async read, which kickstarts the read cycle. */ |
|---|
| 1280 | b_playpump_p_do_read_callback(p); |
|---|
| 1281 | |
|---|
| 1282 | p->throttle_timer = NEXUS_ScheduleTimer(B_THROTTLE_TIMEOUT, b_playpump_p_throttle_timer, p); /* schedulle timer after 30 ms */ |
|---|
| 1283 | } |
|---|
| 1284 | |
|---|
| 1285 | return 0; |
|---|
| 1286 | |
|---|
| 1287 | error_pause: |
|---|
| 1288 | error_started: |
|---|
| 1289 | #if B_HAS_MEDIA |
|---|
| 1290 | if (p->state.packetizer==b_play_packetizer_media) { |
|---|
| 1291 | b_pump_demux_stop(p->demux); |
|---|
| 1292 | } else |
|---|
| 1293 | #endif |
|---|
| 1294 | if (p->state.packetizer==b_play_packetizer_crypto) { |
|---|
| 1295 | b_pump_crypto_stop(p->crypto); |
|---|
| 1296 | } else { |
|---|
| 1297 | BPVRlib_Feed_Stop(p->play_feed); |
|---|
| 1298 | } |
|---|
| 1299 | if (p->state.pacing) { |
|---|
| 1300 | NEXUS_Playpump_P_UninstallRangeErrIntHandler(p); |
|---|
| 1301 | |
|---|
| 1302 | rc = BXPT_Playback_ConfigPacing(p->xpt_play,BXPT_PacingControl_eStop); |
|---|
| 1303 | if (rc!=BERR_SUCCESS) { rc = BERR_TRACE(rc);} |
|---|
| 1304 | } |
|---|
| 1305 | err_parser_band: |
|---|
| 1306 | NEXUS_Transport_P_IncPowerDown(false); |
|---|
| 1307 | err_state: |
|---|
| 1308 | error: |
|---|
| 1309 | BDBG_ASSERT(rc); |
|---|
| 1310 | return rc; |
|---|
| 1311 | } |
|---|
| 1312 | |
|---|
| 1313 | NEXUS_Error NEXUS_Playpump_Start(NEXUS_PlaypumpHandle p) |
|---|
| 1314 | { |
|---|
| 1315 | return NEXUS_Playpump_Start_priv(p, false); |
|---|
| 1316 | } |
|---|
| 1317 | |
|---|
| 1318 | NEXUS_Error NEXUS_Playpump_StartMuxInput_priv(NEXUS_PlaypumpHandle playpump) |
|---|
| 1319 | { |
|---|
| 1320 | NEXUS_ASSERT_MODULE(); |
|---|
| 1321 | BDBG_OBJECT_ASSERT(playpump, NEXUS_Playpump); |
|---|
| 1322 | return NEXUS_Playpump_Start_priv(playpump, true); |
|---|
| 1323 | } |
|---|
| 1324 | |
|---|
| 1325 | |
|---|
| 1326 | void NEXUS_Playpump_Stop(NEXUS_PlaypumpHandle p) |
|---|
| 1327 | { |
|---|
| 1328 | BERR_Code rc; |
|---|
| 1329 | NEXUS_P_PlaypumpPidChannel *play_pid; |
|---|
| 1330 | |
|---|
| 1331 | BDBG_OBJECT_ASSERT(p, NEXUS_Playpump); |
|---|
| 1332 | if(!p->state.running) { |
|---|
| 1333 | BDBG_WRN(("NEXUS_Playpump_Stop: %#lx playpump already stopped")); |
|---|
| 1334 | return; |
|---|
| 1335 | } |
|---|
| 1336 | p->consumerStarted = false; /* don't pause on Start */ |
|---|
| 1337 | |
|---|
| 1338 | NEXUS_UnregisterEvent(p->playEventHandle); |
|---|
| 1339 | if (p->state.pacing) { |
|---|
| 1340 | NEXUS_Playpump_P_UninstallRangeErrIntHandler(p); |
|---|
| 1341 | rc = BXPT_Playback_ConfigPacing(p->xpt_play, BXPT_PacingControl_eStop); |
|---|
| 1342 | if (rc!=BERR_SUCCESS) { |
|---|
| 1343 | BDBG_ERR(("ignored error %#x from BXPT_Playback_ConfigPacing", rc)); |
|---|
| 1344 | } |
|---|
| 1345 | p->state.pacing = false; |
|---|
| 1346 | } |
|---|
| 1347 | rc = NEXUS_Playpump_Flush(p); |
|---|
| 1348 | if (rc!=BERR_SUCCESS) {rc=BERR_TRACE(rc);} |
|---|
| 1349 | |
|---|
| 1350 | /* after we've flushed, we can state we're not running */ |
|---|
| 1351 | p->state.running = false; |
|---|
| 1352 | p->state.muxInput = false; |
|---|
| 1353 | |
|---|
| 1354 | p->settings.playRate = NEXUS_NORMAL_PLAY_SPEED; /* reset a play rate */ |
|---|
| 1355 | #if B_HAS_MEDIA |
|---|
| 1356 | if (p->state.packetizer==b_play_packetizer_media) { |
|---|
| 1357 | b_pump_demux_stop(p->demux); |
|---|
| 1358 | } else |
|---|
| 1359 | #endif |
|---|
| 1360 | if (p->state.packetizer==b_play_packetizer_crypto) { |
|---|
| 1361 | b_pump_crypto_stop(p->crypto); |
|---|
| 1362 | } else { |
|---|
| 1363 | BPVRlib_Feed_Stop(p->play_feed); |
|---|
| 1364 | } |
|---|
| 1365 | |
|---|
| 1366 | for(play_pid=BLST_S_FIRST(&p->pid_list);play_pid!=NULL;play_pid=BLST_S_NEXT(play_pid, link)) { |
|---|
| 1367 | NEXUS_Playpump_P_StopPid(p, play_pid); |
|---|
| 1368 | } |
|---|
| 1369 | rc = BXPT_Playback_DisablePacketizers(p->xpt_play); |
|---|
| 1370 | if (rc!=BERR_SUCCESS) {rc=BERR_TRACE(rc);} |
|---|
| 1371 | |
|---|
| 1372 | if (p->throttle_timer) { |
|---|
| 1373 | NEXUS_CancelTimer(p->throttle_timer); |
|---|
| 1374 | p->throttle_timer = NULL; |
|---|
| 1375 | } |
|---|
| 1376 | |
|---|
| 1377 | NEXUS_Transport_P_IncPowerDown(false); |
|---|
| 1378 | |
|---|
| 1379 | if(NEXUS_GetEnv("profile_playpump")) { |
|---|
| 1380 | NEXUS_Profile_Stop("NEXUS_Playpump"); |
|---|
| 1381 | } |
|---|
| 1382 | |
|---|
| 1383 | return; |
|---|
| 1384 | } |
|---|
| 1385 | |
|---|
| 1386 | NEXUS_Error NEXUS_Playpump_Flush(NEXUS_PlaypumpHandle p) |
|---|
| 1387 | { |
|---|
| 1388 | BERR_Code rc; |
|---|
| 1389 | |
|---|
| 1390 | BDBG_OBJECT_ASSERT(p, NEXUS_Playpump); |
|---|
| 1391 | |
|---|
| 1392 | if (!p->state.running) { |
|---|
| 1393 | /* no need to flush if not started. if it is stopped, BPVRlib_Feed_Stop/Start further down |
|---|
| 1394 | will have the unintentional effect of restarting playback. */ |
|---|
| 1395 | return 0; |
|---|
| 1396 | } |
|---|
| 1397 | BDBG_MSG(("flushing playback buffers")); |
|---|
| 1398 | |
|---|
| 1399 | #if B_HAS_MEDIA |
|---|
| 1400 | if (p->state.packetizer==b_play_packetizer_media) { |
|---|
| 1401 | b_pump_demux_flush(p->demux); |
|---|
| 1402 | } else |
|---|
| 1403 | #endif |
|---|
| 1404 | if (p->state.packetizer==b_play_packetizer_crypto) { |
|---|
| 1405 | b_pump_crypto_flush(p->crypto); |
|---|
| 1406 | } |
|---|
| 1407 | b_playpump_p_reset(p); |
|---|
| 1408 | |
|---|
| 1409 | if (p->state.packetizer!=b_play_packetizer_media) { |
|---|
| 1410 | BPVRlib_Feed_Stop(p->play_feed); |
|---|
| 1411 | rc = BPVRlib_Feed_Start(p->play_feed); |
|---|
| 1412 | if (rc) return BERR_TRACE(rc); |
|---|
| 1413 | } |
|---|
| 1414 | |
|---|
| 1415 | p->state.last_addr = NULL; |
|---|
| 1416 | |
|---|
| 1417 | /* PI will clear pause, so restore it */ |
|---|
| 1418 | if (p->paused) { |
|---|
| 1419 | rc = NEXUS_Playpump_SetPause(p, true); |
|---|
| 1420 | if (rc) return BERR_TRACE(rc); |
|---|
| 1421 | } |
|---|
| 1422 | |
|---|
| 1423 | return NEXUS_SUCCESS; |
|---|
| 1424 | } |
|---|
| 1425 | |
|---|
| 1426 | NEXUS_Error |
|---|
| 1427 | NEXUS_Playpump_GetBuffer(NEXUS_PlaypumpHandle p, void **buffer, size_t *size) |
|---|
| 1428 | { |
|---|
| 1429 | uint8_t *addr; |
|---|
| 1430 | unsigned freeSize, freeDesc; |
|---|
| 1431 | |
|---|
| 1432 | BDBG_OBJECT_ASSERT(p, NEXUS_Playpump); |
|---|
| 1433 | |
|---|
| 1434 | if (!p->state.running) { |
|---|
| 1435 | /* don't print error message, because this is a normal exit from thread processing */ |
|---|
| 1436 | return NEXUS_UNKNOWN; |
|---|
| 1437 | } |
|---|
| 1438 | |
|---|
| 1439 | freeSize = BFIFO_WRITE_PEEK(&p->fifo); |
|---|
| 1440 | if(freeSize==0) { |
|---|
| 1441 | BDBG_MSG_FLOW(("Playback buffer is full, keep waiting")); |
|---|
| 1442 | goto keep_waiting; |
|---|
| 1443 | } |
|---|
| 1444 | freeDesc = BFIFO_WRITE_LEFT(&p->activeFifo); |
|---|
| 1445 | if(freeDesc==0) { |
|---|
| 1446 | BDBG_MSG_FLOW(("no chunks available, waiting for any")); |
|---|
| 1447 | goto keep_waiting; |
|---|
| 1448 | } |
|---|
| 1449 | BDBG_ASSERT(BFIFO_WRITE_PEEK(&p->pendingFifo)); |
|---|
| 1450 | BDBG_ASSERT(BFIFO_WRITE(&p->activeFifo)==BFIFO_WRITE(&p->pendingFifo)); |
|---|
| 1451 | *size = freeSize; |
|---|
| 1452 | if(p->settings.mode==NEXUS_PlaypumpMode_eScatterGather) { |
|---|
| 1453 | if(freeSize>freeDesc*sizeof(NEXUS_PlaypumpDesc)) { |
|---|
| 1454 | *size = freeDesc*sizeof(NEXUS_PlaypumpDesc); |
|---|
| 1455 | } |
|---|
| 1456 | } |
|---|
| 1457 | addr = BFIFO_WRITE(&p->fifo); |
|---|
| 1458 | BDBG_ASSERT(addr); |
|---|
| 1459 | |
|---|
| 1460 | p->state.last_addr = addr; |
|---|
| 1461 | *buffer = p->state.last_addr; |
|---|
| 1462 | BDBG_MSG_FLOW(("get_buffer %#lx, %d", (unsigned long)*buffer, *size)); |
|---|
| 1463 | return 0; |
|---|
| 1464 | |
|---|
| 1465 | keep_waiting: |
|---|
| 1466 | *buffer = NULL; |
|---|
| 1467 | *size = 0; |
|---|
| 1468 | return 0; |
|---|
| 1469 | |
|---|
| 1470 | } |
|---|
| 1471 | |
|---|
| 1472 | NEXUS_Error NEXUS_Playpump_WriteComplete(NEXUS_PlaypumpHandle p, size_t skip, size_t amount_used) |
|---|
| 1473 | { |
|---|
| 1474 | BERR_Code rc; |
|---|
| 1475 | unsigned amount_to_commit = skip + amount_used; |
|---|
| 1476 | unsigned amount_to_skip = skip; |
|---|
| 1477 | |
|---|
| 1478 | BDBG_OBJECT_ASSERT(p, NEXUS_Playpump); |
|---|
| 1479 | |
|---|
| 1480 | if (amount_to_commit > p->openSettings.fifoSize) { |
|---|
| 1481 | return BERR_TRACE(NEXUS_INVALID_PARAMETER); |
|---|
| 1482 | } |
|---|
| 1483 | |
|---|
| 1484 | if (!p->state.running) { |
|---|
| 1485 | /* don't print error message, because this is a normal exit from thread processing */ |
|---|
| 1486 | return NEXUS_UNKNOWN; |
|---|
| 1487 | } |
|---|
| 1488 | |
|---|
| 1489 | if (!p->state.last_addr) { |
|---|
| 1490 | return BERR_TRACE(NEXUS_UNKNOWN); |
|---|
| 1491 | } |
|---|
| 1492 | |
|---|
| 1493 | if (skip==0 && amount_used==0) { |
|---|
| 1494 | BDBG_MSG(("%#lx loop detected", (unsigned long)p)); /* player sends an empty entry if it's about to loop a stream */ |
|---|
| 1495 | } |
|---|
| 1496 | |
|---|
| 1497 | /* make sure it's in the physical memory so the chip can read it */ |
|---|
| 1498 | BDBG_MSG_FLOW(("write_complete %#lx:%u %u %#lx", (unsigned long)p->state.last_addr, skip, amount_used, (unsigned long)BFIFO_WRITE(&p->activeFifo))); |
|---|
| 1499 | |
|---|
| 1500 | rc = b_playpump_p_add_request(p, amount_to_skip, amount_to_commit - amount_to_skip, NULL); |
|---|
| 1501 | if (rc) return BERR_TRACE(rc); |
|---|
| 1502 | |
|---|
| 1503 | p->state.last_addr = NULL; |
|---|
| 1504 | |
|---|
| 1505 | return 0; |
|---|
| 1506 | } |
|---|
| 1507 | |
|---|
| 1508 | NEXUS_Error NEXUS_Playpump_SubmitScatterGatherDescriptor(NEXUS_PlaypumpHandle p, const NEXUS_PlaypumpScatterGatherDescriptor *pDesc, size_t numDescriptors, size_t *pNumConsumed) |
|---|
| 1509 | { |
|---|
| 1510 | BERR_Code rc; |
|---|
| 1511 | unsigned nFree; |
|---|
| 1512 | BDBG_OBJECT_ASSERT(p, NEXUS_Playpump); |
|---|
| 1513 | BDBG_ASSERT(pNumConsumed); |
|---|
| 1514 | |
|---|
| 1515 | if (!p->state.running) { |
|---|
| 1516 | /* don't print error message, because this is a normal exit from thread processing */ |
|---|
| 1517 | return NEXUS_UNKNOWN; |
|---|
| 1518 | } |
|---|
| 1519 | |
|---|
| 1520 | *pNumConsumed = 0; |
|---|
| 1521 | |
|---|
| 1522 | nFree = BFIFO_WRITE_PEEK(&p->activeFifo); |
|---|
| 1523 | if (nFree==0 || numDescriptors==0) { |
|---|
| 1524 | return 0; |
|---|
| 1525 | } |
|---|
| 1526 | else if (nFree < numDescriptors) { |
|---|
| 1527 | numDescriptors = nFree; |
|---|
| 1528 | } |
|---|
| 1529 | |
|---|
| 1530 | BDBG_MSG_FLOW(("submit_sg %#lx: %#lx", (unsigned long)p->state.last_addr, (unsigned long)BFIFO_WRITE(&p->activeFifo))); |
|---|
| 1531 | |
|---|
| 1532 | rc = b_playpump_p_add_request(p, 0, numDescriptors*sizeof(NEXUS_PlaypumpScatterGatherDescriptor), pDesc); |
|---|
| 1533 | if (rc) return BERR_TRACE(rc); |
|---|
| 1534 | |
|---|
| 1535 | *pNumConsumed = numDescriptors; |
|---|
| 1536 | |
|---|
| 1537 | return 0; |
|---|
| 1538 | } |
|---|
| 1539 | |
|---|
| 1540 | NEXUS_Error NEXUS_Playpump_GetStatus(NEXUS_PlaypumpHandle p, NEXUS_PlaypumpStatus *pStatus) |
|---|
| 1541 | { |
|---|
| 1542 | BDBG_OBJECT_ASSERT(p, NEXUS_Playpump); |
|---|
| 1543 | BDBG_ASSERT(pStatus); |
|---|
| 1544 | |
|---|
| 1545 | BKNI_Memset(pStatus, 0, sizeof(*pStatus)); |
|---|
| 1546 | pStatus->started = p->state.running; |
|---|
| 1547 | pStatus->fifoSize = p->openSettings.fifoSize; |
|---|
| 1548 | pStatus->descFifoSize = p->openSettings.numDescriptors; |
|---|
| 1549 | pStatus->bytesPlayed = p->state.bytes_played; |
|---|
| 1550 | pStatus->bufferBase = p->buf; |
|---|
| 1551 | pStatus->fifoDepth = BFIFO_READ_LEFT(&p->fifo); |
|---|
| 1552 | pStatus->descFifoDepth = BFIFO_READ_LEFT(&p->activeFifo); |
|---|
| 1553 | pStatus->index=p->index; |
|---|
| 1554 | pStatus->pacingTsRangeError = p->state.pacingTsRangeError; |
|---|
| 1555 | pStatus->syncErrors = 0; |
|---|
| 1556 | pStatus->resyncEvents = 0; |
|---|
| 1557 | pStatus->streamErrors = 0; |
|---|
| 1558 | pStatus->mediaPtsType = NEXUS_PtsType_eInterpolatedFromInvalidPTS; |
|---|
| 1559 | pStatus->mediaPts = 0; |
|---|
| 1560 | |
|---|
| 1561 | #if B_HAS_MEDIA |
|---|
| 1562 | if(p->state.packetizer==b_play_packetizer_media) { |
|---|
| 1563 | b_pump_demux_status(p->demux, pStatus); |
|---|
| 1564 | } else |
|---|
| 1565 | #endif |
|---|
| 1566 | if(p->state.packetizer==b_play_packetizer_crypto) { |
|---|
| 1567 | b_pump_crypto_status(p->crypto); |
|---|
| 1568 | } |
|---|
| 1569 | return NEXUS_SUCCESS; |
|---|
| 1570 | } |
|---|
| 1571 | |
|---|
| 1572 | void NEXUS_Playpump_P_ConsumerStarted(NEXUS_PlaypumpHandle p) |
|---|
| 1573 | { |
|---|
| 1574 | BERR_Code rc; |
|---|
| 1575 | BDBG_OBJECT_ASSERT(p, NEXUS_Playpump); |
|---|
| 1576 | if(p->state.running && !p->consumerStarted) { |
|---|
| 1577 | rc = BXPT_Playback_Resume(p->xpt_play); |
|---|
| 1578 | if(rc!=BERR_SUCCESS) { rc=BERR_TRACE(rc);} |
|---|
| 1579 | } |
|---|
| 1580 | p->consumerStarted=true; /* don't pause on Start */ |
|---|
| 1581 | return; |
|---|
| 1582 | } |
|---|
| 1583 | |
|---|
| 1584 | static void |
|---|
| 1585 | NEXUS_Playpump_P_SetPacketizerCfg(BXPT_Playback_PacketizeConfig *pkt_cfg, NEXUS_TransportType type, uint16_t oldpid, uint16_t newpid, |
|---|
| 1586 | const NEXUS_PlaypumpOpenPidChannelSettings *pSettings) |
|---|
| 1587 | { |
|---|
| 1588 | BDBG_MSG(("mapping stream id %#x to pid %#x", (unsigned)oldpid, (unsigned)newpid)); |
|---|
| 1589 | |
|---|
| 1590 | pkt_cfg->Pid = newpid; |
|---|
| 1591 | pkt_cfg->ChannelNum = 0; /* fill this in below, after calling bsettop_p_transport_lock */ |
|---|
| 1592 | #if !BXPT_HAS_PID_CHANNEL_PES_FILTERING |
|---|
| 1593 | if(type == NEXUS_TransportType_eEs) { |
|---|
| 1594 | pkt_cfg->IsEs = true; |
|---|
| 1595 | pkt_cfg->PesStreamId = 0x00; |
|---|
| 1596 | pkt_cfg->IsDvd = false; |
|---|
| 1597 | } else if (type == NEXUS_TransportType_eVob) { |
|---|
| 1598 | pkt_cfg->IsEs = false; |
|---|
| 1599 | pkt_cfg->PesStreamId = 0; |
|---|
| 1600 | pkt_cfg->IsDvd = true; |
|---|
| 1601 | } else { |
|---|
| 1602 | pkt_cfg->IsEs = false; |
|---|
| 1603 | pkt_cfg->PesStreamId = oldpid; |
|---|
| 1604 | pkt_cfg->IsDvd = false; |
|---|
| 1605 | } |
|---|
| 1606 | pkt_cfg->MapAll = false; |
|---|
| 1607 | BSTD_UNUSED(pSettings); |
|---|
| 1608 | #else |
|---|
| 1609 | if(type == NEXUS_TransportType_eEs) { |
|---|
| 1610 | pkt_cfg->PacketizerMode = BXPT_Playback_PacketizerMode_Es; |
|---|
| 1611 | } else { |
|---|
| 1612 | pkt_cfg->PacketizerMode = BXPT_Playback_PacketizerMode_Pes_Sid; |
|---|
| 1613 | pkt_cfg->FilterConfig.StreamId = oldpid; |
|---|
| 1614 | } |
|---|
| 1615 | if (pSettings->pidType == NEXUS_PidType_eAudio && type == NEXUS_TransportType_eVob) { |
|---|
| 1616 | switch (pSettings->pidTypeSettings.audio.codec) { |
|---|
| 1617 | case NEXUS_AudioCodec_eLpcmDvd: |
|---|
| 1618 | case NEXUS_AudioCodec_eLpcmHdDvd: |
|---|
| 1619 | case NEXUS_AudioCodec_eLpcmBluRay: |
|---|
| 1620 | pkt_cfg->PacketizerMode = BXPT_Playback_PacketizerMode_Pes_SidSubSid; |
|---|
| 1621 | pkt_cfg->FilterConfig.StreamIdAndSubStreamId.Id = (oldpid & 0xFF); |
|---|
| 1622 | pkt_cfg->FilterConfig.StreamIdAndSubStreamId.SubStreamId = 0xA0 | (oldpid>>8); |
|---|
| 1623 | break; |
|---|
| 1624 | case NEXUS_AudioCodec_eAc3Plus: |
|---|
| 1625 | pkt_cfg->PacketizerMode = BXPT_Playback_PacketizerMode_Pes_SidSubSid; |
|---|
| 1626 | pkt_cfg->FilterConfig.StreamIdAndSubStreamId.Id = (oldpid & 0xFF); |
|---|
| 1627 | pkt_cfg->FilterConfig.StreamIdAndSubStreamId.SubStreamId = 0xC0 | (oldpid>>8); |
|---|
| 1628 | break; |
|---|
| 1629 | case NEXUS_AudioCodec_eAc3: |
|---|
| 1630 | pkt_cfg->PacketizerMode = BXPT_Playback_PacketizerMode_Pes_SidSubSid; |
|---|
| 1631 | pkt_cfg->FilterConfig.StreamIdAndSubStreamId.Id = (oldpid & 0xFF); |
|---|
| 1632 | pkt_cfg->FilterConfig.StreamIdAndSubStreamId.SubStreamId = 0x80 | (oldpid>>8); |
|---|
| 1633 | break; |
|---|
| 1634 | case NEXUS_AudioCodec_eDts: |
|---|
| 1635 | pkt_cfg->PacketizerMode = BXPT_Playback_PacketizerMode_Pes_SidSubSid; |
|---|
| 1636 | pkt_cfg->FilterConfig.StreamIdAndSubStreamId.Id = (oldpid & 0xFF); |
|---|
| 1637 | pkt_cfg->FilterConfig.StreamIdAndSubStreamId.SubStreamId = 0x88 | (oldpid>>8); |
|---|
| 1638 | break; |
|---|
| 1639 | default: |
|---|
| 1640 | BDBG_WRN(("Unexpected VOB audio format %d", pSettings->pidTypeSettings.audio.codec)); |
|---|
| 1641 | break; |
|---|
| 1642 | } |
|---|
| 1643 | } |
|---|
| 1644 | #endif |
|---|
| 1645 | } |
|---|
| 1646 | |
|---|
| 1647 | /* OpenPidChannel and activate packetization if needed */ |
|---|
| 1648 | static NEXUS_Error |
|---|
| 1649 | NEXUS_Playpump_P_OpenPid(NEXUS_PlaypumpHandle p, NEXUS_P_PlaypumpPidChannel *play_pid, uint16_t oldpid, NEXUS_TransportType type, |
|---|
| 1650 | NEXUS_TransportType originalType, const NEXUS_PlaypumpOpenPidChannelSettings *pSettings, bool forcedPacketizerPid, uint16_t packetizerPid) |
|---|
| 1651 | { |
|---|
| 1652 | uint16_t newpid = 0; |
|---|
| 1653 | BERR_Code rc; |
|---|
| 1654 | NEXUS_PidChannelHandle pidChannel=NULL; |
|---|
| 1655 | NEXUS_PidChannelStatus pid_status; |
|---|
| 1656 | |
|---|
| 1657 | play_pid->packetizer.enable = false; |
|---|
| 1658 | play_pid->packetizer.active = false; |
|---|
| 1659 | switch (type) { |
|---|
| 1660 | default: |
|---|
| 1661 | pidChannel = NEXUS_PidChannel_P_Open(NULL, p, oldpid, &pSettings->pidSettings, p->settings.continuityCountEnabled); |
|---|
| 1662 | if(!pidChannel) { rc = BERR_TRACE(BERR_NOT_SUPPORTED); goto err_pid_channel_ts; } |
|---|
| 1663 | pidChannel->status.transportType = type; |
|---|
| 1664 | pidChannel->status.originalTransportType = originalType; |
|---|
| 1665 | goto opened; |
|---|
| 1666 | |
|---|
| 1667 | case NEXUS_TransportType_eEs: |
|---|
| 1668 | case NEXUS_TransportType_eVob: |
|---|
| 1669 | case NEXUS_TransportType_eMpeg2Pes: |
|---|
| 1670 | case NEXUS_TransportType_eMpeg1Ps: |
|---|
| 1671 | break; |
|---|
| 1672 | } |
|---|
| 1673 | newpid = b_pid_map_alloc(&p->packetizer_map); |
|---|
| 1674 | if(newpid==0) { |
|---|
| 1675 | rc = BERR_TRACE(BERR_NOT_SUPPORTED); |
|---|
| 1676 | goto err_newpid; |
|---|
| 1677 | } |
|---|
| 1678 | |
|---|
| 1679 | /* the remainder of this function handles packetization */ |
|---|
| 1680 | NEXUS_Playpump_P_SetPacketizerCfg(&play_pid->packetizer.cfg, type, oldpid, forcedPacketizerPid?packetizerPid:newpid, pSettings); |
|---|
| 1681 | |
|---|
| 1682 | pidChannel = NEXUS_PidChannel_P_Open(NULL, p, forcedPacketizerPid?packetizerPid:newpid, &pSettings->pidSettings, p->settings.continuityCountEnabled); |
|---|
| 1683 | if(!pidChannel) { rc = BERR_TRACE(BERR_NOT_SUPPORTED); goto err_pid_channel; } |
|---|
| 1684 | |
|---|
| 1685 | pidChannel->status.transportType = NEXUS_TransportType_eTs; |
|---|
| 1686 | pidChannel->status.originalTransportType = originalType; |
|---|
| 1687 | pidChannel->status.remappedPid = oldpid; |
|---|
| 1688 | |
|---|
| 1689 | rc = NEXUS_PidChannel_GetStatus(pidChannel, &pid_status); |
|---|
| 1690 | if(rc!=BERR_SUCCESS) { rc = BERR_TRACE(rc); goto err_pid_status; } |
|---|
| 1691 | play_pid->packetizer.context = newpid - NEXUS_P_PACKETIZER_BASE; |
|---|
| 1692 | play_pid->packetizer.cfg.ChannelNum = pid_status.pidChannelIndex; |
|---|
| 1693 | BDBG_ASSERT(newpid >= NEXUS_P_PACKETIZER_BASE); |
|---|
| 1694 | |
|---|
| 1695 | play_pid->packetizer.enable = true; |
|---|
| 1696 | |
|---|
| 1697 | opened: |
|---|
| 1698 | play_pid->pid_channel = pidChannel; |
|---|
| 1699 | if (p->state.running) { |
|---|
| 1700 | rc = NEXUS_Playpump_P_StartPid(p, play_pid); |
|---|
| 1701 | if (rc!=BERR_SUCCESS) { rc = BERR_TRACE(rc); goto err_packetize; } |
|---|
| 1702 | } |
|---|
| 1703 | |
|---|
| 1704 | return 0; |
|---|
| 1705 | |
|---|
| 1706 | err_packetize: |
|---|
| 1707 | err_pid_status: |
|---|
| 1708 | NEXUS_PidChannel_P_Close(pidChannel); |
|---|
| 1709 | err_pid_channel: |
|---|
| 1710 | if (newpid) { |
|---|
| 1711 | b_pid_map_free(&p->packetizer_map, newpid); |
|---|
| 1712 | } |
|---|
| 1713 | err_newpid: |
|---|
| 1714 | err_pid_channel_ts: |
|---|
| 1715 | play_pid->pid_channel = NULL; |
|---|
| 1716 | BDBG_ASSERT(rc); |
|---|
| 1717 | return rc; |
|---|
| 1718 | } |
|---|
| 1719 | |
|---|
| 1720 | static void |
|---|
| 1721 | NEXUS_Playpump_P_ClosePid(NEXUS_PlaypumpHandle p, NEXUS_P_PlaypumpPidChannel *play_pid) |
|---|
| 1722 | { |
|---|
| 1723 | #if B_HAS_MEDIA |
|---|
| 1724 | if(p->use_media) { |
|---|
| 1725 | if(p->state.running) { |
|---|
| 1726 | b_pump_demux_remove_pid(p->demux, play_pid); |
|---|
| 1727 | } |
|---|
| 1728 | b_pump_demux_close_pid(p->demux, play_pid); |
|---|
| 1729 | } |
|---|
| 1730 | #endif |
|---|
| 1731 | if (p->state.running) { |
|---|
| 1732 | NEXUS_Playpump_P_StopPid(p, play_pid); |
|---|
| 1733 | } |
|---|
| 1734 | |
|---|
| 1735 | if(play_pid->packetizer.enable) { |
|---|
| 1736 | b_pid_map_free(&p->packetizer_map, play_pid->packetizer.context+NEXUS_P_PACKETIZER_BASE); |
|---|
| 1737 | } |
|---|
| 1738 | NEXUS_PidChannel_P_Close(play_pid->pid_channel); |
|---|
| 1739 | return; |
|---|
| 1740 | } |
|---|
| 1741 | |
|---|
| 1742 | void |
|---|
| 1743 | NEXUS_Playpump_GetDefaultOpenPidChannelSettings(NEXUS_PlaypumpOpenPidChannelSettings *pSettings) |
|---|
| 1744 | { |
|---|
| 1745 | BDBG_ASSERT(pSettings); |
|---|
| 1746 | BKNI_Memset(pSettings, 0, sizeof(*pSettings)); |
|---|
| 1747 | NEXUS_PidChannel_GetDefaultSettings(&pSettings->pidSettings); |
|---|
| 1748 | pSettings->pidType = NEXUS_PidType_eUnknown; |
|---|
| 1749 | pSettings->allowTimestampReordering = true; |
|---|
| 1750 | return; |
|---|
| 1751 | } |
|---|
| 1752 | |
|---|
| 1753 | |
|---|
| 1754 | |
|---|
| 1755 | static NEXUS_PidChannelHandle |
|---|
| 1756 | NEXUS_Playpump_P_OpenPidChannel_MuxImpl(NEXUS_PlaypumpHandle p, unsigned pid, const NEXUS_PlaypumpOpenPidChannelSettings *pSettings, bool forcedPacketizerPid, uint16_t packetizerPid) |
|---|
| 1757 | { |
|---|
| 1758 | BERR_Code rc; |
|---|
| 1759 | NEXUS_P_PlaypumpPidChannel *play_pid; |
|---|
| 1760 | NEXUS_PlaypumpOpenPidChannelSettings settings; |
|---|
| 1761 | NEXUS_TransportType transportType; |
|---|
| 1762 | |
|---|
| 1763 | BDBG_OBJECT_ASSERT(p, NEXUS_Playpump); |
|---|
| 1764 | if(!pSettings) { |
|---|
| 1765 | NEXUS_Playpump_GetDefaultOpenPidChannelSettings(&settings); |
|---|
| 1766 | pSettings = &settings; |
|---|
| 1767 | } |
|---|
| 1768 | |
|---|
| 1769 | /* if pidChannelIndex is specified, this is a special case that requires the app to manage its pid channels more. */ |
|---|
| 1770 | if (pSettings->pidSettings.pidChannelIndex != -1) { |
|---|
| 1771 | /* look up existing pid channels for the same pidChannelIndex */ |
|---|
| 1772 | for(play_pid=BLST_S_FIRST(&p->pid_list); play_pid; play_pid=BLST_S_NEXT(play_pid, link)) { |
|---|
| 1773 | if((int)play_pid->pid_channel->status.pidChannelIndex == pSettings->pidSettings.pidChannelIndex) { |
|---|
| 1774 | if(play_pid->pid != pid) { |
|---|
| 1775 | BDBG_ERR(("Cannot open the same pidChannelIndex (%d) with different pids (0x%x and 0x%x)", pSettings->pidSettings.pidChannelIndex, play_pid->pid, pid)); |
|---|
| 1776 | return NULL; |
|---|
| 1777 | } |
|---|
| 1778 | play_pid->ref_cnt++; |
|---|
| 1779 | goto done; |
|---|
| 1780 | } |
|---|
| 1781 | } |
|---|
| 1782 | /* else, allow the new NEXUS_PidChannelHandle to be opened, even if a NEXUS_PidChannelHandle already exists for this pid on a different pidChannelIndex. |
|---|
| 1783 | This is needed to support playpump multiplexing. */ |
|---|
| 1784 | } |
|---|
| 1785 | else { |
|---|
| 1786 | for(play_pid=BLST_S_FIRST(&p->pid_list); play_pid; play_pid=BLST_S_NEXT(play_pid, link)) { |
|---|
| 1787 | if(play_pid->pid == pid) { |
|---|
| 1788 | BDBG_MSG(("NEXUS_Playpump_OpenPidChannel: %#lx detected duplicated pid %u (%#lx:%u)", (unsigned long)p, (unsigned)pid, (unsigned long)play_pid, play_pid->ref_cnt)); |
|---|
| 1789 | if(BKNI_Memcmp(pSettings, &play_pid->settings, sizeof(*pSettings))!=0) { |
|---|
| 1790 | BDBG_WRN(("NEXUS_Playpump_OpenPidChannel: %#lx detected duplicated pid %u (%#lx:%u) with non-compatible settings", (unsigned long)p, (unsigned)pid, (unsigned long)play_pid, play_pid->ref_cnt)); |
|---|
| 1791 | } |
|---|
| 1792 | play_pid->ref_cnt++; |
|---|
| 1793 | goto done; |
|---|
| 1794 | } |
|---|
| 1795 | } |
|---|
| 1796 | } |
|---|
| 1797 | |
|---|
| 1798 | play_pid = BKNI_Malloc(sizeof(*play_pid)); |
|---|
| 1799 | if(!play_pid) { rc = BERR_TRACE(BERR_OUT_OF_SYSTEM_MEMORY); goto err_alloc;} |
|---|
| 1800 | transportType = p->settings.transportType; |
|---|
| 1801 | play_pid->pid = pid; |
|---|
| 1802 | play_pid->ref_cnt = 1; |
|---|
| 1803 | play_pid->settings = *pSettings; |
|---|
| 1804 | #if B_HAS_MEDIA |
|---|
| 1805 | if(p->use_media) { |
|---|
| 1806 | transportType = NEXUS_TransportType_eMpeg2Pes; |
|---|
| 1807 | rc = b_pump_demux_open_pid(p->demux, play_pid, pid, pSettings); |
|---|
| 1808 | if(rc!=NEXUS_SUCCESS) { |
|---|
| 1809 | goto err_media_open; |
|---|
| 1810 | } |
|---|
| 1811 | pid = play_pid->media_pid; |
|---|
| 1812 | if (p->state.running) { |
|---|
| 1813 | rc = b_pump_demux_add_pid(p->demux, play_pid); |
|---|
| 1814 | if(rc!=NEXUS_SUCCESS) { |
|---|
| 1815 | goto err_media_add; |
|---|
| 1816 | } |
|---|
| 1817 | } |
|---|
| 1818 | } |
|---|
| 1819 | #endif |
|---|
| 1820 | rc = NEXUS_Playpump_P_OpenPid(p, play_pid, pid, transportType, |
|---|
| 1821 | p->settings.originalTransportType==NEXUS_TransportType_eUnknown?p->settings.transportType:p->settings.originalTransportType, |
|---|
| 1822 | pSettings, forcedPacketizerPid, packetizerPid); |
|---|
| 1823 | if (rc) { rc = BERR_TRACE(rc); goto err_pid_channel;} |
|---|
| 1824 | BLST_S_DICT_ADD(&p->pid_list, play_pid, NEXUS_P_PlaypumpPidChannel, pid_channel, link, err_duplicate); |
|---|
| 1825 | |
|---|
| 1826 | done: |
|---|
| 1827 | return play_pid->pid_channel; |
|---|
| 1828 | |
|---|
| 1829 | err_duplicate: |
|---|
| 1830 | BDBG_ERR(("NEXUS_Playpump_OpenPidChannel: %#lx detected duplicate pid %#lx", (unsigned long)p, (unsigned long)play_pid->pid_channel)); |
|---|
| 1831 | err_pid_channel: |
|---|
| 1832 | #if B_HAS_MEDIA |
|---|
| 1833 | if(p->use_media && p->state.running) { |
|---|
| 1834 | b_pump_demux_remove_pid(p->demux, play_pid); |
|---|
| 1835 | } |
|---|
| 1836 | err_media_add: |
|---|
| 1837 | if(p->use_media) { |
|---|
| 1838 | b_pump_demux_close_pid(p->demux, play_pid); |
|---|
| 1839 | } |
|---|
| 1840 | err_media_open: |
|---|
| 1841 | #endif |
|---|
| 1842 | BKNI_Free(play_pid); |
|---|
| 1843 | err_alloc: |
|---|
| 1844 | return NULL; |
|---|
| 1845 | } |
|---|
| 1846 | |
|---|
| 1847 | NEXUS_PidChannelHandle |
|---|
| 1848 | NEXUS_Playpump_OpenPidChannel(NEXUS_PlaypumpHandle p, unsigned pid, const NEXUS_PlaypumpOpenPidChannelSettings *pSettings) |
|---|
| 1849 | { |
|---|
| 1850 | return NEXUS_Playpump_P_OpenPidChannel_MuxImpl(p, pid, pSettings, false, 0); |
|---|
| 1851 | } |
|---|
| 1852 | |
|---|
| 1853 | NEXUS_PidChannelHandle |
|---|
| 1854 | NEXUS_Playpump_OpenPidChannel_priv( NEXUS_PlaypumpHandle p, uint16_t src_pid, uint16_t dst_pid, const NEXUS_PlaypumpOpenPidChannelSettings *pSettings ) |
|---|
| 1855 | { |
|---|
| 1856 | NEXUS_ASSERT_MODULE(); |
|---|
| 1857 | return NEXUS_Playpump_P_OpenPidChannel_MuxImpl(p, src_pid, pSettings, true, dst_pid); |
|---|
| 1858 | } |
|---|
| 1859 | |
|---|
| 1860 | NEXUS_Error |
|---|
| 1861 | NEXUS_Playpump_ClosePidChannel(NEXUS_PlaypumpHandle p, NEXUS_PidChannelHandle pidChannel) |
|---|
| 1862 | { |
|---|
| 1863 | NEXUS_Error rc; |
|---|
| 1864 | NEXUS_P_PlaypumpPidChannel *play_pid; |
|---|
| 1865 | |
|---|
| 1866 | BDBG_OBJECT_ASSERT(p, NEXUS_Playpump); |
|---|
| 1867 | BLST_S_DICT_FIND(&p->pid_list, play_pid, pidChannel, pid_channel, link); |
|---|
| 1868 | if(play_pid==NULL) { |
|---|
| 1869 | BDBG_WRN(("NEXUS_Playpump_ClosePidChannel: %#lx can't find pid:%#lx", (unsigned long)p, (unsigned long)pidChannel)); |
|---|
| 1870 | rc = BERR_TRACE(NEXUS_INVALID_PARAMETER); |
|---|
| 1871 | goto err_not_found; |
|---|
| 1872 | } |
|---|
| 1873 | BDBG_ASSERT(play_pid->ref_cnt>0); |
|---|
| 1874 | play_pid->ref_cnt--; |
|---|
| 1875 | if(play_pid->ref_cnt==0) { |
|---|
| 1876 | BLST_S_DICT_REMOVE(&p->pid_list, play_pid, pidChannel, NEXUS_P_PlaypumpPidChannel, pid_channel, link); |
|---|
| 1877 | BDBG_ASSERT(play_pid); |
|---|
| 1878 | NEXUS_Playpump_P_ClosePid(p, play_pid); |
|---|
| 1879 | BKNI_Free(play_pid); |
|---|
| 1880 | } |
|---|
| 1881 | return NEXUS_SUCCESS; |
|---|
| 1882 | |
|---|
| 1883 | err_not_found: |
|---|
| 1884 | return rc; |
|---|
| 1885 | } |
|---|
| 1886 | |
|---|
| 1887 | void |
|---|
| 1888 | NEXUS_Playpump_CloseAllPidChannels(NEXUS_PlaypumpHandle p) |
|---|
| 1889 | { |
|---|
| 1890 | NEXUS_P_PlaypumpPidChannel *play_pid; |
|---|
| 1891 | BDBG_OBJECT_ASSERT(p, NEXUS_Playpump); |
|---|
| 1892 | while(NULL!=(play_pid=BLST_S_FIRST(&p->pid_list))) { |
|---|
| 1893 | nexus_unregister_NEXUS_PidChannelHandle(nexus_transport_client(), play_pid->pid_channel, false); |
|---|
| 1894 | NEXUS_Playpump_ClosePidChannel(p, play_pid->pid_channel); |
|---|
| 1895 | } |
|---|
| 1896 | return; |
|---|
| 1897 | } |
|---|
| 1898 | |
|---|
| 1899 | /* This function was added for low-level control required for IP STB flow control. */ |
|---|
| 1900 | NEXUS_Error NEXUS_Playpump_SetPause( NEXUS_PlaypumpHandle p, bool paused ) |
|---|
| 1901 | { |
|---|
| 1902 | BERR_Code rc; |
|---|
| 1903 | if (paused) { |
|---|
| 1904 | rc = BXPT_Playback_Pause(p->xpt_play); |
|---|
| 1905 | if (rc) return BERR_TRACE(rc); |
|---|
| 1906 | } |
|---|
| 1907 | else { |
|---|
| 1908 | rc = BXPT_Playback_Resume(p->xpt_play); |
|---|
| 1909 | if (rc) return BERR_TRACE(rc); |
|---|
| 1910 | } |
|---|
| 1911 | p->paused = paused; |
|---|
| 1912 | return 0; |
|---|
| 1913 | } |
|---|
| 1914 | |
|---|
| 1915 | NEXUS_Error NEXUS_Playpump_SuspendPacing( NEXUS_PlaypumpHandle p, bool suspended ) |
|---|
| 1916 | { |
|---|
| 1917 | BERR_Code rc; |
|---|
| 1918 | rc = BXPT_Playback_ConfigPacing(p->xpt_play, suspended?BXPT_PacingControl_eStop:BXPT_PacingControl_eStart); |
|---|
| 1919 | if (rc) return BERR_TRACE(rc); |
|---|
| 1920 | return 0; |
|---|
| 1921 | } |
|---|
| 1922 | |
|---|
| 1923 | static void NEXUS_Playpump_P_PacingErr_isr( void *playpump, int param2 ) |
|---|
| 1924 | { |
|---|
| 1925 | NEXUS_PlaypumpHandle p = (NEXUS_PlaypumpHandle)playpump; |
|---|
| 1926 | BSTD_UNUSED(param2); |
|---|
| 1927 | p->state.pacingTsRangeError++; |
|---|
| 1928 | return; |
|---|
| 1929 | } |
|---|
| 1930 | |
|---|
| 1931 | static void NEXUS_Playpump_P_InstallRangeErrIntHandler(NEXUS_PlaypumpHandle p) |
|---|
| 1932 | { |
|---|
| 1933 | BERR_Code rc; |
|---|
| 1934 | rc = BINT_CreateCallback(&p->pacingErrIntCallback, g_pCoreHandles->bint, BXPT_Playback_GetIntId(p->xpt_play, BXPT_PbInt_eTsRangeErr), |
|---|
| 1935 | NEXUS_Playpump_P_PacingErr_isr, ( void * ) p, 0 ); |
|---|
| 1936 | if (!rc) { |
|---|
| 1937 | rc = BINT_EnableCallback(p->pacingErrIntCallback); |
|---|
| 1938 | } |
|---|
| 1939 | if (rc) {rc = BERR_TRACE(rc);} |
|---|
| 1940 | } |
|---|
| 1941 | |
|---|
| 1942 | static void NEXUS_Playpump_P_UninstallRangeErrIntHandler(NEXUS_PlaypumpHandle p) |
|---|
| 1943 | { |
|---|
| 1944 | (void)BINT_DestroyCallback(p->pacingErrIntCallback); |
|---|
| 1945 | } |
|---|
| 1946 | |
|---|
| 1947 | #if NEXUS_PARSER_BAND_CC_CHECK |
|---|
| 1948 | void NEXUS_Playpump_P_CCError_isr(void *context, int param) |
|---|
| 1949 | { |
|---|
| 1950 | NEXUS_PlaypumpHandle p = context; |
|---|
| 1951 | BSTD_UNUSED(param); |
|---|
| 1952 | NEXUS_ParserBand_P_CountCcErrors_isr(); |
|---|
| 1953 | NEXUS_IsrCallback_Fire_isr(p->ccErrorCallback); |
|---|
| 1954 | } |
|---|
| 1955 | #endif |
|---|
| 1956 | |
|---|
| 1957 | void NEXUS_Playpump_P_TeiError_isr(void *context, int param) |
|---|
| 1958 | { |
|---|
| 1959 | NEXUS_PlaypumpHandle p = context; |
|---|
| 1960 | BSTD_UNUSED(param); |
|---|
| 1961 | NEXUS_IsrCallback_Fire_isr(p->teiErrorCallback); |
|---|
| 1962 | } |
|---|
| 1963 | |
|---|
| 1964 | static NEXUS_Error NEXUS_Playpump_P_SetInterrupts(NEXUS_PlaypumpHandle p, const NEXUS_PlaypumpSettings *pSettings) |
|---|
| 1965 | { |
|---|
| 1966 | BERR_Code rc; |
|---|
| 1967 | |
|---|
| 1968 | /* only enable certain interrupts when their callbacks are desired. this helps typical system performance. */ |
|---|
| 1969 | #if NEXUS_PARSER_BAND_CC_CHECK |
|---|
| 1970 | if (pSettings->ccError.callback) { |
|---|
| 1971 | if (!p->ccErrorInt) { |
|---|
| 1972 | BDBG_MSG(("create playpump %d cc callback", p->index)); |
|---|
| 1973 | rc = BINT_CreateCallback(&p->ccErrorInt, g_pCoreHandles->bint, |
|---|
| 1974 | BXPT_Playback_GetIntId(p->xpt_play, BCHP_XPT_PB0_INTR_PARSER_CONTINUITY_ERROR_SHIFT), |
|---|
| 1975 | NEXUS_Playpump_P_CCError_isr, p, 0); |
|---|
| 1976 | if (rc) return BERR_TRACE(rc); |
|---|
| 1977 | rc = BINT_EnableCallback(p->ccErrorInt); |
|---|
| 1978 | if (rc) return BERR_TRACE(rc); |
|---|
| 1979 | } |
|---|
| 1980 | } |
|---|
| 1981 | else if (p->ccErrorInt) { |
|---|
| 1982 | (void)BINT_DestroyCallback(p->ccErrorInt); |
|---|
| 1983 | p->ccErrorInt = NULL; |
|---|
| 1984 | } |
|---|
| 1985 | #endif |
|---|
| 1986 | |
|---|
| 1987 | /* only enable certain interrupts when their callbacks are desired. this helps typical system performance. */ |
|---|
| 1988 | if (pSettings->teiError.callback) { |
|---|
| 1989 | if (!p->teiErrorInt) { |
|---|
| 1990 | BDBG_MSG(("create playpump %d tei callback", p->index)); |
|---|
| 1991 | rc = BINT_CreateCallback(&p->teiErrorInt, g_pCoreHandles->bint, |
|---|
| 1992 | BXPT_Playback_GetIntId(p->xpt_play, BCHP_XPT_PB0_INTR_PARSER_TRANSPORT_ERROR_SHIFT), |
|---|
| 1993 | NEXUS_Playpump_P_TeiError_isr, p, 0); |
|---|
| 1994 | if (rc) return BERR_TRACE(rc); |
|---|
| 1995 | rc = BINT_EnableCallback(p->teiErrorInt); |
|---|
| 1996 | if (rc) return BERR_TRACE(rc); |
|---|
| 1997 | } |
|---|
| 1998 | } |
|---|
| 1999 | else if (p->teiErrorInt) { |
|---|
| 2000 | (void)BINT_DestroyCallback(p->teiErrorInt); |
|---|
| 2001 | p->teiErrorInt = NULL; |
|---|
| 2002 | } |
|---|
| 2003 | |
|---|
| 2004 | NEXUS_IsrCallback_Set(p->ccErrorCallback, &pSettings->ccError); |
|---|
| 2005 | NEXUS_IsrCallback_Set(p->teiErrorCallback, &pSettings->teiError); |
|---|
| 2006 | |
|---|
| 2007 | return 0; |
|---|
| 2008 | } |
|---|
| 2009 | |
|---|
| 2010 | NEXUS_Error NEXUS_Playpump_GetAllPassPidChannelIndex( |
|---|
| 2011 | NEXUS_PlaypumpHandle playpump, |
|---|
| 2012 | unsigned *pHwPidChannel |
|---|
| 2013 | ) |
|---|
| 2014 | { |
|---|
| 2015 | BDBG_OBJECT_ASSERT(playpump, NEXUS_Playpump); |
|---|
| 2016 | BDBG_ASSERT(pHwPidChannel); |
|---|
| 2017 | |
|---|
| 2018 | *pHwPidChannel = BXPT_GET_PLAYBACK_ALLPASS_CHNL( playpump->index ); |
|---|
| 2019 | return 0; |
|---|
| 2020 | } |
|---|
| 2021 | |
|---|