source: svn/newcon3bcm2_21bu/nexus/utils/playback.c

Last change on this file was 76, checked in by megakiss, 10 years ago

1W 대기전력을 만족시키기 위하여 POWEROFF시 튜너를 Standby 상태로 함

  • Property svn:executable set to *
File size: 60.5 KB
Line 
1/******************************************************************************
2 *    (c)2008-2012 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: playback.c $
39 * $brcm_Revision: 82 $
40 * $brcm_Date: 2/22/12 1:52p $
41 *
42 * Module Description:
43 *
44 * Revision History:
45 *
46 * $brcm_Log: /nexus/utils/playback.c $
47 *
48 * 82   2/22/12 1:52p vsilyaev
49 * SW7425-2258: Improved handling of MJPEG decoders
50 *
51 * 81   2/21/12 12:21p erickson
52 * SW7208-183: can't call cmdline_probe until after NEXUS_Platform_Init
53 *  because it calls thunked core module functions
54 *
55 * 80   2/14/12 12:32p erickson
56 * SW7425-2282: seek now fails if out of bounds
57 *
58 * 79   1/31/12 5:07p rjlewis
59 * SW7425-1136: Added HDMI support (and some cleanup).
60 *
61 * 78   1/26/12 1:32p erickson
62 * SW7425-2250: print hex PTS/STC values, add audio/video queue depth to
63 *  status
64 *
65 * 77   1/19/12 11:52a erickson
66 * SW7346-629: add -cmp_crc and -avd_crc options
67 *
68 * 76   1/11/12 6:13p vsilyaev
69 * SW7425-2112: Added option to limit playback rate
70 *
71 * 75   1/10/12 11:11a jgarrett
72 * SW7231-524: Fixing multichannel audio playback
73 *
74 * 74   11/9/11 5:10p erickson
75 * SW7405-5317: add host(bcm,X)
76 *
77 * 73   11/9/11 2:14p erickson
78 * SW7335-1368: avoid round to zero, clarify 3rd param of host() is
79 *  slowmotion rate, not overall rate
80 *
81 * 72   10/19/11 3:52p erickson
82 * SW7335-1368: don't allow non-zero rate to round down to zero (pause)
83 *
84 * 71   10/12/11 11:44a erickson
85 * SW7425-1264: don't abs rate
86 *
87 * 70   8/29/11 10:32a erickson
88 * SW7425-1205: add host(gop,X) option
89 *
90 * 69   7/13/11 8:39p vsilyaev
91 * SWDTV-7897: Added code to wrap PCM file with the WAV header
92 *
93 * 68   7/7/11 5:53p jtna
94 * SW7425-869: added runtime option to override
95 *  NEXUS_VideoDecoderSourceOrientation
96 *
97 * 67   5/13/11 12:17p erickson
98 * SW7420-1873: remove shutdown attribute
99 *
100 * 66   5/11/11 12:49p erickson
101 * SW7405-5317: add host trick mode command
102 *
103 * 65   4/22/11 5:49p vsilyaev
104 * SW7425-416: Added option to override display orientation
105 *
106 * 64   3/23/11 5:41p vsilyaev
107 * SW7422-406: Unified parsing of command line parameters
108 *
109 * 63   3/23/11 2:48p vsilyaev
110 * SW7422-14: Added status for the enhanced layer FIFO
111 *
112 * 62   3/15/11 2:15p erickson
113 * SW7346-101: fix dss playback
114 *
115 * 61   3/11/11 3:35p vsilyaev
116 * SW7422-14: Added support for decoding SVC/MVC streams
117 *
118 * 60   3/4/11 3:18p jgarrett
119 * SW7422-146: Adding multichannel audio support
120 *
121 * 59   1/7/11 3:31p jtna
122 * SW7422-165: use NEXUS_VideoDecoderStatus.ptsStcDifference to calculate
123 *  PTS - STC difference
124 *
125 * 58   11/23/10 8:39p vsilyaev
126 * SW35230-2195: Added compile time option to capture and restore stream
127 *  data with relative timing
128 *
129 * 57   11/17/10 3:58p jgarrett
130 * SW7408-137: Adding HDMI output
131 *
132 * 56   10/27/10 3:26p erickson
133 * SW7422-69: fix dtv
134 *
135 * 55   10/22/10 12:17p vsilyaev
136 * SW3548-3106: Added option to start playback in a paused state
137 *
138 * 54   10/5/10 10:41a erickson
139 * SW7422-65: add index
140 *
141 * 53   9/8/10 12:06p vsilyaev
142 * SW7468-129: Added video decoder on ZSP
143 *
144 * 52   8/31/10 2:44p erickson
145 * SWGIGGSVIZIO-57: add -fixed_bitrate option to set
146 *  NEXUS_PlaybackMode_eFixedBitrate
147 *
148 * 51   8/9/10 6:48a erickson
149 * SW7420-933: don't assert for fast or reverse trick modes
150 *
151 * 50   7/14/10 6:12p vsilyaev
152 * SW3556-1131: Added basic support for CDXA format
153 *
154 * 49   6/18/10 4:38p vsilyaev
155 * SW3548-2988: Don't open pidChannel if pid is 0
156 *
157 * 48   6/1/10 3:56p erickson
158 * SW3548-2962: add runtime bvn_usage(ID) command
159 *
160 * 47   5/10/10 12:59p vsilyaev
161 * SW3548-2920: Added printout for End Of Stream
162 *
163 * 46   5/5/10 10:43a vsilyaev
164 * SW7405-1260: Added settings for size of the audio decoder buffer
165 *
166 * 45   2/23/10 4:50p vsilyaev
167 * SW3556-913: Added code that monitors state of the playback file and
168 *  restarts playback (from last good position) in case of error
169 *
170 * 44   2/22/10 5:33p vsilyaev
171 * SW3556-913: Added option to plug  Custom File I/O routines to inject
172 *  errors
173 *
174 * 43   2/18/10 6:00p vsilyaev
175 * SW3556-913: Added command to restart playback
176 *
177 * 42   2/12/10 5:56p jtna
178 * SW3556-1051: added option to control playback timestamp reordering
179 *
180 * 41   12/30/09 3:19p vsilyaev
181 * SW7408-17: Added options to select PCM and compressed audio outputs
182 *
183 * 40   12/30/09 2:13p erickson
184 * SW7550-128: add closed caption feature (-cc on)
185 *
186 * 39   11/25/09 5:24p katrep
187 * SW7405-2740: Add support for WMA pro drc
188 *
189 * 38   11/20/09 3:54p erickson
190 * SW7405-3260: remove unused #include nexus_astm.h
191 *
192 * 37   10/20/09 4:32p erickson
193 * SW7405-3260: allow trick modes on streams where video/audio pid == 0.
194 *  this is normal for AVI/ASF stream ids.
195 *
196 * 36   10/19/09 11:24a gmohile
197 * SW7405-3209 : Add support for streams where pcr pid is different from
198 *  video pid
199 *
200 * 35   8/18/09 4:36p vsilyaev
201 * PR 56809: Added option to control handling of video errors
202 *
203 * 34   7/21/09 5:57p vsilyaev
204 * PR 56977: Nexus playback always control audio and video decoder.
205 *  Provided way for the user to control the decoder slowmotion factor
206 *  using the playback trick API.
207 *
208 * 33   7/15/09 7:27p vsilyaev
209 * PR 55653: Added WAV format
210 *
211 * 32   6/22/09 5:26p jtna
212 * PR55571: vdecoder trick modes require adecoder to be stopped
213 *
214 * 31   6/19/09 5:20p vsilyaev
215 * PR 56169: Added option to set max decode rate
216 *
217 * 30   6/8/09 7:06a erickson
218 * PR55617: add user-specific aspectRatio
219 *
220 * 29   5/22/09 6:28p vsilyaev
221 * PR 55376 PR 52344: Use custom heap configuration when enabled
222 *  AVC(H.264) Level 5.1 decoding
223 *
224 * 28   5/22/09 5:21p vsilyaev
225 * PR 55376 PR 52344: Added option to enable processing of AVC(H.264)
226 *  Level 5.1 video
227 *
228 * 27   5/15/09 1:23p vsilyaev
229 * PR 55193: Updated way on how we report status
230 *
231 * 26   5/15/09 12:48p vsilyaev
232 * PR 55193: Added function to return last parsed PTS by the media library
233 *
234 * 25   3/27/09 12:51p vsilyaev
235 * PR 50311: Return readPosition in the Nexus playback status. In
236 *  combination with the position it could be used to measure depth of
237 *  decoder and playback buffers in units of time.
238 *
239 * 24   3/18/09 10:26a erickson
240 * PR52350: add wxga/fha support with 50/60 hz option
241 *
242 * 23   3/6/09 3:38p vsilyaev
243 * PR 52831: Added shutdown code
244 *
245 * 22   3/6/09 9:33a erickson
246 * PR51743: added -ar and -graphics options, default DTV apps to panel
247 *  output
248 *
249 * 21   2/27/09 5:05p vsilyaev
250 * PR 52634: Added code to handle MPEG-2 TS streams with timesampts (e.g.
251 *  192 byte packets)
252 *
253 * 20   2/20/09 2:06p vsilyaev
254 * PR 51467: Added option to set size of the video decoder buffer
255 *
256 * 19   2/5/09 2:12p erickson
257 * PR51151: update
258 *
259 * 18   1/26/09 1:15p vsilyaev
260 * PR 51351: Added option to seek using minutes and seconds
261 *
262 * 17   1/26/09 11:26a vsilyaev
263 * PR 51579: Added stream_processing and auto_bitrate options
264 *
265 * 16   1/23/09 5:12p erickson
266 * PR48944: update
267 *
268 * 15   1/22/09 7:48p vsilyaev
269 * PR 50848: Don't use globals for the command line options
270 *
271 * 14   1/20/09 4:28p erickson
272 * PR48944: add -mad and -display_format options
273 *
274 * 13   1/8/09 10:48p erickson
275 * PR50861: added avdStatusBlock
276 *
277 * 12   1/8/09 10:34p erickson
278 * PR48944: add more options
279 *
280 * 11   1/8/09 9:36p erickson
281 * PR50757: added NEXUS_VideoFrameRate support, both as a start setting
282 *  and status
283 *
284 * 10   1/7/09 9:50p erickson
285 * PR50763: fix segfault
286 *
287 * 9   1/6/09 1:11a erickson
288 * PR50763: added sleep and ; delimiter
289 *
290 * 8   1/6/09 12:45a erickson
291 * PR50763: added -bof, -eof options. added playback position to status.
292 *  fix mkv, mp4.
293 *
294 * 7   1/5/09 12:49p erickson
295 * PR50763: update for mkv testing
296 *
297 * 6   12/11/08 3:25p erickson
298 * PR48944: fix playback index support
299 *
300 * 5   12/3/08 3:55p erickson
301 * PR48944: update
302 *
303 * 4   11/26/08 8:52a erickson
304 * PR48944: more status
305 *
306 * 3   11/19/08 1:30p erickson
307 * PR48944: update
308 *
309 * 2   11/17/08 2:19p erickson
310 * PR48944: update
311 *
312 * 1   11/17/08 12:34p erickson
313 * PR48944: add utils
314 *
315 *****************************************************************************/
316
317#include "nexus_platform.h"
318#include "nexus_core_utils.h"
319#include "nexus_video_decoder.h"
320#include "nexus_video_decoder_trick.h"
321#include "nexus_video_decoder_extra.h"
322#include "nexus_video_adj.h"
323#include "nexus_stc_channel.h"
324#include "nexus_display.h"
325#include "nexus_display_vbi.h"
326#include "nexus_video_window.h"
327#include "nexus_video_input.h"
328#include "nexus_audio_dac.h"
329#include "nexus_audio_decoder.h"
330#include "nexus_audio_decoder_trick.h"
331#include "nexus_audio_output.h"
332#include "nexus_audio_input.h"
333#include "nexus_audio_playback.h"
334#include "nexus_spdif_output.h"
335#include "nexus_composite_output.h"
336#include "nexus_component_output.h"
337#if NEXUS_HAS_HDMI_OUTPUT
338#include "nexus_hdmi_output.h"
339#endif
340#include "nexus_surface.h"
341#if NEXUS_HAS_PLAYBACK
342#include "nexus_playback.h"
343#include "nexus_file.h"
344#endif
345#include "cmdline_args.h"
346
347#include <stdio.h>
348#include <string.h>
349#include <assert.h>
350#include <stdlib.h>
351#include "bstd.h"
352#include "bkni.h"
353#include "fileio_custom.h"
354#include "bmedia_cdxa.h"
355#include "nexus_file_pvr.h"
356
357BDBG_MODULE(playback);
358
359#if !NEXUS_HAS_PLAYBACK
360int main(void)
361{
362    printf("This application is not supported on this platform (needs Playback)!\n");
363    return 0;
364}
365#else
366
367static void print_cmp_crc(NEXUS_DisplayHandle display);
368static void print_avd_crc(NEXUS_VideoDecoderHandle videoDecoder);
369
370/* this should be enabled with conjunction of enabling  READ_TIMED_DATA in BSEAV/lib/utils/bsink_playback.c */
371/* #define READ_TIMED_DATA 1 */
372
373#if READ_TIMED_DATA
374#include "nexus_memory.h"
375#include "barena.h"
376static void *b_nexus_alloc(balloc_iface_t alloc, size_t size)
377{
378    NEXUS_Error rc;
379    void *b;
380    BSTD_UNUSED(alloc);
381    rc = NEXUS_Memory_Allocate(size, NULL, &b);
382    if(rc==NEXUS_SUCCESS) {return b;}
383    else {return NULL;}
384}
385
386static void b_nexus_free(balloc_iface_t alloc, void *ptr)
387{
388    BSTD_UNUSED(alloc);
389    NEXUS_Memory_Free(ptr);
390}
391
392static const struct balloc_iface b_nexus_alloc_iface = {
393    b_nexus_alloc, b_nexus_free
394};
395
396extern balloc_iface_t bsink_dump_reader_allocator;
397#endif /* READ_TIMED_DATA */
398
399
400static void start_video(const struct util_opts_t *opts, NEXUS_VideoDecoderHandle videoDecoder, const NEXUS_VideoDecoderStartSettings *videoProgram)
401{
402    NEXUS_Error rc;
403    if (opts->common.videoPid) {
404        rc = NEXUS_VideoDecoder_Start(videoDecoder, videoProgram);
405        if(rc!=NEXUS_SUCCESS) {
406            bool supported=true;
407            NEXUS_VideoDecoder_IsCodecSupported(videoDecoder, videoProgram->codec, &supported);
408            if(!supported) {
409                unsigned i;
410                bool found_supported=false;
411                unsigned num_decoders = NEXUS_NUM_VIDEO_DECODERS;
412
413                BDBG_LOG(("VideoDecoder:%u doesn't support codec %u", opts->common.videoDecoder, videoProgram->codec));
414#if NEXUS_NUM_DSP_VIDEO_DECODERS
415                num_decoders += NEXUS_NUM_DSP_VIDEO_DECODERS;
416#endif
417
418#if NEXUS_NUM_SID_VIDEO_DECODERS
419                num_decoders += NEXUS_NUM_SID_VIDEO_DECODERS;
420#endif
421
422                for(i=0;i<num_decoders;i++) {
423                    NEXUS_VideoDecoderHandle decoder;
424                    if(i==opts->common.videoDecoder) {
425                        continue;
426                    }
427                    decoder = NEXUS_VideoDecoder_Open(i, NULL);
428                    if(decoder) {
429                        NEXUS_VideoDecoder_IsCodecSupported(decoder, videoProgram->codec, &supported);
430                        if(supported) {
431                            if(!found_supported) {
432                                found_supported = true;
433                                BDBG_LOG(("try to run with the '-video_decoder n' option, where 'n' is the index of the video decoder that supports codec %u", videoProgram->codec));
434                            }
435                            BDBG_LOG(("VideoDecoder:%u supports codec %u", i, videoProgram->codec));
436                        }
437                        NEXUS_VideoDecoder_Close(decoder);
438                    }
439                }
440            }
441            BDBG_ASSERT(false);
442        }
443    }
444    return;
445}
446static void stop_video(const struct util_opts_t *opts, NEXUS_VideoDecoderHandle videoDecoder)
447{
448    if (opts->common.videoPid) {
449        NEXUS_VideoDecoder_Stop(videoDecoder);
450    }
451    return;
452}
453
454static void start_audio(const struct util_opts_t *opts, NEXUS_AudioDecoderHandle audioDecoder, NEXUS_AudioDecoderHandle compressedDecoder, const NEXUS_AudioDecoderStartSettings *audioProgram)
455{
456    NEXUS_Error rc;
457    if (opts->common.audioPid) {
458#if B_HAS_ASF
459        /* if DRC for WMA pro is available apply now */
460        if(audioProgram->codec == NEXUS_AudioCodec_eWmaPro && opts->common.dynamicRangeControlValid ){
461
462            NEXUS_AudioDecoderCodecSettings codecSettings;
463
464            BDBG_WRN(("wma-pro drc enabled,ref peak %d,ref target %d,ave peak %d, ave target %d",
465                      opts->common.dynamicRangeControl.peakReference,opts->common.dynamicRangeControl.peakTarget,
466                      opts->common.dynamicRangeControl.averageReference,opts->common.dynamicRangeControl.averageTarget));
467            NEXUS_AudioDecoder_GetCodecSettings(audioDecoder, audioProgram->codec, &codecSettings);
468            codecSettings.codec = audioProgram->codec;
469            codecSettings.codecSettings.wmaPro.dynamicRangeControlValid = true;
470            codecSettings.codecSettings.wmaPro.dynamicRangeControl.peakReference = opts->common.dynamicRangeControl.peakReference;
471            codecSettings.codecSettings.wmaPro.dynamicRangeControl.peakTarget = opts->common.dynamicRangeControl.peakTarget;
472            codecSettings.codecSettings.wmaPro.dynamicRangeControl.averageReference = opts->common.dynamicRangeControl.averageReference;
473            codecSettings.codecSettings.wmaPro.dynamicRangeControl.averageTarget = opts->common.dynamicRangeControl.averageTarget;
474            NEXUS_AudioDecoder_SetCodecSettings(audioDecoder,&codecSettings);
475            }
476#endif
477
478        if(opts->common.decodedAudio) {
479            rc = NEXUS_AudioDecoder_Start(audioDecoder, audioProgram);
480            BDBG_ASSERT(!rc);
481        }
482        if(compressedDecoder) {
483            rc = NEXUS_AudioDecoder_Start(compressedDecoder, audioProgram);
484            /* This may fail in some cases because we haven't atached any outputs.  Don't assert. */
485            /*BDBG_ASSERT(!rc);*/
486        }
487    }
488    return;
489}
490
491static void stop_audio(const struct util_opts_t *opts, NEXUS_AudioDecoderHandle audioDecoder, NEXUS_AudioDecoderHandle compressedDecoder)
492{
493    if (opts->common.audioPid) {
494        if(opts->common.decodedAudio) {
495            NEXUS_AudioDecoder_Stop(audioDecoder);
496        }
497        if(compressedDecoder) {
498            NEXUS_AudioDecoder_Stop(compressedDecoder);
499        }
500    }
501    return;
502}
503
504#define  B_HAS_PLAYBACK_MONITOR 0
505#if B_HAS_PLAYBACK_MONITOR
506#include <pthread.h>
507#include "bkni_multi.h"
508
509typedef struct PlaybackMonitorState {
510    bool terminate;
511    pthread_t thread;
512    BKNI_MutexHandle lock;
513    const struct util_opts_t *opts;
514    NEXUS_PlaybackHandle playback;
515    NEXUS_VideoDecoderHandle videoDecoder;
516    const NEXUS_VideoDecoderStartSettings *videoProgram;
517    NEXUS_AudioDecoderHandle audioDecoder;
518    NEXUS_AudioDecoderHandle compressedDecoder;
519    const NEXUS_AudioDecoderStartSettings *audioProgram;
520    NEXUS_FilePlayHandle file;
521    NEXUS_FilePlayHandle customFile;
522    NEXUS_FilePlayHandle stickyFile;
523    const NEXUS_PlaybackStartSettings *playbackStartSettings;
524} PlaybackMonitorState;
525
526static void *
527monitor_thread(void *state_)
528{
529    const PlaybackMonitorState *state=state_;
530    while(!state->terminate) {
531        NEXUS_PlaybackStatus status;
532        NEXUS_PlaybackSettings playbackSettings;
533        NEXUS_VideoDecoderSettings videoDecoderSettings;
534        BERR_Code rc;
535        bool failed;
536
537        rc = NEXUS_Playback_GetStatus(state->playback, &status);
538        BDBG_ASSERT(!rc);
539        BKNI_Sleep(1000);
540        FileIoSticky_GetFailBit(state->stickyFile, &failed);
541        if(!failed) {
542            continue;
543        }
544
545        BDBG_WRN(("restarting from %u", status.position));
546        BKNI_AcquireMutex(state->lock);
547        NEXUS_Playback_Stop(state->playback);
548        FileIoSticky_ClearFailBit(state->stickyFile);
549        if(state->customFile) {
550            FileIoCustomProbabilities probabilities;
551            FileIoCustom_GetProbabilities(state->customFile, NULL, &probabilities);
552            probabilities.error = 0;
553            probabilities.nodata = 0;
554            probabilities.partial_read = 0;
555            FileIoCustom_SetProbabilities(state->customFile, &probabilities, &probabilities);
556        }
557
558        if (state->opts->videoPid) {
559            /* don't show black frame */
560            NEXUS_VideoDecoder_GetSettings(state->videoDecoder, &videoDecoderSettings);
561            videoDecoderSettings.channelChangeMode = NEXUS_VideoDecoder_ChannelChangeMode_eHoldUntilTsmLock;
562            rc=NEXUS_VideoDecoder_SetSettings(state->videoDecoder, &videoDecoderSettings);
563            BDBG_ASSERT(!rc);
564        }
565        /* stop decoder */
566        stop_video(state->opts, state->videoDecoder);
567        stop_audio(state->opts, state->audioDecoder, state->compressedDecoder);
568
569        NEXUS_Playback_GetSettings(state->playback, &playbackSettings);
570        playbackSettings.startPaused = true;
571        rc = NEXUS_Playback_SetSettings(state->playback, &playbackSettings);
572        BDBG_ASSERT(!rc);
573
574        /* Start decoders */
575        start_video(state->opts, state->videoDecoder, state->videoProgram);
576        start_audio(state->opts, state->audioDecoder, state->compressedDecoder, state->audioProgram);
577
578        /* start playback  */
579        rc = NEXUS_Playback_Start(state->playback, state->file, state->playbackStartSettings);
580        BDBG_ASSERT(!rc);
581
582        /* seek into desired location */
583        rc = NEXUS_Playback_Seek(state->playback, status.position);
584        BDBG_ASSERT(!rc);
585
586        /* start playing */
587        rc = NEXUS_Playback_Play(state->playback);
588        BDBG_ASSERT(!rc);
589        BKNI_ReleaseMutex(state->lock);
590    }
591    return NULL;
592}
593
594static void
595monitor_thread_start(PlaybackMonitorState *state)
596{
597    int rc;
598    BKNI_CreateMutex(&state->lock);
599    state->terminate = false;
600    rc = pthread_create(&state->thread, NULL, monitor_thread, state);
601    BDBG_ASSERT(rc==0);
602    return;
603}
604
605static void
606monitor_thread_stop(PlaybackMonitorState *state)
607{
608    state->terminate = true;
609    pthread_join(state->thread, NULL);
610}
611#endif /* B_HAS_PLAYBACK_MONITOR */
612
613static void play_endOfStreamCallback(void *context, int param)
614{
615    BSTD_UNUSED(param);
616    BSTD_UNUSED(context);
617
618    printf("endOfStream\n");
619    return;
620}
621
622struct CdxaFile {
623    struct NEXUS_FilePlay interface; /* must be the first member */
624    bcdxa_file_t data;
625    bcdxa_file_t index;
626    NEXUS_FilePlayHandle parent;
627};
628
629static void Cdxa_File_Close(struct NEXUS_FilePlay *file_)
630{
631    struct CdxaFile *file = (void *)file_;
632    bcdxa_file_destroy(file->data);
633    if(file->index) {
634        bcdxa_file_destroy(file->index);
635    }
636    file->parent->file.close(file->parent);
637    BKNI_Free(file);
638    return;
639}
640
641static NEXUS_FilePlayHandle Cdxa_File_Attach(NEXUS_FilePlayHandle parent)
642{
643    struct CdxaFile *file;
644    file = BKNI_Malloc(sizeof(*file));
645    BDBG_ASSERT(file);
646    file->parent = parent;
647    file->data = bcdxa_file_create(parent->file.data);
648    file->interface.file.close = Cdxa_File_Close;
649    BDBG_ASSERT(file->data);
650    file->interface.file.data = bcdxa_file_get_file_interface(file->data);
651    file->interface.file.index = NULL;
652    file->index = NULL;
653    if(parent->file.index) {
654        file->index = bcdxa_file_create(parent->file.index);
655        BDBG_ASSERT(file->index);
656        file->interface.file.index = bcdxa_file_get_file_interface(file->index);
657    }
658    return &file->interface;
659}
660
661struct PcmFile {
662    struct NEXUS_FilePlay interface; /* must be the first member */
663    bpcm_file_t data;
664    bpcm_file_t index;
665    NEXUS_FilePlayHandle parent;
666};
667
668static void Pcm_File_Close(struct NEXUS_FilePlay *file_)
669{
670    struct PcmFile *file = (void *)file_;
671    bpcm_file_destroy(file->data);
672    if(file->index) {
673        bpcm_file_destroy(file->index);
674    }
675    file->parent->file.close(file->parent);
676    BKNI_Free(file);
677    return;
678}
679
680static NEXUS_FilePlayHandle Pcm_File_Attach(NEXUS_FilePlayHandle parent, const bpcm_file_config *pcm_config)
681{
682    struct PcmFile *file;
683    file = BKNI_Malloc(sizeof(*file));
684    BDBG_ASSERT(file);
685    file->parent = parent;
686    file->data = bpcm_file_create(parent->file.data, pcm_config);
687    BDBG_ASSERT(file->data);
688    file->interface.file.data = bpcm_file_get_file_interface(file->data);
689    if(parent->file.index) {
690        file->index = bpcm_file_create(parent->file.index, pcm_config);
691        BDBG_ASSERT(file->index);
692        file->interface.file.index= bpcm_file_get_file_interface(file->index);
693    } else {
694        file->interface.file.index = NULL;
695        file->index = NULL;
696    }
697    file->interface.file.close = Pcm_File_Close;
698    return &file->interface;
699}
700
701#if NEXUS_NUM_HDMI_OUTPUTS
702/* registered HDMI hotplug handler -- changes the format (to monitor's default) if monitor doesn't support current format */
703static void hotplug_callback(void *pParam, int iParam)
704{
705    NEXUS_HdmiOutputStatus hdmiStatus;
706    NEXUS_HdmiOutputHandle hdmi = pParam;
707    NEXUS_DisplayHandle display = (NEXUS_DisplayHandle)iParam;
708    NEXUS_Error rc;
709
710    rc = NEXUS_HdmiOutput_GetStatus(hdmi, &hdmiStatus);
711    /*fprintf(stderr, "HDMI event: %s\n", hdmiStatus.connected?"connected":"not connected");*/
712
713    /* the app can choose to switch to the preferred format, but it's not required. */
714    if ( !rc && hdmiStatus.connected )
715    {
716        NEXUS_DisplaySettings displaySettings;
717        NEXUS_Display_GetSettings(display, &displaySettings);
718        if ( !hdmiStatus.videoFormatSupported[displaySettings.format] )
719        {
720            fprintf(stderr, "Current format not supported by attached monitor -- switching to preferred format (%d)\n", hdmiStatus.preferredVideoFormat);
721            if (hdmiStatus.preferredVideoFormat >= NEXUS_VideoFormat_e480p) 
722                fprintf(stderr, "Warning: This format may disable composite output!\n");
723            displaySettings.format = hdmiStatus.preferredVideoFormat;
724            NEXUS_Display_SetSettings(display, &displaySettings);
725        }
726    }
727}
728#endif
729
730int main(int argc, const char *argv[])
731{
732    NEXUS_PlatformSettings platformSettings;
733    NEXUS_PlatformConfiguration platformConfig;
734    NEXUS_StcChannelHandle stcChannel;
735    NEXUS_StcChannelSettings stcSettings;
736    NEXUS_PidChannelHandle videoPidChannel = NULL, audioPidChannel = NULL, pcrPidChannel, videoExtPidChannel=NULL;
737    NEXUS_DisplayHandle display;
738    NEXUS_DisplaySettings displaySettings;
739    NEXUS_DisplayVbiSettings displayVbiSettings;
740    NEXUS_VideoWindowHandle window;
741    NEXUS_VideoWindowSettings windowSettings;
742    NEXUS_VideoDecoderHandle videoDecoder;
743    NEXUS_VideoDecoderSettings videoDecoderSettings;
744    NEXUS_VideoDecoderStartSettings videoProgram;
745    NEXUS_AudioDecoderHandle audioDecoder, compressedDecoder=NULL;
746    NEXUS_AudioDecoderStartSettings audioProgram;
747    NEXUS_FilePlayHandle file,customFile=NULL, stickyFile=NULL, cdxaFile=NULL, pcmFile=NULL;
748    NEXUS_PlaypumpHandle playpump;
749    NEXUS_PlaybackHandle playback;
750    NEXUS_PlaybackSettings playbackSettings;
751    NEXUS_PlaybackPidChannelSettings playbackPidSettings;
752    NEXUS_PlaybackStartSettings playbackStartSettings;
753    NEXUS_VideoDecoderOpenSettings openSettings;
754    NEXUS_Error rc;
755    bool exit;
756    NEXUS_SurfaceHandle framebuffer = NULL;
757    NEXUS_AudioDecoderOpenSettings audioDecoderOpenSettings;
758    struct util_opts_t opts;
759
760    if (cmdline_parse(argc, argv, &opts)) {
761        return 0;
762    }
763    /* They MUST include a file to play */
764    if (!opts.filename) {
765        BDBG_ERR(("Missing playback file; See usage."));
766        print_usage(argv[0]);
767        return 0;
768    }
769
770    /* Bring up all modules for a platform in a default configuraiton for this platform */
771    NEXUS_Platform_GetDefaultSettings(&platformSettings);
772    platformSettings.openFrontend = false;
773    if(opts.avc51) {
774        platformSettings.videoDecoderModuleSettings.heapSize[0].general = (84*1024*1024);
775        platformSettings.videoDecoderModuleSettings.numDecodes = 1;
776    }
777
778    rc = NEXUS_Platform_Init(&platformSettings);
779    BDBG_ASSERT(!rc);
780    NEXUS_Platform_GetConfiguration(&platformConfig);
781   
782    if (cmdline_probe(&opts.common, opts.filename, &opts.indexname)) {
783        return 1;
784    }
785
786    playpump = NEXUS_Playpump_Open(0, NULL);
787    BDBG_ASSERT(playpump);
788    playback = NEXUS_Playback_Create();
789    BDBG_ASSERT(playback);
790
791    if ((opts.indexname && !strcmp(opts.indexname, "same")) ||
792        opts.common.transportType == NEXUS_TransportType_eMkv ||
793        opts.common.transportType == NEXUS_TransportType_eMp4
794        )
795    {
796        opts.indexname = opts.filename;
797    }
798
799    file = NEXUS_FilePlay_OpenPosix(opts.filename, opts.indexname);
800    if (!file) {
801        fprintf(stderr, "can't open files: '%s' '%s'\n", opts.filename, opts.indexname);
802        return -1;
803    }
804    if(opts.customFileIo) {
805        customFile = file = FileIoCustom_Attach(file);
806        BDBG_ASSERT(file);
807    }
808    if(opts.common.cdxaFile) {
809        cdxaFile = file = Cdxa_File_Attach(file);
810    }
811    if(opts.common.pcm) {
812        pcmFile = file = Pcm_File_Attach(file, &opts.common.pcm_config);
813    }
814    if(opts.playbackMonitor) {
815        stickyFile = file = FileIoSticky_Attach(file);
816        BDBG_ASSERT(file);
817    }
818
819    NEXUS_StcChannel_GetDefaultSettings(0, &stcSettings);
820    stcSettings.timebase = NEXUS_Timebase_e0;
821    stcSettings.mode = NEXUS_StcChannelMode_eAuto;
822    stcSettings.modeSettings.Auto.behavior = opts.stcChannelMaster;
823    stcSettings.modeSettings.Auto.transportType = opts.common.transportType;
824    stcChannel = NEXUS_StcChannel_Open(0, &stcSettings);
825
826    NEXUS_Playback_GetSettings(playback, &playbackSettings);
827    playbackSettings.playpump = playpump;
828    playbackSettings.playpumpSettings.transportType = opts.common.transportType;
829    playbackSettings.playpumpSettings.timestamp.pacing = false;
830    playbackSettings.playpumpSettings.timestamp.type = opts.common.tsTimestampType;
831    if(opts.maxPlaybackDataRate) {
832        playbackSettings.playpumpSettings.maxDataRate = opts.maxPlaybackDataRate;
833    }
834    playbackSettings.startPaused = opts.startPaused;
835    playbackSettings.stcChannel = stcChannel;
836    playbackSettings.stcTrick = opts.stcTrick;
837    playbackSettings.beginningOfStreamAction = opts.beginningOfStreamAction;
838    playbackSettings.endOfStreamAction = opts.endOfStreamAction;
839    playbackSettings.endOfStreamCallback.callback = play_endOfStreamCallback;
840    playbackSettings.enableStreamProcessing = opts.streamProcessing;
841    rc = NEXUS_Playback_SetSettings(playback, &playbackSettings);
842    BDBG_ASSERT(!rc);
843
844    NEXUS_AudioDecoder_GetDefaultOpenSettings(&audioDecoderOpenSettings);
845    if(opts.common.audioCdb) {
846        audioDecoderOpenSettings.fifoSize = opts.common.audioCdb*1024;
847    }
848    if (opts.common.multichannelAudio) {
849        audioDecoderOpenSettings.multichannelFormat = NEXUS_AudioMultichannelFormat_e5_1;
850    }
851    /* Bring up audio decoders and outputs */
852    audioDecoder = NEXUS_AudioDecoder_Open(0, &audioDecoderOpenSettings);
853    BDBG_ASSERT(audioDecoder);
854
855    if (opts.common.audioPid) {
856        rc = NEXUS_AudioOutput_AddInput(
857            NEXUS_AudioDac_GetConnector(platformConfig.outputs.audioDacs[0]),
858            NEXUS_AudioDecoder_GetConnector(audioDecoder, NEXUS_AudioDecoderConnectorType_eStereo));
859        BDBG_ASSERT(!rc);
860    }
861    if (opts.common.compressedAudio) {
862        audioDecoderOpenSettings.multichannelFormat = NEXUS_AudioMultichannelFormat_eNone;
863        compressedDecoder = NEXUS_AudioDecoder_Open(1, &audioDecoderOpenSettings);
864        BDBG_ASSERT(compressedDecoder);
865        if ( opts.common.audioCodec == NEXUS_AudioCodec_eAc3Plus || opts.common.audioCodec == NEXUS_AudioCodec_eWmaPro )
866        {
867            /* These codecs pasthrough as part of decode (ac3+ is transcoded to ac3, wma pro is not transcoded) */
868            rc = NEXUS_AudioOutput_AddInput(
869                NEXUS_SpdifOutput_GetConnector(platformConfig.outputs.spdif[0]),
870                NEXUS_AudioDecoder_GetConnector(audioDecoder, NEXUS_AudioDecoderConnectorType_eCompressed));
871        }
872        else
873        {
874            rc = NEXUS_AudioOutput_AddInput(
875                NEXUS_SpdifOutput_GetConnector(platformConfig.outputs.spdif[0]),
876                NEXUS_AudioDecoder_GetConnector(compressedDecoder, NEXUS_AudioDecoderConnectorType_eCompressed));
877        }
878        BDBG_ASSERT(!rc);
879    }
880    else
881    {
882      rc = NEXUS_AudioOutput_AddInput(
883          NEXUS_SpdifOutput_GetConnector(platformConfig.outputs.spdif[0]),
884          NEXUS_AudioDecoder_GetConnector(audioDecoder, NEXUS_AudioDecoderConnectorType_eStereo));
885      BDBG_ASSERT(!rc);
886    }
887#if NEXUS_NUM_HDMI_OUTPUTS
888    if (opts.common.useHdmiOutput)
889    {
890        NEXUS_HdmiOutputStatus hdmiStatus;
891        NEXUS_AudioDecoderHandle hdmiDecoder = audioDecoder;
892        NEXUS_AudioDecoderConnectorType connectorType = NEXUS_AudioDecoderConnectorType_eStereo;
893
894        NEXUS_HdmiOutput_GetStatus(platformConfig.outputs.hdmi[0], &hdmiStatus);
895        if ( opts.common.multichannelAudio && hdmiStatus.maxAudioPcmChannels > 2 )
896        {
897            connectorType = NEXUS_AudioDecoderConnectorType_eMultichannel;
898        }
899        else if ( opts.common.compressedAudio )
900        {
901            if ( hdmiStatus.audioCodecSupported[opts.common.audioCodec] )
902            {
903                /* Codec is directly supported */
904                hdmiDecoder = (opts.common.audioCodec == NEXUS_AudioCodec_eWmaPro) ? audioDecoder:compressedDecoder;
905                connectorType = NEXUS_AudioDecoderConnectorType_eCompressed;
906            }
907            else if ( opts.common.audioCodec == NEXUS_AudioCodec_eAc3Plus && hdmiStatus.audioCodecSupported[NEXUS_AudioCodec_eAc3] )
908            {
909                /* AC3 is supported, convert ac3+ to ac3. */
910                connectorType = NEXUS_AudioDecoderConnectorType_eCompressed;
911            }
912        }
913
914        rc = NEXUS_AudioOutput_AddInput(
915            NEXUS_HdmiOutput_GetAudioConnector(platformConfig.outputs.hdmi[0]),
916            NEXUS_AudioDecoder_GetConnector(hdmiDecoder, connectorType));
917        BDBG_ASSERT(!rc);
918    }
919#endif /*NEXUS_NUM_HDMI_OUTPUTS*/
920
921    NEXUS_Display_GetDefaultSettings(&displaySettings);
922    displaySettings.displayType = opts.common.displayType;
923    displaySettings.format = opts.common.displayFormat;
924    if(opts.common.displayOrientation != NEXUS_VideoOrientation_e2D) {
925        displaySettings.display3DSettings.overrideOrientation = true;
926        displaySettings.display3DSettings.orientation = opts.common.displayOrientation;
927    }
928    if (opts.cmp_crc) {
929        displaySettings.crcQueueSize = 60; /* This enables the CRC capture */
930    }
931    display = NEXUS_Display_Open(0, &displaySettings);
932    if (opts.common.useCompositeOutput) {
933        rc = NEXUS_Display_AddOutput(display, NEXUS_CompositeOutput_GetConnector(platformConfig.outputs.composite[0]));
934        BDBG_ASSERT(!rc);
935    }
936#if NEXUS_NUM_COMPONENT_OUTPUTS
937    if (opts.common.useComponentOutput) {
938        rc = NEXUS_Display_AddOutput(display, NEXUS_ComponentOutput_GetConnector(platformConfig.outputs.component[0]));
939        BDBG_ASSERT(!rc);
940    }
941#endif
942#if NEXUS_NUM_PANEL_OUTPUTS
943    if (opts.common.usePanelOutput) {
944        rc = NEXUS_Display_AddOutput(display, NEXUS_PanelOutput_GetConnector(platformConfig.outputs.panel[0]));
945        BDBG_ASSERT(!rc);
946        NEXUS_BoardCfg_ConfigurePanel(true, true, true);
947    }
948#endif
949#if NEXUS_NUM_SCART_INPUTS
950    if (opts.common.useScart1CompositeOutput) {
951        printf("Turning on: scart 1 composite output\n");
952        rc = NEXUS_Display_AddOutput(display, NEXUS_ScartInput_GetVideoOutputConnector(platformConfig.inputs.scart[1]));
953        BDBG_ASSERT(!rc);
954    }
955#endif
956#if NEXUS_NUM_HDMI_OUTPUTS
957    if (opts.common.useHdmiOutput) {
958        NEXUS_HdmiOutputSettings hdmiSettings;
959
960        rc = NEXUS_Display_AddOutput(display, NEXUS_HdmiOutput_GetVideoConnector(platformConfig.outputs.hdmi[0]));
961        BDBG_ASSERT(!rc);
962
963        /* Install hotplug callback -- video only for now */
964        NEXUS_HdmiOutput_GetSettings(platformConfig.outputs.hdmi[0], &hdmiSettings);
965        hdmiSettings.hotplugCallback.callback = hotplug_callback;
966        hdmiSettings.hotplugCallback.context = platformConfig.outputs.hdmi[0];
967        hdmiSettings.hotplugCallback.param = (int)display;
968        NEXUS_HdmiOutput_SetSettings(platformConfig.outputs.hdmi[0], &hdmiSettings);
969
970        /* Force a hotplug to switch to preferred format */
971        hotplug_callback(platformConfig.outputs.hdmi[0], (int)display);
972    }
973#endif
974
975    if (opts.graphics) {
976        NEXUS_SurfaceCreateSettings surfaceCreateSettings;
977        NEXUS_SurfaceMemory mem;
978        NEXUS_GraphicsSettings graphicsSettings;
979        NEXUS_VideoFormatInfo videoFormatInfo;
980        unsigned i,j;
981
982        NEXUS_VideoFormat_GetInfo(displaySettings.format, &videoFormatInfo);
983
984        NEXUS_Surface_GetDefaultCreateSettings(&surfaceCreateSettings);
985        surfaceCreateSettings.width = 720;
986        surfaceCreateSettings.height = videoFormatInfo.height;
987        framebuffer = NEXUS_Surface_Create(&surfaceCreateSettings);
988        NEXUS_Surface_GetMemory(framebuffer, &mem);
989        for (i=0;i<surfaceCreateSettings.height;i++) {
990            for (j=0;j<surfaceCreateSettings.width;j++) {
991                /* create checker board */
992                ((uint32_t*)((uint8_t*)mem.buffer + i*mem.pitch))[j] = (((i/50)%2) ^ ((j/50)%2)) ? 0x00000000 : 0xFFFFFFFF;
993            }
994        }
995        NEXUS_Surface_Flush(framebuffer);
996
997        NEXUS_Display_GetGraphicsSettings(display, &graphicsSettings);
998        graphicsSettings.enabled = true;
999        graphicsSettings.clip.width = surfaceCreateSettings.width;
1000        graphicsSettings.clip.height = surfaceCreateSettings.height;
1001        rc = NEXUS_Display_SetGraphicsSettings(display, &graphicsSettings);
1002        BDBG_ASSERT(!rc);
1003        rc = NEXUS_Display_SetGraphicsFramebuffer(display, framebuffer);
1004        BDBG_ASSERT(!rc);
1005    }
1006
1007    window = NEXUS_VideoWindow_Open(display, 0);
1008
1009    NEXUS_VideoWindow_GetSettings(window, &windowSettings);
1010    windowSettings.contentMode = opts.common.contentMode;
1011    rc = NEXUS_VideoWindow_SetSettings(window, &windowSettings);
1012    BDBG_ASSERT(!rc);
1013
1014    if (opts.common.mad) {
1015        NEXUS_VideoWindowMadSettings madSettings;
1016        NEXUS_VideoWindow_GetMadSettings(window, &madSettings);
1017        madSettings.deinterlace = true;
1018        rc = NEXUS_VideoWindow_SetMadSettings(window, &madSettings);
1019        BDBG_ASSERT(!rc);
1020    }
1021
1022    NEXUS_VideoDecoder_GetDefaultOpenSettings(&openSettings);
1023    if(opts.common.videoCdb) {
1024        openSettings.fifoSize = opts.common.videoCdb*1024;
1025    }
1026    if(opts.avc51) {
1027        openSettings.avc51Enabled = opts.avc51;
1028    }
1029    /* bring up decoder and connect to display */
1030    videoDecoder = NEXUS_VideoDecoder_Open(opts.common.videoDecoder, &openSettings);
1031    NEXUS_VideoDecoder_GetSettings(videoDecoder, &videoDecoderSettings);
1032    if (opts.common.sourceOrientation != NEXUS_VideoDecoderSourceOrientation_e2D) {
1033        videoDecoderSettings.customSourceOrientation = true;
1034        videoDecoderSettings.sourceOrientation = opts.common.sourceOrientation;
1035    }
1036    rc = NEXUS_VideoDecoder_SetSettings(videoDecoder, &videoDecoderSettings);
1037    BDBG_ASSERT(!rc);
1038    if (opts.avd_crc) {
1039        NEXUS_VideoDecoderExtendedSettings settings;
1040        NEXUS_VideoDecoder_GetExtendedSettings(videoDecoder, &settings);
1041        settings.crcFifoSize = 30;
1042        rc = NEXUS_VideoDecoder_SetExtendedSettings(videoDecoder, &settings);
1043        BDBG_ASSERT(!rc);
1044    }
1045    rc = NEXUS_VideoWindow_AddInput(window, NEXUS_VideoDecoder_GetConnector(videoDecoder));
1046    BDBG_ASSERT(!rc);
1047
1048    NEXUS_Display_GetVbiSettings(display, &displayVbiSettings);
1049    displayVbiSettings.vbiSource = NEXUS_VideoDecoder_GetConnector(videoDecoder);
1050    displayVbiSettings.closedCaptionEnabled = opts.closedCaptionEnabled;
1051    displayVbiSettings.closedCaptionRouting = opts.closedCaptionEnabled;
1052    rc = NEXUS_Display_SetVbiSettings(display, &displayVbiSettings);
1053    BDBG_ASSERT(!rc);
1054
1055    /* Open the audio and video pid channels */
1056    if (opts.common.videoCodec != NEXUS_VideoCodec_eNone && opts.common.videoPid!=0) {
1057        NEXUS_Playback_GetDefaultPidChannelSettings(&playbackPidSettings);
1058        playbackPidSettings.pidSettings.pidType = NEXUS_PidType_eVideo;
1059        playbackPidSettings.pidSettings.allowTimestampReordering = opts.common.playpumpTimestampReordering;
1060        playbackPidSettings.pidTypeSettings.video.decoder = videoDecoder;
1061        playbackPidSettings.pidTypeSettings.video.index = true;
1062        playbackPidSettings.pidTypeSettings.video.codec = opts.common.videoCodec;
1063        videoPidChannel = NEXUS_Playback_OpenPidChannel(playback, opts.common.videoPid, &playbackPidSettings);
1064    }
1065
1066    if (opts.common.extVideoCodec != NEXUS_VideoCodec_eNone && opts.common.extVideoPid!=0) {
1067        NEXUS_Playback_GetDefaultPidChannelSettings(&playbackPidSettings);
1068        playbackPidSettings.pidSettings.pidType = NEXUS_PidType_eVideo;
1069        playbackPidSettings.pidTypeSettings.video.index = true;
1070        playbackPidSettings.pidSettings.allowTimestampReordering = opts.common.playpumpTimestampReordering;
1071        playbackPidSettings.pidTypeSettings.video.decoder = videoDecoder;
1072        playbackPidSettings.pidTypeSettings.video.codec = opts.common.extVideoCodec;
1073        videoExtPidChannel = NEXUS_Playback_OpenPidChannel(playback, opts.common.extVideoPid, &playbackPidSettings);
1074    }
1075
1076    if (opts.common.audioCodec != NEXUS_AudioCodec_eUnknown && opts.common.audioPid!=0) {
1077        NEXUS_Playback_GetDefaultPidChannelSettings(&playbackPidSettings);
1078        playbackPidSettings.pidSettings.pidType = NEXUS_PidType_eAudio;
1079        playbackPidSettings.pidTypeSettings.audio.primary = audioDecoder;
1080        playbackPidSettings.pidSettings.pidTypeSettings.audio.codec = opts.common.audioCodec;
1081        audioPidChannel = NEXUS_Playback_OpenPidChannel(playback, opts.common.audioPid, &playbackPidSettings);
1082    }
1083
1084    if (opts.common.pcrPid && opts.common.pcrPid!=opts.common.videoPid && opts.common.pcrPid!=opts.common.audioPid) {
1085        NEXUS_Playback_GetDefaultPidChannelSettings(&playbackPidSettings);
1086        playbackPidSettings.pidSettings.pidType = NEXUS_PidType_eOther;
1087        pcrPidChannel = NEXUS_Playback_OpenPidChannel(playback, opts.common.pcrPid, &playbackPidSettings);
1088    }
1089
1090    /* Set up decoder Start structures now. We need to know the audio codec to properly set up the audio outputs. */
1091    NEXUS_VideoDecoder_GetDefaultStartSettings(&videoProgram);
1092    videoProgram.codec = opts.common.videoCodec;
1093    videoProgram.pidChannel = videoPidChannel;
1094    videoProgram.stcChannel = stcChannel;
1095    videoProgram.frameRate = opts.common.videoFrameRate;
1096    videoProgram.aspectRatio = opts.common.aspectRatio;
1097    videoProgram.sampleAspectRatio.x = opts.common.sampleAspectRatio.x;
1098    videoProgram.sampleAspectRatio.y = opts.common.sampleAspectRatio.y;
1099    videoProgram.errorHandling = opts.videoErrorHandling;
1100    videoProgram.timestampMode = opts.common.decoderTimestampMode;
1101    if(videoExtPidChannel) {
1102        videoProgram.enhancementPidChannel = videoExtPidChannel;
1103        videoProgram.codec = opts.common.extVideoCodec;
1104    }
1105    NEXUS_AudioDecoder_GetDefaultStartSettings(&audioProgram);
1106    audioProgram.codec = opts.common.audioCodec;
1107    audioProgram.pidChannel = audioPidChannel;
1108    audioProgram.stcChannel = stcChannel;
1109
1110    /* Start decoders */
1111    start_video(&opts, videoDecoder, &videoProgram);
1112    start_audio(&opts, audioDecoder, compressedDecoder, &audioProgram);
1113
1114    /* Start playback */
1115    NEXUS_Playback_GetDefaultStartSettings(&playbackStartSettings);
1116    if (opts.fixedBitrate) {
1117        playbackStartSettings.mode = NEXUS_PlaybackMode_eFixedBitrate;
1118        playbackStartSettings.bitrate = opts.fixedBitrate;
1119    }
1120    else if (opts.autoBitrate) {
1121        playbackStartSettings.mode = NEXUS_PlaybackMode_eAutoBitrate;
1122    }
1123#if READ_TIMED_DATA
1124    {
1125        barena_t arena;
1126
1127        arena = barena_create(&b_nexus_alloc_iface, 2*1024*1024);
1128        BDBG_ASSERT(arena);
1129        bsink_dump_reader_allocator = barena_alloc_iface(arena);
1130    }
1131#endif
1132    rc = NEXUS_Playback_Start(playback, file, &playbackStartSettings);
1133    BDBG_ASSERT(!rc);
1134
1135#if B_HAS_PLAYBACK_MONITOR
1136    {
1137        PlaybackMonitorState monitorState;
1138        BKNI_Memset(&monitorState, 0, sizeof(monitorState));
1139        monitorState.opts = &opts;
1140        monitorState.playback = playback;
1141        monitorState.videoDecoder = videoDecoder;
1142        monitorState.videoProgram = &videoProgram;
1143        monitorState.audioDecoder = audioDecoder;
1144        monitorState.compressedDecoder = compressedDecoder;
1145        monitorState.audioProgram = &audioProgram;
1146        monitorState.file = file;
1147        monitorState.stickyFile = stickyFile;
1148        monitorState.customFile = customFile;
1149        monitorState.playbackStartSettings = &playbackStartSettings;
1150        if(stickyFile) {
1151            monitor_thread_start(&monitorState);
1152        }
1153#endif
1154
1155    if (opts.avd_crc) {
1156        print_avd_crc(videoDecoder);
1157    }
1158    if (opts.cmp_crc) {
1159        print_cmp_crc(display);
1160    }
1161
1162    for (exit=false;!exit;)
1163    {
1164        char buffer[256];
1165        char *buf;
1166
1167        printf("playback>"); fflush(stdout);
1168        fgets(buffer, 256, stdin);
1169        if (feof(stdin)) break;
1170        buffer[strlen(buffer)-1] = 0; /* chop off \n */
1171
1172        buf = strtok(buffer, ";");
1173        if (!buf) continue;
1174
1175#if B_HAS_PLAYBACK_MONITOR
1176        if(stickyFile) {
1177            BKNI_AcquireMutex(monitorState.lock);
1178        }
1179#endif
1180        do {
1181            if (!strcmp(buf, "?") || !strcmp(buf, "help")) {
1182                printf(
1183                "Commands:\n"
1184                "  play - resume normal playback\n"
1185                "  pause - pause playback\n"
1186                "  i - decode only I frames\n"
1187                "  ip - decode only I & P frames\n"
1188                "  all - decode all frames\n"
1189                );
1190                printf(
1191                "  fa - frame advance\n"
1192                "  fr - frame reverse\n"
1193                "  rate(rate) - set trick rate (floating point number, 1.0 is normal play)\n"
1194                "  host(type[,modifier,slowrate]) - set host trick mode\n"
1195                "    type=i,ip,all; modifier=1,-1 for forward,reverse(i only); slowrate=decoder repeat rate (1=1x,2=2x)\n"
1196                );
1197                printf(
1198                "  seek(pos) - jump to position (in milliseconds)\n"
1199                "  sleep(msec) - sleep for given number of milli-seconds\n"
1200                "  st - print status\n"
1201                "  af - audio flush\n"
1202                "  restart  - stop playback and restart play from the current position\n"
1203                );
1204/*TODO* figure out what these do and add appropriate explanation*/
1205#if 0
1206                if (customFile) printf(
1207                "  error_index(error,nodata,partial_read) - get \n"
1208                "  error_data(error,nodata,partial_read) - set \n"
1209                );
1210#endif
1211                printf(
1212/*TODO* figure out what this does and add appropriate explanation*/
1213                /*"  bvn_usage(id) - \n"*/
1214                "  q - quit\n"
1215                );
1216            }
1217            else if (!strcmp(buf, "q") || !strcmp(buf, "quit")) {
1218                exit = true;
1219                break;
1220            }
1221            else if (!strcmp(buf, "play")) {
1222                rc = NEXUS_Playback_Play(playback);
1223                BDBG_ASSERT(!rc);
1224            }
1225            else if (!strcmp(buf, "fa")) {
1226                rc = NEXUS_Playback_FrameAdvance(playback, true);
1227                BDBG_ASSERT(!rc);
1228            }
1229            else if (!strcmp(buf, "fr")) {
1230                rc = NEXUS_Playback_FrameAdvance(playback, false);
1231                BDBG_ASSERT(!rc);
1232            }
1233            else if (!strcmp(buf, "pause")) {
1234                rc = NEXUS_Playback_Pause(playback);
1235                BDBG_ASSERT(!rc);
1236            }
1237            else if (!strcmp(buf, "i")) {
1238                NEXUS_PlaybackTrickModeSettings trickSettings;
1239                NEXUS_Playback_GetDefaultTrickModeSettings(&trickSettings);
1240                trickSettings.mode = NEXUS_PlaybackHostTrickMode_ePlayI;
1241                trickSettings.skipControl = NEXUS_PlaybackSkipControl_eDecoder;
1242                trickSettings.rateControl = NEXUS_PlaybackRateControl_eDecoder;
1243                rc = NEXUS_Playback_TrickMode(playback, &trickSettings);
1244                BDBG_ASSERT(!rc);
1245            }
1246            else if (!strcmp(buf, "ip")) {
1247                NEXUS_PlaybackTrickModeSettings trickSettings;
1248                NEXUS_Playback_GetDefaultTrickModeSettings(&trickSettings);
1249                trickSettings.mode = NEXUS_PlaybackHostTrickMode_ePlayIP;
1250                trickSettings.skipControl = NEXUS_PlaybackSkipControl_eDecoder;
1251                trickSettings.rateControl = NEXUS_PlaybackRateControl_eDecoder;
1252                rc = NEXUS_Playback_TrickMode(playback, &trickSettings);
1253                BDBG_ASSERT(!rc);
1254            }
1255            else if (!strcmp(buf, "all")) {
1256                NEXUS_PlaybackTrickModeSettings trickSettings;
1257                NEXUS_Playback_GetDefaultTrickModeSettings(&trickSettings);
1258                trickSettings.mode = NEXUS_PlaybackHostTrickMode_eNormal;
1259                trickSettings.skipControl = NEXUS_PlaybackSkipControl_eDecoder;
1260                trickSettings.rateControl = NEXUS_PlaybackRateControl_eDecoder;
1261                rc = NEXUS_Playback_TrickMode(playback, &trickSettings);
1262                BDBG_ASSERT(!rc);
1263            }
1264            else if (strstr(buf, "sleep(") == buf) {
1265                unsigned msec;
1266                sscanf(buf+6, "%u", &msec);
1267                BKNI_Sleep(msec);
1268            }
1269            else if (strstr(buf, "rate(") == buf) {
1270                NEXUS_PlaybackTrickModeSettings trickSettings;
1271                float rate;
1272
1273                sscanf(buf+5, "%f", &rate);
1274                NEXUS_Playback_GetDefaultTrickModeSettings(&trickSettings);
1275                trickSettings.rate = NEXUS_NORMAL_DECODE_RATE * rate;
1276                if (!trickSettings.rate && rate) {
1277                    trickSettings.rate = rate>0?1:-1;
1278                }
1279                if(opts.maxDecoderRate) {
1280                    trickSettings.maxDecoderRate = opts.maxDecoderRate;
1281                }
1282                rc = NEXUS_Playback_TrickMode(playback, &trickSettings);
1283                /* don't assert for fast or reverse trick modes */
1284                if (trickSettings.rate >=0 && trickSettings.rate <= NEXUS_NORMAL_DECODE_RATE) {
1285                    BDBG_ASSERT(!rc);
1286                }
1287            }
1288            else if (strstr(buf, "host(") == buf) {
1289                char *s;
1290                char trick[64];
1291                int n, modifier, decoder_slowrate;
1292                NEXUS_PlaybackTrickModeSettings trickSettings;
1293
1294                /* convert , and ) into spaces for sscanf */
1295                while ((s = strpbrk(buf, ",)"))) {
1296                    *s = ' ';
1297                }
1298               
1299                n = sscanf(buf+5, "%s %d %d", trick, &modifier, &decoder_slowrate);
1300                if (n < 2 || modifier == 0) modifier = 1;
1301                if (n < 3 || decoder_slowrate == 0) decoder_slowrate = 1;
1302               
1303                BDBG_MSG(("host(%s,%d,%d)", trick, modifier, decoder_slowrate));
1304               
1305                NEXUS_Playback_GetDefaultTrickModeSettings(&trickSettings);
1306                trickSettings.skipControl = NEXUS_PlaybackSkipControl_eHost;
1307                trickSettings.rateControl = NEXUS_PlaybackRateControl_eDecoder;
1308                trickSettings.mode_modifier = modifier;
1309                if (!strcasecmp(trick, "ip")) {
1310                    trickSettings.mode = NEXUS_PlaybackHostTrickMode_ePlayIP;
1311                }
1312                else if (!strcasecmp(trick, "i")) {
1313                    trickSettings.mode = NEXUS_PlaybackHostTrickMode_ePlayI;
1314                }
1315                else if (!strcasecmp(trick, "all")) {
1316                    trickSettings.mode = NEXUS_PlaybackHostTrickMode_eNormal;
1317                }
1318                else if (!strcasecmp(trick, "gop")) {
1319                    trickSettings.mode = NEXUS_PlaybackHostTrickMode_ePlayGop;
1320                }
1321                else if (!strcasecmp(trick, "bcm")) {
1322                    trickSettings.mode = NEXUS_PlaybackHostTrickMode_ePlayBrcm;
1323                }
1324                else {
1325                    BDBG_WRN(("unknown trick mode: %s", trick));
1326                    trickSettings.mode = NEXUS_PlaybackHostTrickMode_eNone;
1327                }
1328                trickSettings.rate = NEXUS_NORMAL_DECODE_RATE / decoder_slowrate;
1329                if (decoder_slowrate && !trickSettings.rate) {
1330                    trickSettings.rate = 1;
1331                }
1332                NEXUS_Playback_TrickMode(playback, &trickSettings);
1333            }
1334            else if (strstr(buf, "seek(") == buf) {
1335                unsigned pos;
1336                unsigned min,sec,msec;
1337
1338                if(sscanf(buf+5,"%u:%u.%u", &min, &sec, &msec)==3) {
1339                    pos = (min*60+sec)*1000+msec;
1340                } if(sscanf(buf+5,"%u:%u", &min, &sec)==2) {
1341                    pos = (min*60+sec)*1000;
1342                } else {
1343                    sscanf(buf+5, "%u", &pos);
1344                }
1345                NEXUS_Playback_Seek(playback, pos);
1346                /* failure is normal if location doesn't exist */
1347            }
1348            else if (!strcmp(buf, "st")) {
1349                NEXUS_VideoDecoderStatus vstatus;
1350                NEXUS_AudioDecoderStatus astatus;
1351                NEXUS_AudioDecoderStatus acstatus;
1352                NEXUS_PlaybackStatus pstatus;
1353                NEXUS_PlaypumpStatus pumpstatus;
1354                uint32_t stc;
1355
1356                rc = NEXUS_VideoDecoder_GetStatus(videoDecoder, &vstatus);
1357                BDBG_ASSERT(!rc);
1358                if(opts.common.decodedAudio) {
1359                    rc = NEXUS_AudioDecoder_GetStatus(audioDecoder, &astatus);
1360                    BDBG_ASSERT(!rc);
1361                }
1362                if(compressedDecoder) {
1363                    rc = NEXUS_AudioDecoder_GetStatus(compressedDecoder, &acstatus);
1364                    BDBG_ASSERT(!rc);
1365                }
1366
1367                rc = NEXUS_Playback_GetStatus(playback, &pstatus);
1368                BDBG_ASSERT(!rc);
1369                rc = NEXUS_Playpump_GetStatus(playpump, &pumpstatus);
1370                NEXUS_StcChannel_GetStc(stcChannel, &stc);
1371
1372                if (opts.common.videoPid) {
1373                    char enhancementInfo[64];
1374                    *enhancementInfo='\0';
1375                    if(vstatus.enhancementFifoSize) {
1376                        snprintf(enhancementInfo, sizeof(enhancementInfo),  " [%u/%u (%u%%)]",
1377                                vstatus.enhancementFifoDepth, vstatus.enhancementFifoSize,
1378                                vstatus.enhancementFifoDepth * 100 / vstatus.enhancementFifoSize);
1379                    }
1380
1381                    printf("video %u/%u (%u%%)%s pts=%#x, stc=%#x (diff %d) fps=%sHz, queueDepth=%d\n", vstatus.fifoDepth, vstatus.fifoSize,
1382                        vstatus.fifoSize ? vstatus.fifoDepth * 100 / vstatus.fifoSize : 0,
1383                        enhancementInfo,
1384                        vstatus.pts, stc, vstatus.ptsStcDifference,
1385                        g_videoFrameRateStrs[vstatus.frameRate].name,
1386                        vstatus.queueDepth);
1387                    if (vstatus.avdStatusBlock) {
1388                        printf("  avdStatusBlock=%#x\n", vstatus.avdStatusBlock);
1389                    }
1390                }
1391                if (opts.common.audioPid) {
1392                    if(opts.common.decodedAudio) {
1393                        printf("audio %u/%u (%u%%) pts=%#x, stc=%#x (diff %d), queuedFrames=%d\n", astatus.fifoDepth, astatus.fifoSize,
1394                            astatus.fifoSize ? astatus.fifoDepth * 100 / astatus.fifoSize : 0,
1395                            astatus.pts, stc, astatus.ptsStcDifference,
1396                            astatus.queuedFrames);
1397                    }
1398                    if(compressedDecoder) {
1399                        printf("compressed %u/%u (%u%%) pts=%#x, stc=%#x (diff %d), queuedFrames=%d\n", acstatus.fifoDepth, acstatus.fifoSize,
1400                            acstatus.fifoSize ? acstatus.fifoDepth * 100 / acstatus.fifoSize : 0,
1401                            acstatus.pts, stc, acstatus.ptsStcDifference,
1402                            astatus.queuedFrames);
1403                    }
1404                }
1405                printf("playback %u/%u (%u%%) pos=%u:%02u.%03u(%d:%d) last=%u:%02u.%03u\n", pstatus.fifoDepth, pstatus.fifoSize,
1406                    pstatus.fifoSize ? pstatus.fifoDepth * 100 / pstatus.fifoSize : 0,
1407                    (unsigned)pstatus.position/60000,
1408                    (unsigned)(pstatus.position%60000)/1000,
1409                    (unsigned)pstatus.position%1000,
1410                    (int)(pstatus.readPosition - pstatus.position),
1411                    (int)(pumpstatus.mediaPts - (opts.common.videoPid?vstatus.pts:astatus.pts))/45,
1412                    (unsigned)pstatus.last/60000,
1413                    (unsigned)(pstatus.last%60000)/1000,
1414                    (unsigned)pstatus.last%1000
1415                    );
1416            }
1417            else if (!strcmp(buf, "af")) {
1418                NEXUS_AudioDecoder_Flush(audioDecoder);
1419                if(compressedDecoder) {
1420                    NEXUS_AudioDecoder_Flush(compressedDecoder);
1421                }
1422            }
1423            else if (!strcmp(buf, "restart")) {
1424                NEXUS_PlaybackStatus status;
1425                NEXUS_VideoDecoderSettings videoDecoderSettings;
1426
1427                /* get current playback position */
1428                rc = NEXUS_Playback_GetStatus(playback, &status);
1429                BDBG_ASSERT(!rc);
1430                NEXUS_Playback_Stop(playback);
1431
1432                if (opts.common.videoPid) {
1433                    /* don't show black frame */
1434                    NEXUS_VideoDecoder_GetSettings(videoDecoder, &videoDecoderSettings);
1435                    videoDecoderSettings.channelChangeMode = NEXUS_VideoDecoder_ChannelChangeMode_eHoldUntilTsmLock;
1436                    rc=NEXUS_VideoDecoder_SetSettings(videoDecoder, &videoDecoderSettings);
1437                    BDBG_ASSERT(!rc);
1438                }
1439                /* stop decoder */
1440                stop_video(&opts, videoDecoder);
1441                stop_audio(&opts, audioDecoder, compressedDecoder);
1442
1443                NEXUS_Playback_GetSettings(playback, &playbackSettings);
1444                playbackSettings.startPaused = true;
1445                rc = NEXUS_Playback_SetSettings(playback, &playbackSettings);
1446                BDBG_ASSERT(!rc);
1447
1448                /* Start decoders */
1449                start_video(&opts, videoDecoder, &videoProgram);
1450                start_audio(&opts, audioDecoder, compressedDecoder, &audioProgram);
1451
1452
1453                /* start playback  */
1454                rc = NEXUS_Playback_Start(playback, file, &playbackStartSettings);
1455                BDBG_ASSERT(!rc);
1456
1457                /* seek into desired location */
1458                rc = NEXUS_Playback_Seek(playback, status.position);
1459                BDBG_ASSERT(!rc);
1460
1461                /* start playing */
1462                rc = NEXUS_Playback_Play(playback);
1463                BDBG_ASSERT(!rc);
1464            }
1465            else if (customFile && strstr(buf, "error_index(")==buf) {
1466                FileIoCustomProbabilities probabilities;
1467                FileIoCustom_GetProbabilities(customFile, NULL, &probabilities);
1468                sscanf(buf+strlen("error_index("),"%u,%u,%u", &probabilities.error, &probabilities.nodata, &probabilities.partial_read);
1469                FileIoCustom_SetProbabilities(customFile, NULL, &probabilities);
1470            }
1471            else if (customFile && strstr(buf, "error_data(")==buf) {
1472                FileIoCustomProbabilities probabilities;
1473                FileIoCustom_GetProbabilities(customFile , &probabilities, NULL);
1474                sscanf(buf+strlen("error_data("),"%u,%u,%u", &probabilities.error, &probabilities.nodata, &probabilities.partial_read);
1475                FileIoCustom_SetProbabilities(customFile, &probabilities, NULL);
1476            }
1477            else if (strstr(buf, "bvn_usage(") == buf) {
1478                unsigned id;
1479
1480                if (sscanf(buf+10,"%u", &id)==1) {
1481                    NEXUS_DisplayModule_SetConfigurationId(id);
1482                    /* allow failure */
1483                }
1484            }
1485            else if (!*buf) {
1486                /* allow blank line */
1487            }
1488            else {
1489                printf("unknown command: '%s' (use '?' for list)\n", buf);
1490            }
1491        }
1492        while ((buf = strtok(NULL, ";")));
1493
1494#if B_HAS_PLAYBACK_MONITOR
1495        if(stickyFile) {
1496            BKNI_ReleaseMutex(monitorState.lock);
1497        }
1498#endif
1499    }
1500
1501#if B_HAS_PLAYBACK_MONITOR
1502    if(stickyFile) {
1503        monitor_thread_stop(&monitorState);
1504    }
1505    }
1506#endif
1507    NEXUS_Playback_Stop(playback);
1508    stop_video(&opts, videoDecoder);
1509    stop_audio(&opts, audioDecoder, compressedDecoder);
1510
1511    NEXUS_Playback_CloseAllPidChannels(playback);
1512    NEXUS_FilePlay_Close(file);
1513    NEXUS_Playback_Destroy(playback);
1514    NEXUS_Playpump_Close(playpump);
1515   
1516    NEXUS_VideoWindow_Close(window);
1517    NEXUS_Display_Close(display); /* must precede NEXUS_VideoDecoder_Close to auto-shutdown of inputs */
1518    NEXUS_VideoDecoder_Close(videoDecoder);
1519    if (framebuffer) {
1520        NEXUS_Surface_Destroy(framebuffer);
1521    }
1522    NEXUS_AudioDecoder_Close(audioDecoder);
1523    if(compressedDecoder) {
1524        NEXUS_AudioDecoder_Close(compressedDecoder);
1525    }
1526    NEXUS_Platform_Uninit();
1527
1528    return 0;
1529}
1530
1531static void print_cmp_crc(NEXUS_DisplayHandle display)
1532{
1533    /* loop forever printing CMP CRC's */
1534    for (;;) {
1535        NEXUS_DisplayCrcData data[16];
1536        unsigned num, i;
1537        int rc;
1538
1539        rc = NEXUS_Display_GetCrcData(display, data, 16, &num);
1540        BDBG_ASSERT(!rc);
1541        if (!num) {
1542            BKNI_Sleep(10);
1543            continue;
1544        }
1545
1546        for (i=0;i<num;i++) {
1547            printf("CMP CRC %x %x %x\n", data[i].cmp.luma, data[i].cmp.cb, data[i].cmp.cr);
1548        }
1549    }
1550}
1551
1552static void print_avd_crc(NEXUS_VideoDecoderHandle videoDecoder)
1553{
1554    /* loop forever printing AVD CRC's */
1555    for (;;) {
1556        NEXUS_VideoDecoderCrc data[16];
1557        unsigned num, i;
1558        int rc;
1559
1560        rc = NEXUS_VideoDecoder_GetCrcData(videoDecoder, data, 16, &num);
1561        BDBG_ASSERT(!rc);
1562        if (!num) {
1563            BKNI_Sleep(10);
1564            continue;
1565        }
1566
1567        for (i=0;i<num;i++) {
1568            printf("AVD CRC %x %x %x; %x %x %x\n", data[i].top.luma, data[i].top.cr, data[i].top.cb, data[i].bottom.luma, data[i].bottom.cr, data[i].bottom.cb);
1569        }
1570    }
1571}
1572
1573#endif /*!NEXUS_HAS_PLAYBACK*/
1574
1575/*
1576************************************************
1577
1578examples / test cases
1579
1580# basic decode of streamer input
1581nexus playback -video 0x31 -audio 0x34 -video_type mpeg -audio_type ac3 /mnt/hd/italyriviera_spiderman2_cc_q64.mpg
1582
1583************************************************
1584*/
1585
Note: See TracBrowser for help on using the repository browser.