📄 play_capture.c
字号:
EMhwlibTVStandard_HDMI_1080p50, // 31 EMhwlibTVStandard_HDMI_1080p24, // 32 EMhwlibTVStandard_HDMI_1080p25, // 33 EMhwlibTVStandard_HDMI_1080p30, // 34 EMhwlibTVStandard_HDMI_2880x480p60, // 35 EMhwlibTVStandard_HDMI_2880x480p60, // 36 EMhwlibTVStandard_HDMI_2880x576p50, // 37 EMhwlibTVStandard_HDMI_2880x576p50, // 38 EMhwlibTVStandard_HDMI_1080i50_1250, // 39 EMhwlibTVStandard_HDMI_1080i100, // 40 EMhwlibTVStandard_HDMI_720p100, // 41 EMhwlibTVStandard_HDMI_576p100, // 42 EMhwlibTVStandard_HDMI_576p100, // 43 EMhwlibTVStandard_HDMI_576i100, // 44 EMhwlibTVStandard_HDMI_576i100, // 45 EMhwlibTVStandard_HDMI_1080i120, // 46 EMhwlibTVStandard_HDMI_720p120, // 47 EMhwlibTVStandard_HDMI_480p120, // 48 EMhwlibTVStandard_HDMI_480p120, // 49 EMhwlibTVStandard_HDMI_480i120, // 50 EMhwlibTVStandard_HDMI_480i120, // 51 EMhwlibTVStandard_HDMI_576p200, // 52 EMhwlibTVStandard_HDMI_576p200, // 53 EMhwlibTVStandard_HDMI_576i200, // 54 EMhwlibTVStandard_HDMI_576i200, // 55 EMhwlibTVStandard_HDMI_480p240, // 56 EMhwlibTVStandard_HDMI_480p240, // 57 EMhwlibTVStandard_HDMI_480i240, // 58 EMhwlibTVStandard_HDMI_480i240, // 59};/* Compare two values and return a weighted match value. Return value is 'weight' if both values are equal, or 50% of 'weight' minus the percentage points 'a' is away from 'b'. */static inline RMuint32 comp_weight(RMuint32 a, RMuint32 b, RMuint32 weight) { RMuint32 dist; if (a == b) return weight; dist = (a > b) ? a - b : b - a;// weight /= 2; dist = (dist * 100) / b; return (weight > dist) ? weight - dist : 0;}static RMascii *CEA861_ShortDescriptorVideoResolutions[] = { "Unknown", "VGA 640x480 60Hz", // 1 "480p 60Hz (4:3)", // 2 "480p 60Hz (16:9)", // 3 "720p 60Hz", // 4 "1080i 60Hz", // 5 "480i 60Hz (4:3)", // 6 "480i 60Hz (16:9)", // 7 "240p 60Hz (4:3)", // 8 "240p 60Hz (16:9)", // 9 "480i 60Hz (4:3)", // 10 "480i 60Hz (16:9)", // 11 "240p 60Hz (4:3)", // 12 "240p 60Hz (16:9)", // 13 "480p 60Hz (4:3)", // 14 "480p 60Hz (16:9)", // 15 "1080p 60Hz", // 16 "576p 50Hz (4:3)", // 17 "576p 50Hz (16:9)", // 18 "720p 50Hz", // 19 "1080i 50Hz", // 20 "576i 50Hz (4:3)", // 21 "576i 50Hz (16:9)", // 22 "288p 50Hz (4:3)", // 23 "288p 50Hz (16:9)", // 24 "576i 50Hz (4:3)", // 25 "576i 50Hz (16:9)", // 26 "288p 50Hz (4:3)", // 27 "288p 50Hz (16:9)", // 28 "576p 50Hz (4:3)", // 29 "576p 50Hz (16:9)", // 30 "1080p 50Hz", // 31 "1080p 24Hz", // 32 "1080p 25Hz", // 33 "1080p 30Hz", // 34 "480p 60Hz (4:3)", // 35 "480p 60Hz (16:9)", // 36 "576p 50Hz (4:3)", // 37 "576p 50Hz (16:9)", // 38 "1080i 50Hz", // 39 "1080i 100Hz", // 40 "720p 100Hz", // 41 "576p 100Hz (4:3)", // 42 "576p 100Hz (16:9)", // 43 "576i 100Hz (4:3)", // 44 "576i 100Hz (16:9)", // 45 "1080i 120Hz", // 46 "720p 120Hz", // 47 "480p 120Hz (4:3)", // 48 "480p 120Hz (16:9)", // 49 "480i 120Hz (4:3)", // 50 "480i 120Hz (16:9)", // 51 "576p 200Hz (4:3)", // 52 "576p 200Hz (16:9)", // 53 "576i 200Hz (4:3)", // 54 "576i 200Hz (16:9)", // 55 "480p 240Hz (4:3)", // 56 "480p 240Hz (16:9)", // 57 "480i 240Hz (4:3)", // 58 "480i 240Hz (16:9)", // 59};/* Detect video format from the line and pixel counter in the SiI9031 */static RMstatus get_format_SiI9031( struct dcc_context *dcc_info, struct capture_cmdline *options, struct local_cmdline *local_opt, RMuint8 dev, RMuint8 delay, RMbool *update){ RMstatus err; RMuint32 reg; RMuint8 data[17]; RMuint32 h_res, v_res, de_pix, de_lin, vid_vtavl, vid_vfp, vid_hfp, vid_hswidth, vid_xpcnt, pixel_rep, h_shift; RMbool intrl, vspol, hspol; RMuint32 i, best_match; enum EMhwlibTVStandard mode, old; RMascii *StandardName; RMbool limit861 = FALSE; /* whether to limit to CEA 861 modes */ if (update) *update = FALSE; old = options->TVStandard; /* read measurement registers from SiI9031 */ err = read_i2c(dcc_info->pRUA, delay, dev, 0x06, ®); if (RMFAILED(err)) return err; if ((reg & 0x03) != 0x03) { fprintf(stderr, "no %s%s%s!\n", (reg & 0x08) ? "" : "power", (reg & 0x02) ? "" : (reg & 0x08) ? "clock" : (reg & 0x01) ? " or clock" : ", clock", (reg & 0x01) ? "" : ((reg & 0x02) && (reg & 0x08)) ? "sync" : " or sync"); return RM_ERROR; } err = read_i2c(dcc_info->pRUA, delay, dev, 0x08, &pixel_rep); if (RMFAILED(err)) return err; pixel_rep = RMunshiftBits(pixel_rep, 2, 6); h_shift = (pixel_rep > 1) ? 2 : pixel_rep; err = read_i2c_data(dcc_info->pRUA, delay, dev, 0x3A, &data[0], 4); if (RMFAILED(err)) return err; err = read_i2c_data(dcc_info->pRUA, delay, dev, 0x4E, &data[4], 8); if (RMFAILED(err)) return err; err = read_i2c_data(dcc_info->pRUA, delay, dev, 0x59, &data[12], 4); if (RMFAILED(err)) return err; err = read_i2c_data(dcc_info->pRUA, delay, dev, 0x6F, &data[16], 1); if (RMFAILED(err)) return err; h_res = (data[0] & 0xFF); h_res |= ((data[1] & 0x1F) << 8); v_res = (data[2] & 0xFF); v_res |= ((data[3] & 0x07) << 8); de_pix = (data[4] & 0xFF); de_pix |= ((data[5] & 0x1F) << 8); de_lin = (data[6] & 0xFF); de_lin |= ((data[7] & 0x07) << 8); vid_vtavl = (data[8] & 0x3F); vid_vfp = (data[9] & 0x3F); intrl = (data[11] & 0x04) ? TRUE : FALSE; vspol = (data[11] & 0x02) ? TRUE : FALSE; hspol = (data[11] & 0x01) ? TRUE : FALSE; vid_hfp = (data[12] & 0xFF); vid_hswidth = (data[14] & 0xFF); vid_hswidth |= ((data[15] & 0x03) << 8); vid_xpcnt = (data[16] & 0xFF); if (pixel_rep) { h_res >>= h_shift; de_pix >>= h_shift; vid_hfp >>= h_shift; vid_hswidth >>= h_shift; vid_xpcnt >>= h_shift; } fprintf(stderr, "SiI9031 - %lux%lu%c, total:%lux%lu, vsync:%lu-%lu-x-%s., hsync:%lu-%lu-%lu-%s., xpcnt:%lu\n", de_pix, de_lin * (intrl ? 2 : 1), intrl ? 'i' : 'p', h_res, intrl ? v_res * 2 + 1 : v_res, vid_vfp, vid_vtavl, vspol ? "pos" : "neg", vid_hfp, vid_hswidth, h_res - de_pix - vid_hfp - vid_hswidth, hspol ? "pos" : "neg", vid_xpcnt); if (! update) return RM_OK; best_match = 0; i = limit861 ? 0 : 1; while (limit861 ? (i < (sizeof(cea861c) / sizeof(enum EMhwlibTVStandard))) : RMSUCCEEDED(GetTVStandardName((enum EMhwlibTVStandard)i, &StandardName))) { struct EMhwlibTVFormatDigital dig; RMuint32 match; RMbool dig_Intrl, dig_1001; // skip dual-aspect-ratio modes, checking for one is enough if (limit861 && (i > 0) && (cea861c[i - 1] == cea861c[i])) { i++; continue; } mode = limit861 ? cea861c[i] : (enum EMhwlibTVStandard)i; err = RUAExchangeProperty(dcc_info->pRUA, DisplayBlock, RMDisplayBlockPropertyID_TVFormatDigital, &mode, sizeof(mode), &dig, sizeof(dig)); if RMFAILED(err) { fprintf(stderr, "Could not get format!\n"); return err; } dig_1001 = ( (dig.PixelClock == 25174825) || (dig.PixelClock == 74175824) || (dig.PixelClock == 148351648) || (( (dig.ActiveHeight == 240) || (dig.ActiveHeight == 480) ) && ( (dig.PixelClock == 27000000) || (dig.PixelClock == 54000000) || (dig.PixelClock == 108000000) )) ); // skip X*1000/1001 frame rate modes, capture does not discriminate between those and X*1 modes if (dig_1001) { i++; continue; } dig_Intrl = (dig.TopFieldHeight != 0); if (dig_Intrl) dig.VTotalSize = (dig.VTotalSize + 1) / 2; /*if (mode == EMhwlibTVStandard_HDMI_1080i60) { fprintf(stderr, "1080i60 video format: \nh_res = %lu\nv_res = %lu\nde_pix = %lu\nde_lin = %lu\nvid_vtavl = %lu\nvid_vfp = %lu\nvid_hfp = %lu\nvid_hswidth = %lu\nvid_xpcnt = %lu\nintrl = %u\nvspol = %u\nhspol = %u\n", dig.HTotalSize, dig.VTotalSize, dig.ActiveWidth, dig.ActiveHeight, dig.YOffsetTop, dig.VTotalSize - dig.ActiveHeight - dig.YOffsetTop, dig.HTotalSize - dig.ActiveWidth - dig.XOffset, dig.HSyncWidth, (RMuint32)(28322000LL * 128LL / dig.PixelClock), dig_Intrl, ! dig.VSyncActiveLow, ! dig.HSyncActiveLow);}*/ match = 0; match += comp_weight(h_res, dig.HTotalSize, 20); match += comp_weight(v_res, dig.VTotalSize, 20); match += comp_weight(de_pix, dig.ActiveWidth, 20); match += comp_weight(de_lin, dig.ActiveHeight, 20); //match += comp_weight(vid_vtavl, dig.YOffsetTop, 12); //match += comp_weight(vid_vfp, dig.VTotalSize - dig.ActiveHeight - dig.YOffsetTop, 12); //match += comp_weight(vid_hfp, dig.HTotalSize - dig.ActiveWidth - dig.XOffset, 12); //match += comp_weight(vid_hswidth, dig.HSyncWidth, 12); match += comp_weight(vid_xpcnt, RM64mult32div32(28322000, 128, dig.PixelClock), 20); if (intrl == dig_Intrl) match += 32; if (vspol == ! dig.VSyncActiveLow) match += 20; if (hspol == ! dig.HSyncActiveLow) match += 20; if (match > best_match) { best_match = match; options->TVStandard = mode; //GetTVStandardName(mode, &StandardName); //fprintf(stderr, "%s scores %lu\n", StandardName, match); } i++; } if (options->TVStandard != old) { GetTVStandardName(options->TVStandard, &StandardName); fprintf(stderr, "Detected new mode from timing: %s\n", StandardName); *update = TRUE; } err = read_i2c_data(dcc_info->pRUA, delay, dev + 4, 0x2A, &data[0], 3); if (RMFAILED(err)) return err; err = read_i2c_data(dcc_info->pRUA, delay, dev + 4, 0x30, &data[3], 2); if (RMFAILED(err)) return err; fprintf(stderr, "SiI9031 audio channel status [39:0]: %02X %02X %02X %02X %02X\n", data[4], data[3], data[2], data[1], data[0]); return RM_OK;}static RMstatus get_spdif_status( struct dcc_context *dcc_info, struct audio_cmdline *audio_opt){ RMstatus err; struct AudioEngine_InputSPDIFStatus_type stat; err = RUAGetProperty(dcc_info->pRUA, EMHWLIB_MODULE(AudioEngine, audio_opt->AudioEngineID), RMAudioEnginePropertyID_InputSPDIFStatus, &stat, sizeof(stat)); if (RMSUCCEEDED(err)) { fprintf(stderr, "Audio Input channel status [18:0]: 0x%05lX Pc:%04X Pd:%04X Pe:%04X Pf:%04X\n", stat.ChannelStatus, stat.Pc, stat.Pd, stat.Pe, stat.Pf); } return err;}// Set up local and capture options (zoom, aspect ratio etc.) based on capture_opt->TVStandardstatic RMstatus setup_format_options( struct dcc_context *dcc_info, struct capture_cmdline *capture_opt, struct display_cmdline *disp_opt, struct local_cmdline *local_opt, RMuint32 input){ struct EMhwlibActiveFormatDescription afd; afd.ActiveFormat = local_opt->active_format; afd.ActiveFormatValid = TRUE; afd.FrameAspectRatio.X = 4; afd.FrameAspectRatio.Y = 3; switch (capture_opt->TVStandard) { case EMhwlibTVStandard_Custom: fprintf(stderr, "No sync or video detected!\n"); break; case EMhwlibTVStandard_ITU_Bt656_525: case EMhwlibTVStandard_ITU_Bt656_240p: { // NTSC only part capture_opt->PixelAspectRatio.X = 8; capture_opt->PixelAspectRatio.Y = 9; if (local_opt->parse_anc) { capture_opt->vbianc_w = 12; capture_opt->vbianc_h = 3; capture_opt->vbianc_ytop = 16; capture_opt->vbianc_ybot = 17; capture_opt->vbianc_enable = TRUE; //capture_opt->vbi_dma = FALSE; fprintf(stderr, "*** NTSC ClosedCaption, setting up capture window w=%lu, h=%lu, ytop=%lu, ybot=%lu ***\n", capture_opt->vbianc_w, capture_opt->vbianc_h, capture_opt->vbianc_ytop, capture_opt->vbianc_ybot); } else { capture_opt->vbianc_enable = FALSE; } // full screen minus top 4 and bottom 3 lines of each frame if (! local_opt->zoom_force) { local_opt->zoom_x = 0; local_opt->zoom_y = 4; // discard top 2 lines of each field, containing VBI data in ITU656-525 mode local_opt->zoom_w = 720; local_opt->zoom_h = 480; // discard bottom 3 lines of each frame to match standard picture size } if (capture_opt->TVStandard == EMhwlibTVStandard_ITU_Bt656_240p) { capture_opt->PixelAspectRatio.Y *= 2; if (! local_opt->zoom_force) { local_opt->zoom_h /= 2; } } } if (0) case EMhwlibTVStandard_ITU_Bt656_625: case EMhwlibTVStandard_ITU_Bt656_288p: { // PAL only part capture_opt->PixelAspectRatio.X = 16; capture_opt->PixelAspectRatio.Y = 15; if (local_opt->parse_anc) { capture_opt->vbianc_w = 52; capture_opt->vbianc_h = 18; capture_opt->vbianc_ytop = 5; capture_opt->vbianc_ybot = 5; capture_opt->vbianc_enable = TRUE; //capture_opt->vbi_dma = TRUE; fprintf(stderr, "*** PAL TeleText, setting up capture window w=%lu, h=%lu, ytop=%lu, ybot=%lu ***\n", capture_opt->vbianc_w, capture_opt->vbianc_h, capture_opt->vbianc_ytop, capture_opt->vbianc_ybot); } else { capture_opt->vbianc_enable = FALSE; } // full screen capture if (! local_opt->zoom_force) { local_opt->zoom_x = 0; local_opt->zoom_y = 0; local_opt->zoom_w = 720; local_opt->zoom_h = 576; } if (capture_opt->TVStandard == EMhwlibTVStandard_ITU_Bt656_288p) { capture_opt->PixelAspectRatio.Y *= 2; if (! local_opt->zoom_force) { local_opt->zoom_h /= 2; } } } { // PAL/NTSC common part // disable picture aspect ratio, using pixel aspect ratio capture_opt->PictureAspectRatio.X = 0; capture_opt->PictureAspectRatio.Y = 0; // Set up wide and clipping mode if (local_opt->wide_screen) { // 16:9 output capture_opt->PixelAspectRatio.X *= 4; capture_opt->PixelAspectRatio.Y *= 3; afd.FrameAspectRatio.X *= 4; afd.FrameAspectRatio.Y *= 3; } if (! local_opt->zoom_force) { RMstatus err; struct EMhwlibAspectRatio scaler_ar; RMbool output_variable_ar, variable_output; struct EMhwlibActiveFormatDescription output_afd; RMuint32 w = local_opt->zoom_w, h = local_opt->zoom_h, adj; err = get_scaler_output_aspect_ra
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -