source: svn/newcon3bcm2_21bu/nexus/utils/record.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: 50.9 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: record.c $
39 * $brcm_Revision: 25 $
40 * $brcm_Date: 2/15/12 2:34p $
41 *
42 * Module Description:
43 *
44 * Revision History:
45 *
46 * $brcm_Log: /nexus/utils/record.c $
47 *
48 * 25   2/15/12 2:34p vsilyaev
49 * SW7425-2266: Updated call to NEXUS_VideoEncoder_Stop
50 *
51 * 24   1/31/12 5:07p rjlewis
52 * SW7425-1136: Added HDMI support (and some cleanup).
53 *
54 * 23   10/18/11 4:33p gmullen
55 * SW7425-1383: Merged to main
56 *
57 * SW7425-1383/3   10/18/11 4:26p gmullen
58 * SW7425-1383: Use Nexus API to get allPass PID channel number
59 *
60 * SW7425-1383/2   10/11/11 3:31p gmullen
61 * SW7425-1383: Removed test code
62 *
63 * SW7425-1383/1   10/11/11 2:35p gmullen
64 * SW7425-1383: Changed allPass PID channel assignment
65 *
66 * 22   8/18/11 5:23p vsilyaev
67 * SW7425-651: Removed deprecated control over the encoder delay
68 *
69 * 21   4/22/11 5:46p vsilyaev
70 * SW7422-14: Added code to set depth of the video decoder CDB
71 *
72 * 20   4/8/11 6:54p vsilyaev
73 * SW7422-14: Added support for recording SVC/MVC content
74 *
75 * 19   3/28/11 3:36p vsilyaev
76 * SW7425-159:  Fixed shutdown sequence
77 *
78 * 18   3/23/11 5:41p vsilyaev
79 * SW7422-406: Unified parsing of command line parameters
80 *
81 * 17   3/11/11 4:08p vsilyaev
82 * SW7425-159: Use BDBG_WRN to get nice timestamps
83 *
84 * 16   3/11/11 3:47p vsilyaev
85 * SW7425-159: add encode profile/level etc settings; add clean shutdown
86 *  sequence for transcoder; add sample usage for transcoder;
87 *
88 * SW7425-159/1   3/9/11 8:05p hongtaoz
89 * SW7425-159: add encode profile/level etc settings; add clean shutdown
90 *  sequence for transcoder; add sample usage for transcoder;
91 *
92 * 15   3/7/11 11:08a erickson
93 * SW7425-40: allow 7425 compilation w/o hdmi_input
94 *
95 * 14   3/4/11 11:43a vsilyaev
96 * SW7425-137: Removed min and target bitrates
97 *
98 * SW7425_bringup/3   3/4/11 1:27a hongtaoz
99 * SW7425-137: removed minimum and target bit rate;
100 *
101 * 13   2/22/11 3:44p vsilyaev
102 * SW7425-40: adapted to new API;
103 *
104 * SW7425_bringup/2   2/15/11 9:52p hongtaoz
105 * SW7425-40: adapted to new API;
106 *
107 * 12   12/30/10 1:50p vsilyaev
108 * SW7425-39: Updated to match StreamMux API
109 *
110 * 11   12/30/10 12:43p vsilyaev
111 * SW7425-39: Updated to match StreamMux API
112 *
113 * 10   12/22/10 1:16p vsilyaev
114 * SW7425-39, SW7425-40: merged hdmi_input source and transcoder util
115 *  test;
116 *
117 * SW7425_bringup/1   12/22/10 12:42a hongtaoz
118 * SW7425-39, SW7425-40: add hdmi_input source and transcoder util test;
119 *
120 * 9   9/8/10 12:06p vsilyaev
121 * SW7468-129: Added video decoder on ZSP
122 *
123 * 8   8/10/10 12:15p erickson
124 * SW7405-4735: merge
125 *
126 * SW7405-4735/2   8/9/10 4:31p jtna
127 * SW7405-4735: change printf back to BDBG_WRN
128 *
129 * SW7405-4735/1   8/9/10 3:22p jtna
130 * SW7405-4735: rename opts.pids to opts.otherPids. allow pid 0 in
131 *  opts.otherPids. start only one playback during allpass record.
132 *
133 * 7   8/9/10 6:34a erickson
134 * SW3548-3042: don't use NEXUS_HAS_FRONTEND to eliminate streamer. if
135 *  stremer is not available, another #define should be used. cleaned up
136 *  decoder stop. don't configure all pass parser band unless actually in
137 *  use. convert errors to BDBG_ERR.
138 *
139 * 6   5/12/10 11:26a erickson
140 * SW7550-159: fix warning
141 *
142 * 5   1/20/10 5:08p erickson
143 * SW7550-159: update record util for threshold and buffer control
144 *
145 * 4   12/8/09 3:00p gmohile
146 * SW7408-1 : Add support for platforms with no frontend
147 *
148 * 3   10/8/09 10:43a jtna
149 * SWDEPRECATED-3793: more prints and examples
150 *
151 * 2   6/18/09 4:30p jtna
152 * PR54802: add frontend support to record
153 *
154 * 1   6/16/09 5:09p jtna
155 * PR54802: initial version
156 *
157******************************************************************************/
158
159#include "nexus_platform.h"
160#include "nexus_pid_channel.h"
161#include "nexus_parser_band.h"
162#include "nexus_video_decoder.h"
163#include "nexus_stc_channel.h"
164#include "nexus_display.h"
165#include "nexus_video_window.h"
166#include "nexus_audio_dac.h"
167#include "nexus_audio_decoder.h"
168#include "nexus_audio_input.h"
169#include "nexus_audio_output.h"
170#include "nexus_spdif_output.h"
171#include "nexus_composite_output.h"
172#include "nexus_component_output.h"
173#if NEXUS_HAS_HDMI_OUTPUT
174#include "nexus_hdmi_output.h"
175#endif
176#include "nexus_surface.h"
177#include "nexus_core_utils.h"
178#if NEXUS_HAS_FRONTEND
179#include "nexus_frontend.h"
180#endif
181#if NEXUS_HAS_HDMI_INPUT
182#include "nexus_hdmi_input.h"
183#endif
184#if NEXUS_HAS_VIDEO_ENCODER
185#include "nexus_stream_mux.h"
186#endif
187#include "nexus_record.h"
188#include <sys/types.h>
189#include <sys/stat.h>
190
191#include "bstd.h"
192#include "bkni.h"
193#include <stdio.h>
194#include <string.h>
195#include <stdlib.h>
196#include "sys/time.h"
197
198#include "cmdline_args.h"
199
200BDBG_MODULE(record);
201
202#if !NEXUS_HAS_RECORD
203int main(void)
204{
205        printf("This application is not supported on this platform (needs Record)!\n");
206        return 0;
207}
208#else
209
210#define ALLPASS_PLAYMUMP_INDEX 1
211#define VIDEO_MUX_PLAYMUMP_INDEX 2
212#define AUDIO_MUX_PLAYMUMP_INDEX 3
213#define SYSTEM_MUX_PLAYMUMP_INDEX 4
214
215typedef enum RecordSource {
216    RecordSource_eStreamer,
217    RecordSource_ePlayback,
218    RecordSource_eVsb,
219    RecordSource_eQam,
220    RecordSource_eSat,
221    RecordSource_eHdmiInput
222} RecordSource;
223
224static int64_t get_filesize(const char* fname)
225{
226    struct stat buf;
227    if (stat(fname, &buf)) {
228        return -1;
229    }
230    else {
231        return (int64_t)buf.st_size;
232    }
233}
234
235struct timeval startTime;
236static void get_recordtime(char* timestamp, int size_t)
237{
238    struct timeval currentTime;
239    int hours, minutes, seconds;
240    int rc;
241
242    rc = gettimeofday(&currentTime, NULL);
243    if (rc!=0) {
244        timestamp = "00:00:00";
245        return;
246    }
247
248    hours = (currentTime.tv_sec - startTime.tv_sec)/3600;
249    minutes = (((currentTime.tv_sec - startTime.tv_sec)/60))%60;
250    seconds = (currentTime.tv_sec - startTime.tv_sec)%60;
251
252    rc = BKNI_Snprintf(timestamp, size_t, "%02u:%02u:%02u", hours, minutes, seconds);
253    return;
254}
255
256#if NEXUS_HAS_FRONTEND
257BKNI_EventHandle lockEvent;
258static void lock_callback(void *context, int param)
259{
260#if 0 /* TODO: for now, assume frontend locked upon entrance to this function */
261    NEXUS_FrontendHandle frontend = (NEXUS_FrontendHandle)context;
262    RecordSource source = (int)param;
263    bool locked = false;
264
265    if (source==RecordSource_eVsb) {
266        NEXUS_FrontendVsbStatus status;
267        NEXUS_Frontend_GetVsbStatus(frontend, &status);
268        locked = status.receiverLock;
269    }
270    else if (source==RecordSource_eQam) {
271        NEXUS_FrontendQamStatus status;
272        NEXUS_Frontend_GetQamStatus(frontend, &status);
273        locked = status.receiverLock;
274    }
275    else if (source==RecordSource_eSat) {
276        NEXUS_FrontendSatelliteStatus status;
277        NEXUS_Frontend_GetSatelliteStatus(frontend, &status);
278        locked = status.demodLocked;
279    }
280
281    if (locked) {
282        BKNI_SetEvent(lockEvent);
283    }
284#else
285    BSTD_UNUSED(context);
286    BSTD_UNUSED(param);
287    BKNI_SetEvent(lockEvent);
288#endif
289    return;
290}
291#endif
292
293#if NEXUS_HAS_STREAM_MUX
294static void 
295transcoderFinishCallback(void *context, int param)
296{
297    BKNI_EventHandle finishEvent = (BKNI_EventHandle)context;
298
299    BSTD_UNUSED(param);
300    BDBG_WRN(("Finish callback invoked, now stop the stream mux."));
301    BKNI_SetEvent(finishEvent);
302}
303#endif
304
305int main(int argc, const char *argv[])
306{
307    NEXUS_PlatformSettings platformSettings;
308    NEXUS_PlatformConfiguration platformConfig;
309    NEXUS_InputBand inputBand;
310    NEXUS_ParserBand parserBand0, parserBand1;
311    NEXUS_ParserBandSettings parserBandSettings;
312    NEXUS_PidChannelSettings pidSettings;
313    NEXUS_StcChannelHandle stcChannel;
314    NEXUS_StcChannelSettings stcSettings;
315    NEXUS_PidChannelHandle pcrPidChannel, videoPidChannel, audioPidChannel, allpassPidChannel, otherPidChannels[MAX_RECORD_PIDS], videoExtPidChannel=NULL;
316    NEXUS_PlaypumpHandle playpump0, playpump1;
317    NEXUS_PlaybackHandle playback0, playback1;
318    NEXUS_PlaybackSettings playbackSettings;
319    NEXUS_PlaybackPidChannelSettings playbackPidSettings;
320    NEXUS_FilePlayHandle playfile;
321    NEXUS_RecpumpHandle recpump;
322    NEXUS_RecpumpOpenSettings recpumpOpenSettings;
323    NEXUS_RecordHandle record;
324    NEXUS_RecordSettings recordSettings;
325    NEXUS_RecordPidChannelSettings recordPidSettings;
326    NEXUS_FileRecordHandle recfile;
327    NEXUS_DisplayHandle display;
328    NEXUS_DisplaySettings displaySettings;
329    NEXUS_VideoWindowHandle window;
330    NEXUS_VideoWindowSettings windowSettings;
331    NEXUS_VideoDecoderHandle videoDecoder;
332    NEXUS_VideoDecoderStartSettings videoProgram;
333    NEXUS_AudioDecoderHandle audioDecoder;
334    NEXUS_AudioDecoderStartSettings audioProgram;
335#if NEXUS_HAS_FRONTEND
336    NEXUS_FrontendHandle frontend = NULL;
337    NEXUS_FrontendUserParameters userParams;
338    NEXUS_FrontendVsbSettings vsbSettings;
339    NEXUS_FrontendQamSettings qamSettings;
340    NEXUS_FrontendSatelliteSettings satSettings;
341    NEXUS_FrontendDiseqcSettings diseqcSettings;
342#endif
343#if NEXUS_HAS_HDMI_INPUT
344    NEXUS_HdmiInputHandle hdmiInput;
345    NEXUS_HdmiInputSettings hdmiInputSettings;
346#endif
347#if NEXUS_HAS_VIDEO_ENCODER
348    NEXUS_DisplayHandle displayTranscode;
349    NEXUS_VideoWindowHandle windowTranscode;
350    NEXUS_VideoEncoderHandle videoEncoder;
351    NEXUS_VideoEncoderSettings videoEncoderConfig;
352    NEXUS_VideoEncoderStartSettings videoEncoderStartConfig;
353    NEXUS_StcChannelHandle stcChannelTranscode;
354    NEXUS_StreamMuxHandle streamMux;
355    NEXUS_StreamMuxCreateSettings muxCreateSettings;
356    BKNI_EventHandle finishEvent;
357    NEXUS_StreamMuxStartSettings muxConfig;
358    NEXUS_PlaypumpOpenSettings playpumpConfig;
359    NEXUS_PlaypumpHandle playpumpTranscodeVideo;
360    NEXUS_PlaypumpHandle playpumpTranscodePcr;
361    NEXUS_PidChannelHandle pidChannelTranscodeVideo;
362    NEXUS_PidChannelHandle pidChannelTranscodePcr;
363#endif
364    struct util_opts_record_t opts;
365    RecordSource source;
366    unsigned i,j;
367    bool exit;
368    NEXUS_Error rc;
369    NEXUS_VideoDecoderOpenSettings videoDecoderOpenSettings;
370
371    BKNI_Memset(otherPidChannels, 0, sizeof(otherPidChannels));
372    videoPidChannel = NULL;
373    audioPidChannel = NULL;
374
375    if (cmdline_parse_record(argc, argv, &opts)) {
376        return 0;
377    }
378
379    /* determine source */
380    if (opts.streamer) {
381        source = RecordSource_eStreamer;
382    }
383#if NEXUS_HAS_FRONTEND
384    else if (opts.vsbMode!=NEXUS_FrontendVsbMode_eMax) {
385        source = RecordSource_eVsb;
386    }
387    else if (opts.qamMode!=NEXUS_FrontendQamMode_eMax) {
388        source = RecordSource_eQam;
389    }
390    else if (opts.satMode!=NEXUS_FrontendSatelliteMode_eMax) {
391        source = RecordSource_eSat;
392    }
393#endif
394#if NEXUS_HAS_HDMI_INPUT
395    else if (opts.hdmiInput) {
396        source = RecordSource_eHdmiInput;
397    }
398#endif
399    else if (opts.playfname) {
400        source = RecordSource_ePlayback;
401        BDBG_MSG(("playback %s", opts.playfname));
402    }
403    else {
404        source = RecordSource_eStreamer;
405    }
406
407    /* bring up platform */
408    NEXUS_Platform_GetDefaultSettings(&platformSettings);
409    if (source==RecordSource_eStreamer || source==RecordSource_ePlayback || source==RecordSource_eHdmiInput) {
410        platformSettings.openFrontend = false;
411    }
412    rc = NEXUS_Platform_Init(&platformSettings);
413    BDBG_ASSERT(!rc);
414    NEXUS_Platform_GetConfiguration(&platformConfig);
415
416#if NEXUS_HAS_FRONTEND
417    /* check frontend capabilities */
418    if (platformSettings.openFrontend) {
419        for (i=0; i<NEXUS_MAX_FRONTENDS; i++) {
420            NEXUS_FrontendCapabilities capabilities;
421            frontend = platformConfig.frontend[i];
422            if (frontend) {
423                NEXUS_Frontend_GetCapabilities(frontend, &capabilities);
424                if (source==RecordSource_eVsb && capabilities.vsb) { break; }
425                else if (source==RecordSource_eQam && capabilities.qam) { break; }
426                else if (source==RecordSource_eSat && capabilities.satellite) { break; }
427                else {
428                    frontend = NULL;
429                }
430            }
431        }
432
433        if (!frontend) {
434            BDBG_ERR(("Unable to find capable frontend"));
435            return 1;
436        }
437    }
438
439    BKNI_CreateEvent(&lockEvent);
440#endif
441
442    /* setup decoder start structures */
443    NEXUS_VideoDecoder_GetDefaultStartSettings(&videoProgram);
444    NEXUS_AudioDecoder_GetDefaultStartSettings(&audioProgram);
445
446    /* media probe */
447    if (source==RecordSource_ePlayback && opts.common.probe && !opts.allpass) {
448        if (cmdline_probe(&opts.common, opts.playfname, &opts.recidxname)) {
449            return 1;
450        }
451    }
452    BDBG_WRN(("data_file: %s, index_file %s", opts.recfname, opts.recidxname));
453
454    /* check options */
455    if (opts.allpass && opts.numOtherPids) {
456        BDBG_WRN(("Allpass record specified with -pids list. -pids will be ignored."));
457        /* continue */
458    }
459    if (opts.recidxname && (!opts.common.videoPid || !opts.common.videoCodec)) {
460        BDBG_ERR(("For record with index, you must explicitly specify a video PID and video_type."));
461        return 1;
462    }
463    if (source!=RecordSource_eStreamer && source!=RecordSource_ePlayback && source!=RecordSource_eHdmiInput
464#if NEXUS_HAS_FRONTEND
465        && opts.freq==0
466#endif
467        ) {
468        BDBG_ERR(("For frontend source, you must specify a frequency"));
469        return 1;
470    }
471    if ((!opts.recfname) ||
472        (!opts.allpass && !opts.common.videoPid && !opts.common.audioPid && !opts.numOtherPids)) {
473        BDBG_ERR(("Missing destination file or pids; See usage."));
474        print_usage_record(argv[0]);
475        return 1;
476    }
477#if !NEXUS_HAS_VIDEO_ENCODER
478    if(source==RecordSource_eHdmiInput) {
479        BDBG_ERR(("For hdmi source, you must have video encoder to record"));
480        return 1;
481    }
482#endif
483    /* we have everything we need. start setting stuff up */
484    if (source==RecordSource_eHdmiInput) {
485#if NEXUS_HAS_HDMI_INPUT
486        NEXUS_TimebaseSettings timebaseSettings;
487        NEXUS_Timebase_GetSettings(NEXUS_Timebase_e0, &timebaseSettings);
488        timebaseSettings.sourceType = NEXUS_TimebaseSourceType_eHdDviIn;
489        NEXUS_Timebase_SetSettings(NEXUS_Timebase_e0, &timebaseSettings);
490
491        NEXUS_HdmiInput_GetDefaultSettings(&hdmiInputSettings);
492        hdmiInputSettings.timebase = NEXUS_Timebase_e0;
493        hdmiInput = NEXUS_HdmiInput_Open(0, &hdmiInputSettings);
494        if(!hdmiInput) {
495            BDBG_ERR(("Can't get hdmi input"));
496            return -1;
497        }
498#endif
499    }
500    else if (source!=RecordSource_ePlayback) {
501        /* setup frontend settings */
502        switch (source) {
503#if NEXUS_HAS_FRONTEND
504            case RecordSource_eVsb:
505                NEXUS_Frontend_GetDefaultVsbSettings(&vsbSettings);
506                vsbSettings.frequency = opts.freq * 1000000;
507                vsbSettings.mode = opts.vsbMode;
508                vsbSettings.lockCallback.callback = lock_callback;
509                vsbSettings.lockCallback.context = frontend;
510                vsbSettings.lockCallback.param = (int)source;
511                break;
512            case RecordSource_eQam:
513                NEXUS_Frontend_GetDefaultQamSettings(&qamSettings);
514                qamSettings.frequency = opts.freq * 1000000;
515                qamSettings.mode = opts.qamMode;
516                qamSettings.annex = NEXUS_FrontendQamAnnex_eB;
517                qamSettings.lockCallback.callback = lock_callback;
518                qamSettings.lockCallback.context = frontend;
519                qamSettings.lockCallback.param = (int)source;
520                break;
521            case RecordSource_eSat:
522                NEXUS_Frontend_GetDefaultSatelliteSettings(&satSettings);
523                satSettings.frequency = opts.freq * 1000000;
524                satSettings.mode = opts.satMode;
525                satSettings.lockCallback.callback = lock_callback;
526                satSettings.lockCallback.context = frontend;
527                satSettings.lockCallback.param = (int)source;
528
529                if (opts.satMode==NEXUS_FrontendSatelliteMode_eDvb &&
530                    opts.common.transportType!=NEXUS_TransportType_eTs) {
531                    BDBG_WRN(("mpeg_type for Sat_DVB was not set to TS"));
532                }
533                if (opts.satMode==NEXUS_FrontendSatelliteMode_eDss &&
534                    opts.common.transportType!=NEXUS_TransportType_eDssEs) {
535                    BDBG_WRN(("mpeg_type for Sat_DSS was not set to DSS_ES"));
536                }
537
538                NEXUS_Frontend_GetDiseqcSettings(frontend, &diseqcSettings);
539                if (opts.satMode==NEXUS_FrontendSatelliteMode_eDvb) {
540                    diseqcSettings.toneEnabled = true;
541                    diseqcSettings.voltage = NEXUS_FrontendDiseqcVoltage_e13v;
542                }
543                else if (opts.satMode==NEXUS_FrontendSatelliteMode_eDss) {
544                    diseqcSettings.toneEnabled = false;
545                    diseqcSettings.voltage = NEXUS_FrontendDiseqcVoltage_e18v;
546                }
547                NEXUS_Frontend_SetDiseqcSettings(frontend, &diseqcSettings);
548                break;
549#endif
550            case RecordSource_eStreamer:
551                BDBG_ASSERT(source==RecordSource_eStreamer);
552                break;
553            default:
554                BDBG_ERR(("unknown source: %d", source));
555                print_usage_record(argv[0]);
556                return 1;
557        }
558
559        /* map a parser band to the streamer/demod input band.
560           pidChannels for the decoders and non-allpass records are opened from PB0 */
561        parserBand0 = NEXUS_ParserBand_e0;
562        NEXUS_ParserBand_GetSettings(parserBand0, &parserBandSettings);
563        parserBandSettings.sourceType = NEXUS_ParserBandSourceType_eInputBand;
564        if (source==RecordSource_eStreamer) {
565            rc = NEXUS_Platform_GetStreamerInputBand(0, &inputBand);
566            BDBG_ASSERT(!rc);
567            parserBandSettings.sourceTypeSettings.inputBand = inputBand;
568        }
569#if NEXUS_HAS_FRONTEND
570        else {
571            rc = NEXUS_Frontend_GetUserParameters(frontend, &userParams);
572            BDBG_ASSERT(!rc);
573            parserBandSettings.sourceTypeSettings.inputBand = userParams.param1;
574        }
575#endif
576        parserBandSettings.transportType = opts.common.transportType;
577        rc = NEXUS_ParserBand_SetSettings(parserBand0, &parserBandSettings);
578        BDBG_ASSERT(!rc);
579
580        if (opts.allpass) {
581                /* use a separate parserBand for allpass record */
582                parserBand1 = NEXUS_ParserBand_e1;
583                NEXUS_ParserBand_GetSettings(parserBand1, &parserBandSettings);
584                parserBandSettings.sourceType = NEXUS_ParserBandSourceType_eInputBand;
585                if (source==RecordSource_eStreamer) {
586                    parserBandSettings.sourceTypeSettings.inputBand = inputBand;
587                }
588#if NEXUS_HAS_FRONTEND
589                else {
590                    parserBandSettings.sourceTypeSettings.inputBand = userParams.param1;
591                }
592#endif
593                parserBandSettings.transportType = opts.common.transportType;
594                parserBandSettings.allPass = true;
595                parserBandSettings.acceptNullPackets = opts.acceptNullPackets;
596                rc = NEXUS_ParserBand_SetSettings(parserBand1, &parserBandSettings);
597                BDBG_ASSERT(!rc);
598        }
599    }
600    else if (source==RecordSource_ePlayback) {
601        /* pidChannels for the decoders and non-allpass records are opened from playpump0 */
602        playpump0 = NEXUS_Playpump_Open(0, NULL);
603        BDBG_ASSERT(playpump0);
604        playback0 = NEXUS_Playback_Create();
605        BDBG_ASSERT(playback0);
606        if (opts.allpass) {
607        /* use a separate playpump for allpass record */
608        playpump1 = NEXUS_Playpump_Open(ALLPASS_PLAYMUMP_INDEX, NULL);
609        BDBG_ASSERT(playpump1);
610        playback1 = NEXUS_Playback_Create();
611        BDBG_ASSERT(playback1);
612        }
613
614        playfile = NEXUS_FilePlay_OpenPosix(opts.playfname, NULL);
615        if (!playfile) {
616            BDBG_ERR(("Can't open file: %s", opts.playfname));
617            return -1;
618        }
619    }
620
621    if (source!=RecordSource_ePlayback && source!=RecordSource_eHdmiInput) {
622        if (opts.allpass) {
623            /* opening the allpass pidChannel first with a specific index avoids conflicts later */
624            NEXUS_PidChannel_GetDefaultSettings(&pidSettings);
625            NEXUS_ParserBand_GetAllPassPidChannelIndex(parserBand1, (unsigned *) &pidSettings.pidChannelIndex);
626            allpassPidChannel = NEXUS_PidChannel_Open(parserBand1, 0x0, &pidSettings); /* pid is redundant */
627        }
628
629        /* open the audio and video pid channels */
630        if (opts.common.videoPid) {
631            videoPidChannel = NEXUS_PidChannel_Open(parserBand0, opts.common.videoPid, NULL);
632        }
633        if (opts.common.audioPid) {
634            audioPidChannel = NEXUS_PidChannel_Open(parserBand0, opts.common.audioPid, NULL);
635        }
636        /* open pid channels from list. don't add if duplicate of video or audio pid channel */
637        for (i=0,j=0; i<opts.numOtherPids; i++) {
638            if (!opts.otherPids[i] || (opts.otherPids[i]!=opts.common.videoPid && opts.otherPids[i]!=opts.common.audioPid)) {
639                otherPidChannels[j++] = NEXUS_PidChannel_Open(parserBand0, opts.otherPids[i], NULL);
640            }
641            else {
642                BDBG_WRN(("Ignoring duplicate pid %#x from -pids list", opts.otherPids[i]));
643            }
644        }
645
646        pcrPidChannel = NEXUS_PidChannel_Open(parserBand0, opts.common.pcrPid?opts.common.pcrPid:opts.common.videoPid, NULL);
647    } /* for playback, pidChannels are opened after decoders are opened */
648
649    /* open the stcChannel to do lipsync with the PCR */
650    NEXUS_StcChannel_GetDefaultSettings(0, &stcSettings);
651    stcSettings.timebase = NEXUS_Timebase_e0;
652    if(source==RecordSource_eHdmiInput) {
653        stcSettings.autoConfigTimebase = false;
654    }
655    else if (source!=RecordSource_ePlayback) {
656        stcSettings.mode = NEXUS_StcChannelMode_ePcr;
657        stcSettings.modeSettings.pcr.pidChannel = pcrPidChannel;
658    }
659    else {
660        stcSettings.mode = NEXUS_StcChannelMode_eAuto;
661    }
662    stcChannel = NEXUS_StcChannel_Open(0, &stcSettings);
663
664#if NEXUS_HAS_VIDEO_ENCODER
665    /* encoders/mux require different STC broadcast mode from decoder */
666    NEXUS_StcChannel_GetDefaultSettings(1, &stcSettings);
667    stcSettings.timebase = NEXUS_Timebase_e0;/* should be the same timebase for end-to-end locking */
668    stcSettings.mode = NEXUS_StcChannelMode_eAuto;
669    stcSettings.pcrBits = NEXUS_StcChannel_PcrBits_eFull42;/* ViCE2 requires 42-bit STC broadcast */
670    stcChannelTranscode = NEXUS_StcChannel_Open(1, &stcSettings);
671#endif
672
673    if (source==RecordSource_ePlayback) {
674        /* set playback settings */
675        NEXUS_Playback_GetSettings(playback0, &playbackSettings);
676        playbackSettings.playpump = playpump0;
677        playbackSettings.playpumpSettings.transportType = opts.common.transportType;
678        playbackSettings.stcChannel = stcChannel;
679        NEXUS_Playback_SetSettings(playback0, &playbackSettings);
680
681        if (opts.allpass) {
682        NEXUS_Playback_GetSettings(playback1, &playbackSettings);
683        playbackSettings.playpump = playpump1;
684        playbackSettings.playpumpSettings.transportType = opts.common.transportType;
685        playbackSettings.stcChannel = stcChannel;
686        playbackSettings.playpumpSettings.allPass = true;
687        playbackSettings.playpumpSettings.acceptNullPackets = opts.acceptNullPackets;
688        NEXUS_Playback_SetSettings(playback1, &playbackSettings);
689    }
690    }
691
692    /* bring up audio decoders and outputs */
693    audioDecoder = NEXUS_AudioDecoder_Open(0, NULL);
694#if 0
695    if(source==RecordSource_eHdmiInput) {
696        audioProgram.input = NEXUS_HdmiInput_GetAudioConnector(hdmiInput);
697
698        audioEncoder = NEXUS_AudioEncoder_Open(NULL);
699        NEXUS_AudioEncoder_AddInput(audioEncoder, NEXUS_AudioDecoder_GetConnector(audioDecoder));
700        audioMuxOutput = NEXUS_AudioMuxOutput_Create(NULL);
701        NEXUS_AudioOutput_AddInput(NEXUS_AudioMuxOutput_GetConnector(audioMuxOutput),
702            NEXUS_AudioEncoder_GetConnector(audioEncoder));
703    }
704    else
705#endif
706    {
707        rc = NEXUS_AudioOutput_AddInput(
708            NEXUS_AudioDac_GetConnector(platformConfig.outputs.audioDacs[0]),
709            NEXUS_AudioDecoder_GetConnector(audioDecoder, NEXUS_AudioDecoderConnectorType_eStereo));
710        BDBG_ASSERT(!rc);
711        rc = NEXUS_AudioOutput_AddInput(
712            NEXUS_SpdifOutput_GetConnector(platformConfig.outputs.spdif[0]),
713            NEXUS_AudioDecoder_GetConnector(audioDecoder, NEXUS_AudioDecoderConnectorType_eStereo));
714        BDBG_ASSERT(!rc);
715    }
716#if NEXUS_NUM_HDMI_OUTPUTS
717    if (opts.common.useHdmiOutput ) {
718        rc = NEXUS_AudioOutput_AddInput(
719            NEXUS_HdmiOutput_GetAudioConnector(platformConfig.outputs.hdmi[0]),
720            NEXUS_AudioDecoder_GetConnector(audioDecoder, NEXUS_AudioDecoderConnectorType_eStereo));
721        BDBG_ASSERT(!rc);
722    }
723#endif
724
725    /* bring up display and outputs */
726    NEXUS_Display_GetDefaultSettings(&displaySettings);
727    displaySettings.displayType = opts.common.displayType;
728    displaySettings.format = opts.common.displayFormat;
729    display = NEXUS_Display_Open(0, &displaySettings);
730
731#if NEXUS_NUM_COMPOSITE_OUTPUTS
732    if (opts.common.useCompositeOutput) {
733        rc = NEXUS_Display_AddOutput(display, NEXUS_CompositeOutput_GetConnector(platformConfig.outputs.composite[0]));
734        BDBG_ASSERT(!rc);
735    }
736#endif
737#if NEXUS_NUM_COMPONENT_OUTPUTS
738    if (opts.common.useComponentOutput) {
739        rc = NEXUS_Display_AddOutput(display, NEXUS_ComponentOutput_GetConnector(platformConfig.outputs.component[0]));
740        BDBG_ASSERT(!rc);
741    }
742#endif
743#if NEXUS_NUM_PANEL_OUTPUTS
744    if (opts.common.usePanelOutput) {
745        rc = NEXUS_Display_AddOutput(display, NEXUS_PanelOutput_GetConnector(platformConfig.outputs.panel[0]));
746        BDBG_ASSERT(!rc);
747        NEXUS_BoardCfg_ConfigurePanel(true, true, true);
748        BDBG_WRN(("Panel on"));
749    }
750#endif
751#if NEXUS_NUM_SCART_INPUTS
752    if (opts.common.useScart1CompositeOutput) {
753        rc = NEXUS_Display_AddOutput(display, NEXUS_ScartInput_GetVideoOutputConnector(platformConfig.inputs.scart[1]));
754        BDBG_ASSERT(!rc);
755        BDBG_WRN(("Turning on: scart 1 composite output"));
756    }
757#endif
758#if NEXUS_NUM_HDMI_OUTPUTS
759    if (opts.common.useHdmiOutput) {
760        NEXUS_HdmiOutputStatus hdmiStatus;
761        rc = NEXUS_Display_AddOutput(display, NEXUS_HdmiOutput_GetVideoConnector(platformConfig.outputs.hdmi[0]));
762        BDBG_ASSERT(!rc);
763        rc = NEXUS_HdmiOutput_GetStatus(platformConfig.outputs.hdmi[0], &hdmiStatus);
764        if ( !rc && hdmiStatus.connected )
765        {
766            /* the app can choose to switch to the preferred format, but it's not required. */
767            NEXUS_Display_GetSettings(display, &displaySettings);
768            if ( !hdmiStatus.videoFormatSupported[displaySettings.format] ) {
769                fprintf(stderr, "Current format not supported by attached monitor -- switching to preferred format (%d)\n", hdmiStatus.preferredVideoFormat);
770                displaySettings.format = hdmiStatus.preferredVideoFormat;
771                NEXUS_Display_SetSettings(display, &displaySettings);
772            }
773        }
774    }
775#endif
776
777    NEXUS_VideoDecoder_GetDefaultOpenSettings(&videoDecoderOpenSettings);
778    if(opts.common.videoCdb) {
779        videoDecoderOpenSettings.fifoSize = opts.common.videoCdb*1024;
780    }
781
782        /* bring up decoder and connect to display */
783        videoDecoder = NEXUS_VideoDecoder_Open(opts.common.videoDecoder, &videoDecoderOpenSettings);
784
785    /* NOTE: must open video encoder before display; otherwise open will init ViCE2 core
786     * which might cause encoder display GISB error since encoder display would
787     * trigger RDC to program mailbox registers in ViCE2;
788     */
789#if NEXUS_HAS_VIDEO_ENCODER
790    if (opts.encoder) {
791        BDBG_MSG(("To open video encoder..."));
792        videoEncoder = NEXUS_VideoEncoder_Open(0, NULL);
793        BDBG_ASSERT(videoEncoder);
794
795        /* Bring up video encoder display */
796        NEXUS_Display_GetDefaultSettings(&displaySettings);
797        displaySettings.displayType = NEXUS_DisplayType_eAuto;
798        displaySettings.timingGenerator = NEXUS_DisplayTimingGenerator_eEncoder;
799        displaySettings.format = opts.encodeFormat;/* bring up 480p first */
800        displayTranscode = NEXUS_Display_Open(NEXUS_ENCODER_DISPLAY_IDX, &displaySettings);/* cmp3 for transcoder */
801        BDBG_ASSERT(displayTranscode);
802
803        windowTranscode = NEXUS_VideoWindow_Open(displayTranscode, 0);
804        BDBG_ASSERT(windowTranscode);
805
806                /* connect same decoder to the encoder display;
807                 * NOTE: simul display + transcode mode might have limitation in audio path;
808                 * here is for video transcode bringup purpose;
809                 */
810#if NEXUS_HAS_HDMI_INPUT
811                if(source==RecordSource_eHdmiInput) {
812                        NEXUS_VideoWindow_AddInput(windowTranscode, NEXUS_HdmiInput_GetVideoConnector(hdmiInput));
813                }
814                else
815#endif
816        {
817            NEXUS_VideoWindow_AddInput(windowTranscode, NEXUS_VideoDecoder_GetConnector(videoDecoder));
818        }
819    }
820#endif /*NEXUS_HAS_VIDEO_ENCODER*/
821       
822    window = NEXUS_VideoWindow_Open(display, 0);
823    NEXUS_VideoWindow_GetSettings(window, &windowSettings);
824    windowSettings.contentMode = opts.common.contentMode;
825    rc = NEXUS_VideoWindow_SetSettings(window, &windowSettings);
826    BDBG_ASSERT(!rc);
827
828    rc = NEXUS_VideoWindow_AddInput(window, NEXUS_VideoDecoder_GetConnector(videoDecoder));
829    BDBG_ASSERT(!rc);
830
831    /* open playback pidChannels */
832    if (source==RecordSource_ePlayback) 
833    {
834        if (opts.allpass) 
835        {
836            NEXUS_PlaybackSettings playbackSettings;
837
838            NEXUS_Playback_GetDefaultPidChannelSettings(&playbackPidSettings);
839            NEXUS_Playback_GetSettings(playback1, &playbackSettings);
840            NEXUS_Playpump_GetAllPassPidChannelIndex(playbackSettings.playpump, (unsigned *) &playbackPidSettings.pidSettings.pidSettings.pidChannelIndex );
841            allpassPidChannel = NEXUS_Playback_OpenPidChannel(playback1, 0x0, &playbackPidSettings); /* pidNo is redundant */
842        }
843
844        /* open the audio and video pid channels */
845        if (opts.common.videoPid) {
846        NEXUS_Playback_GetDefaultPidChannelSettings(&playbackPidSettings);
847        playbackPidSettings.pidSettings.pidType = NEXUS_PidType_eVideo;
848        playbackPidSettings.pidTypeSettings.video.decoder = videoDecoder;
849        playbackPidSettings.pidTypeSettings.video.codec = opts.common.videoCodec;
850        playbackPidSettings.pidTypeSettings.video.index = true;
851        videoPidChannel = NEXUS_Playback_OpenPidChannel(playback0, opts.common.videoPid, &playbackPidSettings);
852        }
853        if (opts.common.extVideoCodec != NEXUS_VideoCodec_eNone && opts.common.extVideoPid!=0) {
854            NEXUS_Playback_GetDefaultPidChannelSettings(&playbackPidSettings);
855            playbackPidSettings.pidSettings.pidType = NEXUS_PidType_eVideo;
856            playbackPidSettings.pidTypeSettings.video.index = true;
857            playbackPidSettings.pidSettings.allowTimestampReordering = opts.common.playpumpTimestampReordering;
858            playbackPidSettings.pidTypeSettings.video.decoder = videoDecoder;
859            playbackPidSettings.pidTypeSettings.video.codec = opts.common.extVideoCodec;
860            videoExtPidChannel = NEXUS_Playback_OpenPidChannel(playback0, opts.common.extVideoPid, &playbackPidSettings);
861        }
862
863        if (opts.common.audioPid) {
864        NEXUS_Playback_GetDefaultPidChannelSettings(&playbackPidSettings);
865        playbackPidSettings.pidSettings.pidType = NEXUS_PidType_eAudio;
866        playbackPidSettings.pidTypeSettings.audio.primary = audioDecoder;
867        playbackPidSettings.pidSettings.pidTypeSettings.audio.codec = opts.common.audioCodec;
868        audioPidChannel = NEXUS_Playback_OpenPidChannel(playback0, opts.common.audioPid, &playbackPidSettings);
869        }
870
871        /* open pid channels from list. don't add if duplicate of video or audio pid channel */
872        for (i=0,j=0; i<opts.numOtherPids; i++) {
873            if (!opts.otherPids[i] || (opts.otherPids[i]!=opts.common.videoPid && opts.otherPids[i]!=opts.common.audioPid)) {
874                otherPidChannels[j++] = NEXUS_Playback_OpenPidChannel(playback0, opts.otherPids[i], NULL);
875            }
876            else {
877                BDBG_WRN(("Ignoring duplicate pid %#x from -pids list", opts.otherPids[i]));
878            }
879        }
880    }
881
882#if NEXUS_HAS_VIDEO_ENCODER
883    if (opts.encoder) {
884        NEXUS_StreamMuxOutput muxOutput;
885            NEXUS_VideoEncoder_GetSettings(videoEncoder, &videoEncoderConfig);
886            videoEncoderConfig.bitrateMax  = opts.maxVideoBitRate;
887            videoEncoderConfig.frameRate   = opts.encodeFrameRate;
888            videoEncoderConfig.variableFrameRate = opts.variableFrameRate;
889            videoEncoderConfig.streamStructure.framesP = opts.gopFrameP;
890            videoEncoderConfig.streamStructure.framesB = opts.gopFrameB;
891
892            NEXUS_VideoEncoder_GetDefaultStartSettings(&videoEncoderStartConfig);
893            videoEncoderStartConfig.codec = opts.videoTranscodec;
894            videoEncoderStartConfig.input = displayTranscode;
895            videoEncoderStartConfig.stcChannel = stcChannelTranscode;
896            videoEncoderStartConfig.profile = opts.videoProfile;
897            videoEncoderStartConfig.level   = opts.videoLevel;
898
899                /* encode setting and startSetting to be set after end-to-end delay is determined */
900               
901                /* get end-to-end delay (Dee) for audio and video encoders;
902                 * TODO: match AV delay! In other words,
903                 *       if (aDee > vDee) {
904                 *               vDee' = aDee' = aDee;
905                 *       }
906                 *       else {
907                 *               vDee' = aDee' = vDee;
908                 *       }
909                 */
910                {
911                        NEXUS_VideoEncoderDelayRange videoDelay;
912#if NEXUS_HAS_AUDIO_MUX_OUTPUT_TEST   
913                        unsigned Dee;
914#endif
915                        /* NOTE: video encoder delay is in 27MHz ticks */
916                        NEXUS_VideoEncoder_GetDelayRange(videoEncoder, &videoEncoderConfig, &videoEncoderStartConfig, &videoDelay);
917                        BDBG_WRN(("Video encoder end-to-end delay = [%u ~ %u] ms", videoDelay.min/27000, videoDelay.max/27000));
918               
919#if NEXUS_HAS_AUDIO_MUX_OUTPUT_TEST   
920                        NEXUS_AudioMuxOutput_GetDelayStatus(audioMuxOutput, audioCodec, &audioDelayStatus);
921                        BDBG_WRN(("\n\tAudio codec %d end-to-end delay = %u ms", audioCodec, audioDelayStatus.endToEndDelay));
922       
923                        Dee = audioDelayStatus.endToEndDelay * 27000; /* in 27MHz ticks */
924                        if(Dee > videoDelay.min)
925                        {
926                                if(Dee > videoDelay.max)
927                                {
928                                        BDBG_ERR(("Audio Dee is way too big! Use video Dee max!"));
929                                        Dee = videoDelay.max;
930                                }
931                                else
932                                {
933                                        BDBG_WRN(("Use audio Dee %u ms %u ticks@27Mhz!", Dee/27000, Dee));
934                                }
935                        }
936                        else
937                        {
938                                Dee = videoDelay.min;
939                                BDBG_WRN(("Use video Dee %u ms %u ticks@27Mhz!", Dee/27000, Dee));
940                        }
941                        videoEncoderConfig.encoderDelay = Dee;
942       
943                        /* Start audio mux output */
944                        NEXUS_AudioMuxOutput_GetDefaultStartSettings(&audioMuxStartSettings);
945                        audioMuxStartSettings.stcChannel = stcChannelTranscode;
946                        audioMuxStartSettings.presentationDelay = Dee/27000;/* in ms */
947                        NEXUS_AudioMuxOutput_Start(audioMuxOutput, &audioMuxStartSettings);
948#else
949                        videoEncoderConfig.encoderDelay = videoDelay.min;
950#endif
951                }
952
953                /* must set settings after Dee is determined */
954            NEXUS_VideoEncoder_SetSettings(videoEncoder, &videoEncoderConfig);
955            NEXUS_VideoEncoder_Start(videoEncoder, &videoEncoderStartConfig);
956
957            NEXUS_Playpump_GetDefaultOpenSettings(&playpumpConfig);
958            playpumpConfig.fifoSize = 16384; /* reduce FIFO size allocated for playpump */
959            playpumpConfig.numDescriptors = 64; /* set number of descriptors */
960            playpumpConfig.streamMuxCompatible = true;
961            playpumpTranscodeVideo = NEXUS_Playpump_Open(VIDEO_MUX_PLAYMUMP_INDEX, &playpumpConfig);
962            BDBG_ASSERT(playpumpTranscodeVideo);
963
964            playpumpTranscodePcr = NEXUS_Playpump_Open(SYSTEM_MUX_PLAYMUMP_INDEX, &playpumpConfig);
965            BDBG_ASSERT(playpumpTranscodePcr);
966
967                BKNI_CreateEvent(&finishEvent);
968                NEXUS_StreamMux_GetDefaultCreateSettings(&muxCreateSettings);
969                muxCreateSettings.finished.callback = transcoderFinishCallback;
970                muxCreateSettings.finished.context = finishEvent;
971                streamMux = NEXUS_StreamMux_Create(&muxCreateSettings);
972
973            NEXUS_StreamMux_GetDefaultStartSettings(&muxConfig);
974            muxConfig.transportType = NEXUS_TransportType_eTs;
975            muxConfig.latencyTolerance = opts.muxLatencyTolerance;
976            muxConfig.stcChannel = stcChannelTranscode;
977
978            muxConfig.video[0].pid = 0x12;
979            muxConfig.video[0].encoder = videoEncoder;
980            muxConfig.video[0].playpump = playpumpTranscodeVideo;
981            muxConfig.pcr.pid = 0x11;
982            muxConfig.pcr.playpump = playpumpTranscodePcr;
983            muxConfig.pcr.interval = 50;
984
985            /* open PidChannels */
986            pidChannelTranscodePcr = NEXUS_Playpump_OpenPidChannel(playpumpTranscodePcr, muxConfig.pcr.pid, NULL);
987            BDBG_ASSERT(pidChannelTranscodePcr);
988
989            /* start mux */
990            NEXUS_StreamMux_Start(streamMux, &muxConfig, &muxOutput);
991            pidChannelTranscodeVideo = muxOutput.video[0];
992            BDBG_ASSERT(pidChannelTranscodeVideo);
993    }
994#endif /* NEXUS_HAS_VIDEO_ENCODER */
995
996    /* setup record/recpump */
997    NEXUS_Recpump_GetDefaultOpenSettings(&recpumpOpenSettings);
998    if (opts.data.bufferSize) {
999        recpumpOpenSettings.data.bufferSize = opts.data.bufferSize;
1000    } else if (opts.common.extVideoCodec != NEXUS_VideoCodec_eNone && opts.common.extVideoPid!=0) {
1001        recpumpOpenSettings.data.bufferSize *=2;
1002    }
1003
1004    if (opts.data.dataReadyThreshold) {
1005        recpumpOpenSettings.data.dataReadyThreshold = opts.data.dataReadyThreshold;
1006        recpumpOpenSettings.data.dataReadyThreshold = 0;
1007    }
1008    if (opts.index.bufferSize) {
1009        recpumpOpenSettings.index.bufferSize = opts.index.bufferSize;
1010    }
1011    if (opts.index.dataReadyThreshold) {
1012        recpumpOpenSettings.index.dataReadyThreshold = opts.index.dataReadyThreshold;
1013    }
1014    recpump = NEXUS_Recpump_Open(0, &recpumpOpenSettings);
1015    record = NEXUS_Record_Create();
1016    NEXUS_Record_GetSettings(record, &recordSettings);
1017    recordSettings.recpump = recpump;
1018    NEXUS_Record_SetSettings(record, &recordSettings);
1019    recfile = NEXUS_FileRecord_OpenPosix(opts.recfname, opts.recidxname);
1020    BDBG_ASSERT(recfile);
1021
1022    /* add the pidChannels to record */
1023#if NEXUS_HAS_VIDEO_ENCODER
1024    if(opts.encoder) {
1025        /* add multiplex data to the same record */
1026        /* configure the video pid for indexing */
1027        NEXUS_Record_GetDefaultPidChannelSettings(&recordPidSettings);
1028        recordPidSettings.recpumpSettings.pidType = NEXUS_PidType_eVideo;
1029        recordPidSettings.recpumpSettings.pidTypeSettings.video.index = true;
1030        recordPidSettings.recpumpSettings.pidTypeSettings.video.codec = opts.videoTranscodec;
1031        NEXUS_Record_AddPidChannel(record, pidChannelTranscodeVideo, opts.recidxname?(&recordPidSettings):NULL);
1032        NEXUS_Record_AddPidChannel(record, pidChannelTranscodePcr, NULL);
1033    }
1034    else
1035#endif
1036    if (!opts.allpass) {
1037        if (opts.common.videoPid) {
1038            /* configure the video pid for indexing */
1039            NEXUS_Record_GetDefaultPidChannelSettings(&recordPidSettings);
1040            recordPidSettings.recpumpSettings.pidType = NEXUS_PidType_eVideo;
1041            recordPidSettings.recpumpSettings.pidTypeSettings.video.index = true;
1042            recordPidSettings.recpumpSettings.pidTypeSettings.video.codec = opts.common.videoCodec;
1043            NEXUS_Record_AddPidChannel(record, videoPidChannel, opts.recidxname?(&recordPidSettings):NULL);
1044        }
1045        if(videoExtPidChannel) {
1046            /* configure the video pid for indexing */
1047            NEXUS_Record_GetDefaultPidChannelSettings(&recordPidSettings);
1048            recordPidSettings.recpumpSettings.pidType = NEXUS_PidType_eVideo;
1049            recordPidSettings.recpumpSettings.pidTypeSettings.video.index = true;
1050            recordPidSettings.recpumpSettings.pidTypeSettings.video.codec = opts.common.extVideoCodec;
1051            NEXUS_Record_AddPidChannel(record, videoExtPidChannel, opts.recidxname?(&recordPidSettings):NULL);
1052        }
1053        if (opts.common.audioPid) {
1054            /* the audio pid requires no special configuration */
1055            NEXUS_Record_AddPidChannel(record, audioPidChannel, NULL);
1056        }
1057
1058        for (i=0; i<opts.numOtherPids; i++) { /* add other unindexed pids */
1059            NEXUS_Record_AddPidChannel(record, otherPidChannels[i], NULL);
1060        }
1061    }
1062    else {
1063        NEXUS_Record_GetDefaultPidChannelSettings(&recordPidSettings);
1064        recordPidSettings.recpumpSettings.pidType = NEXUS_PidType_eVideo;
1065        recordPidSettings.recpumpSettings.pidTypeSettings.video.index = true;
1066        recordPidSettings.recpumpSettings.pidTypeSettings.video.codec = opts.common.videoCodec;
1067        /* for allpass record, perform indexing using pid value, not pid channel */
1068        recordPidSettings.recpumpSettings.pidTypeSettings.video.pid = opts.common.videoPid;
1069        NEXUS_Record_AddPidChannel(record, allpassPidChannel,
1070            (opts.recidxname&&opts.common.videoPid)?(&recordPidSettings):NULL);
1071    }
1072
1073    gettimeofday(&startTime, NULL);
1074    rc = NEXUS_Record_Start(record, recfile);
1075    BDBG_ASSERT(!rc);
1076    /* Nexus is now recording to disk */
1077    BDBG_WRN(("Record started"));
1078
1079    /* tune frontend */
1080#if NEXUS_HAS_FRONTEND
1081    if (platformSettings.openFrontend) {
1082        switch (source) {
1083            case RecordSource_eVsb:
1084                NEXUS_Frontend_TuneVsb(frontend, &vsbSettings);
1085                break;
1086            case RecordSource_eQam:
1087                NEXUS_Frontend_TuneQam(frontend, &qamSettings);
1088                break;
1089            case RecordSource_eSat:
1090            default:
1091                NEXUS_Frontend_TuneSatellite(frontend, &satSettings);
1092                break;
1093        }
1094
1095        BDBG_WRN(("Waiting for frontend lock..."));
1096        if (BKNI_WaitForEvent(lockEvent, 5000)) {
1097            BDBG_ERR(("Failed"));
1098            return 1;
1099        }
1100        BDBG_WRN(("Locked"));
1101    }
1102#endif
1103
1104    /* start decoders */
1105    if (opts.common.videoPid && opts.decode) {
1106        videoProgram.codec = opts.common.videoCodec;
1107        videoProgram.pidChannel = videoPidChannel;
1108        videoProgram.stcChannel = stcChannel;
1109        if(videoExtPidChannel) {
1110            videoProgram.enhancementPidChannel = videoExtPidChannel;
1111            videoProgram.codec = opts.common.extVideoCodec;
1112        }
1113        rc = NEXUS_VideoDecoder_Start(videoDecoder, &videoProgram);
1114        BDBG_ASSERT(!rc);
1115    }
1116    if (opts.common.audioPid && opts.decode) {
1117        audioProgram.codec = opts.common.audioCodec;
1118        audioProgram.pidChannel = audioPidChannel;
1119        audioProgram.stcChannel = stcChannel;
1120        rc = NEXUS_AudioDecoder_Start(audioDecoder, &audioProgram);
1121        BDBG_ASSERT(!rc);
1122    }
1123
1124    /* start playback */
1125    if (source==RecordSource_ePlayback) {
1126        if (!opts.allpass) {
1127            rc = NEXUS_Playback_Start(playback0, playfile, NULL);
1128            BDBG_ASSERT(!rc);
1129        }
1130        else {
1131            rc = NEXUS_Playback_Start(playback1, playfile, NULL);
1132            BDBG_ASSERT(!rc);
1133        }
1134    }
1135
1136    for (exit=false;!exit;)
1137        {
1138        char buffer[256];
1139        char *buf;
1140
1141        printf("record>"); fflush(stdout);
1142        fgets(buffer, 256, stdin);
1143        if (feof(stdin)) break;
1144        buffer[strlen(buffer)-1] = 0; /* chop off \n */
1145
1146        buf = strtok(buffer, ";");
1147        if (!buf) continue;
1148
1149        do {
1150            if (!strcmp(buf, "?") || !strcmp(buf,"help")) {
1151                printf(
1152                "Commands:\n"
1153                "  st - print status\n"
1154                "  q  - stop record and quit\n"
1155                );
1156            }
1157            else if (!strcmp(buf, "q") || !strcmp(buf,"quit")) {
1158                exit = true;
1159                break;
1160            }
1161            else if (!strcmp(buf, "st")) {
1162                NEXUS_RecordStatus rstatus;
1163                char timestamp[20];
1164                get_recordtime(timestamp, sizeof(timestamp));
1165                rc = NEXUS_Record_GetStatus(record, &rstatus);
1166                BDBG_ASSERT(!rc);
1167                printf("(%s) data: %u(%u)KB, index: %u(%u)KB, lastTimestamp: %ums\n",
1168                    timestamp,
1169                    (unsigned)rstatus.recpumpStatus.data.bytesRecorded/1024,
1170                    (unsigned)rstatus.recpumpStatus.data.fifoDepth/1024,
1171                    (unsigned)rstatus.recpumpStatus.index.bytesRecorded/1024,
1172                    (unsigned)rstatus.recpumpStatus.index.fifoDepth/1024,
1173                    (unsigned)rstatus.lastTimestamp /* in ms */);
1174            }
1175            else if (!*buf) {
1176                /* allow blank line */
1177            }
1178            else {
1179                printf("unknown command: '%s' (use '?' for list)\n", buf);
1180            }
1181        }
1182        while ((buf = strtok(NULL, ";")));
1183    }
1184
1185    /* shutdown */
1186#if NEXUS_HAS_FRONTEND
1187    BKNI_DestroyEvent(lockEvent);
1188#endif
1189    if (source==RecordSource_ePlayback) {
1190        NEXUS_Playback_Stop(playback0);
1191        if (opts.allpass) {
1192        NEXUS_Playback_Stop(playback1);
1193        }
1194    }
1195    if (opts.common.videoPid && opts.decode) {
1196        NEXUS_VideoDecoder_Stop(videoDecoder);
1197    }
1198    if (opts.common.audioPid && opts.decode) {
1199        NEXUS_AudioDecoder_Stop(audioDecoder);
1200    }
1201#if NEXUS_HAS_VIDEO_ENCODER
1202    if (opts.encoder) {
1203        NEXUS_VideoEncoder_Stop(videoEncoder, NULL);
1204        NEXUS_StreamMux_Finish(streamMux);
1205            if(BKNI_WaitForEvent(finishEvent, 2000)!=BERR_SUCCESS) {
1206                BDBG_WRN(("TIMEOUT"));
1207            }
1208    }
1209#endif
1210    NEXUS_Record_Stop(record);
1211
1212    BDBG_WRN(("Recorded %u KB", (unsigned)get_filesize(opts.recfname)/1024));
1213
1214    NEXUS_Record_RemoveAllPidChannels(record);
1215#if NEXUS_HAS_VIDEO_ENCODER
1216    if (opts.encoder) {
1217        BKNI_DestroyEvent(finishEvent);
1218        /* stream mux must be stop after PID channel is removed from record since stream_mux stop would close the pid channel */
1219        NEXUS_StreamMux_Stop(streamMux);
1220    }
1221#endif
1222
1223    NEXUS_StcChannel_Close(stcChannel);
1224    if (source!=RecordSource_ePlayback) {
1225        NEXUS_PidChannel_CloseAll(parserBand0);
1226        if (opts.allpass) {
1227            NEXUS_PidChannel_Close(allpassPidChannel);
1228        }
1229    }
1230    else {
1231        if (opts.common.videoPid) {
1232            NEXUS_Playback_ClosePidChannel(playback0, videoPidChannel);
1233        }
1234        if(videoExtPidChannel) {
1235            NEXUS_Playback_ClosePidChannel(playback0, videoExtPidChannel);
1236        }
1237        if (opts.common.audioPid) {
1238            NEXUS_Playback_ClosePidChannel(playback0, audioPidChannel);
1239        }
1240        if (opts.allpass) {
1241            NEXUS_Playback_ClosePidChannel(playback1, allpassPidChannel);
1242        }
1243
1244        NEXUS_FilePlay_Close(playfile);
1245        NEXUS_Playback_Destroy(playback0);
1246        NEXUS_Playpump_Close(playpump0);
1247        if (opts.allpass) {
1248            NEXUS_Playback_Destroy(playback1);
1249            NEXUS_Playpump_Close(playpump1);
1250        }
1251    }
1252    NEXUS_FileRecord_Close(recfile);
1253    NEXUS_Record_Destroy(record);
1254    NEXUS_Recpump_Close(recpump);
1255
1256    NEXUS_AudioOutput_RemoveAllInputs(NEXUS_AudioDac_GetConnector(platformConfig.outputs.audioDacs[0]));
1257    NEXUS_AudioOutput_RemoveAllInputs(NEXUS_SpdifOutput_GetConnector(platformConfig.outputs.spdif[0]));
1258    NEXUS_AudioInput_Shutdown(NEXUS_AudioDecoder_GetConnector(audioDecoder, NEXUS_AudioDecoderConnectorType_eStereo));
1259    NEXUS_AudioDecoder_Close(audioDecoder);
1260    NEXUS_VideoWindow_Close(window);
1261    NEXUS_Display_Close(display);
1262
1263#if NEXUS_HAS_VIDEO_ENCODER
1264    if (opts.encoder) {
1265    NEXUS_Display_Close(displayTranscode);
1266    NEXUS_StreamMux_Destroy(streamMux);
1267    NEXUS_Playpump_Close(playpumpTranscodeVideo);
1268    NEXUS_Playpump_Close(playpumpTranscodePcr);
1269    NEXUS_VideoEncoder_Close(videoEncoder);
1270    }
1271#endif
1272        /* video decoder must be closed after the video input is removed from the display */
1273    NEXUS_VideoDecoder_Close(videoDecoder);
1274    NEXUS_Platform_Uninit();
1275
1276    return 0;
1277}
1278
1279#endif
1280
1281/*
1282************************************************
1283
1284examples / test cases
1285
1286#basic record from streamer input with decode
1287nexus record -video 0x21 -audio 0x24 -audio_type ac3 videos/test.mpg
1288    #with index
1289nexus record -video 0x21 -audio 0x24 -video_type mpeg2 -audio_type ac3 videos/test.mpg videos/test.nav
1290    #without decode
1291nexus record -decode off -video 0x21 -audio 0x24 -video_type mpeg2 videos/test.mpg videos/test.nav
1292
1293
1294#video-only record with index
1295nexus record -video 0x21 -video_type mpeg2 videos/test.mpg videos/test.nav
1296#audio-only record
1297nexus record -audio 0x24 videos/test.mpg
1298
1299
1300#record allpass from streamer input
1301nexus record -allpass videos/test.mpg
1302    #with index (0x21) and decode (0x21,0x24)
1303nexus record -allpass -video 0x21 -audio 0x24 -video_type mpeg2 -audio_type ac3 videos/test.mpg videos/test.nav
1304
1305
1306#record allpass from playback input
1307nexus record -allpass -playfile videos/test.mpg videos/test2.mpg
1308    #with index (0x21) and decode (0x21,0x24); the decode while record is of no use here
1309nexus record -allpass -playfile videos/test.mpg -video 0x21 -audio 0x24 -video_type mpeg2 -audio_type ac3 videos/test2.mpg videos/test2.nav
1310
1311
1312#record specified pids while indexing video pid
1313nexus record -video 0x11 -video_type mpeg2 -pids 0x14,0x21,0x24,0x41,0x44 videos/test.mpg
1314
1315#record specified pids while indexing video pid and transcoded into ts stream
1316nexus record -mpeg_type ts -audio 0x104 -audio_type ac3 -video 0x101 -video_type avc -playfile videos/avatar_AVC_15M.ts -component on -probe -decode on -encode -encode_video_type avc -encode_format 720p  -encode_frame_rate 24 -video_bit_rate 6000000 -gop_frameP 23 -gop_frameB 0 videos/record.mpg videos/record.nav
1317nexus record -mpeg_type ts -audio 0x104 -audio_type ac3 -video 0x101 -video_type avc -playfile videos/avatar_AVC_15M.ts -component on -probe -decode on videos/record.mpg videos/record.nav
1318
1319#allpass record from QAM
1320nexus record -qam 256 -freq 573 -allpass videos/qam_allpass.mpg
1321
1322*************************************************
1323*/
1324
Note: See TracBrowser for help on using the repository browser.