| 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 | |
|---|
| 200 | BDBG_MODULE(record); |
|---|
| 201 | |
|---|
| 202 | #if !NEXUS_HAS_RECORD |
|---|
| 203 | int 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 | |
|---|
| 215 | typedef enum RecordSource { |
|---|
| 216 | RecordSource_eStreamer, |
|---|
| 217 | RecordSource_ePlayback, |
|---|
| 218 | RecordSource_eVsb, |
|---|
| 219 | RecordSource_eQam, |
|---|
| 220 | RecordSource_eSat, |
|---|
| 221 | RecordSource_eHdmiInput |
|---|
| 222 | } RecordSource; |
|---|
| 223 | |
|---|
| 224 | static 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 | |
|---|
| 235 | struct timeval startTime; |
|---|
| 236 | static 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(¤tTime, 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 |
|---|
| 257 | BKNI_EventHandle lockEvent; |
|---|
| 258 | static 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 |
|---|
| 294 | static void |
|---|
| 295 | transcoderFinishCallback(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 | |
|---|
| 305 | int 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 | |
|---|
| 1284 | examples / test cases |
|---|
| 1285 | |
|---|
| 1286 | #basic record from streamer input with decode |
|---|
| 1287 | nexus record -video 0x21 -audio 0x24 -audio_type ac3 videos/test.mpg |
|---|
| 1288 | #with index |
|---|
| 1289 | nexus record -video 0x21 -audio 0x24 -video_type mpeg2 -audio_type ac3 videos/test.mpg videos/test.nav |
|---|
| 1290 | #without decode |
|---|
| 1291 | nexus record -decode off -video 0x21 -audio 0x24 -video_type mpeg2 videos/test.mpg videos/test.nav |
|---|
| 1292 | |
|---|
| 1293 | |
|---|
| 1294 | #video-only record with index |
|---|
| 1295 | nexus record -video 0x21 -video_type mpeg2 videos/test.mpg videos/test.nav |
|---|
| 1296 | #audio-only record |
|---|
| 1297 | nexus record -audio 0x24 videos/test.mpg |
|---|
| 1298 | |
|---|
| 1299 | |
|---|
| 1300 | #record allpass from streamer input |
|---|
| 1301 | nexus record -allpass videos/test.mpg |
|---|
| 1302 | #with index (0x21) and decode (0x21,0x24) |
|---|
| 1303 | nexus 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 |
|---|
| 1307 | nexus 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 |
|---|
| 1309 | nexus 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 |
|---|
| 1313 | nexus 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 |
|---|
| 1316 | nexus 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 |
|---|
| 1317 | nexus 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 |
|---|
| 1320 | nexus record -qam 256 -freq 573 -allpass videos/qam_allpass.mpg |
|---|
| 1321 | |
|---|
| 1322 | ************************************************* |
|---|
| 1323 | */ |
|---|
| 1324 | |
|---|