📄 hdmi.c
字号:
avi->top, avi->bottom)); //RMDBGPRINT((ENABLE, "+-----+-----+-----+-----+-----+-----+-----+-----+\n")); RMDBGPRINT((ENABLE, "| Left vBar = %-5lu | Right vBar = %-5lu |\n", avi->left, avi->right)); RMDBGPRINT((ENABLE, "+-----+-----+-----+-----+-----+-----+-----+-----+\n")); return RM_OK;}/*** Handling Info Frames ***//* Parses an Audio CP info frame, returns the filled struct */RMstatus cap_hdmi_parse_audio_cp_packet( struct cap_hdmi_instance *pHDMI, RMuint8 *header, RMuint8 *data, struct DH_AudioCP_Info *pAudioCP){ RMuint32 Type; RMDBGLOG((ENABLE, "[hdmi] new Audio CP InfoFrame\n")); Type = header[1]; if (pAudioCP) pAudioCP->Type = (enum DH_AudioCP_Type)Type; switch (Type) { case 0: RMDBGLOG((ENABLE, "[hdmi] Generic Audio\n")); break; case 1: RMDBGLOG((ENABLE, "[hdmi] IEC 60958 Audio\n")); break; case 2: { RMuint32 Generation, Transaction, Quality, CopyNumber, CopyPermission; if (pAudioCP) { pAudioCP->DVDAudio_generation = data[0]; pAudioCP->DVDAudio_copy = data[1]; } Generation = data[0]; Transaction = RMunshiftBits(data[1], 1, 0); Quality = RMunshiftBits(data[1], 2, 1); CopyNumber = RMunshiftBits(data[1], 3, 3); CopyPermission = RMunshiftBits(data[1], 2, 6); RMDBGLOG((ENABLE, "[hdmi] DVD Audio, Generation=%lu, Transaction=%lu, Quality=%lu, CopyNumber=%lu, CopyPermission=%lu\n", Generation, Transaction, Quality, CopyNumber, CopyPermission)); } break; case 3: { RMuint32 i; if (pAudioCP) { RMMemcpy(pAudioCP->SuperAudioCD_CCI_1, data, 16); } RMDBGLOG((ENABLE, "[hdmi] Super Audio CD, CCI_1 =")); for (i = 0; i < 16; i++) { if (i % 4 == 0) RMDBGPRINT((ENABLE, " ")); RMDBGPRINT((ENABLE, "%02X", data[i])); } RMDBGPRINT((ENABLE, "\n")); } break; default: RMDBGLOG((ENABLE, "[hdmi] Unknown AudioCP: %lu\n", Type)); } return RM_OK;}/* Parses an ISRC1 info frame, return RM_PENDING if not new If not continued in ISRC2, fills in 16 bytes in pISRC and sets *pISRCSize, otherwise *pISRCSize will be set to 0. */RMstatus cap_hdmi_parse_isrc1_packet( struct cap_hdmi_instance *pHDMI, RMuint8 *header, RMuint8 *data, RMuint32 *pISRCSize, RMuint8 *pISRC){ RMuint32 i, Status; RMbool Continued, Valid; // Sanity checks if (pHDMI == NULL) return RM_FATALINVALIDPOINTER; if (pISRCSize) *pISRCSize = 0; if ((header[1] == pHDMI->last_isrc_header) && ! RMMemcmp(&(pHDMI->last_isrc[0]), data, 16)) { return RM_PENDING; } RMDBGLOG((ENABLE, "[hdmi] new ISRC1 InfoFrame\n")); pHDMI->last_isrc_header = header[1]; pHDMI->last_isrc2 = FALSE; RMMemcpy(&(pHDMI->last_isrc[0]), data, 16); RMMemset(&(pHDMI->last_isrc[16]), 0, 16); Status = RMunshiftBits(header[1], 3, 0); Valid = RMunshiftBool(header[1], 6); Continued = RMunshiftBool(header[1], 7); RMDBGLOG((ENABLE, "[hdmi] ISRC Valid: %s, Cont. in ISRC2: %s, %s position\n", Valid ? "yes" : "no", Continued ? "yes" : "no", (Status == 1) ? "starting" : (Status == 2) ? "intermediate" : (Status == 4) ? "ending" : "unknown")); if (! Continued) { RMDBGLOG((ENABLE, "[hdmi] ISRC 0..15 =")); for (i = 0; i < 16; i++) { if (i % 4 == 0) RMDBGPRINT((ENABLE, " ")); RMDBGPRINT((ENABLE, "%02X", data[i])); } RMDBGPRINT((ENABLE, "\n")); if (pISRC && pISRCSize) { RMMemcpy(pISRC, data, 16); *pISRCSize = 16; } } return RM_OK;}/* Parses an ISRC2 info frame, return RM_PENDING if not new. otherwise fills in 32 bytes from ISRC1 and ISRC2 into pISRC and sets *pISRCSize */RMstatus cap_hdmi_parse_isrc2_packet( struct cap_hdmi_instance *pHDMI, RMuint8 *header, RMuint8 *data, RMuint32 *pISRCSize, RMuint8 *pISRC){ RMuint32 i; // Sanity checks if (pHDMI == NULL) return RM_FATALINVALIDPOINTER; if (pISRCSize) *pISRCSize = 0; if (! RMMemcmp(&(pHDMI->last_isrc[16]), data, 16)) { return RM_PENDING; } RMDBGLOG((ENABLE, "[hdmi] new ISRC2 InfoFrame\n")); pHDMI->last_isrc2 = TRUE; RMMemcpy(&(pHDMI->last_isrc[16]), data, 16); if (pHDMI->last_isrc_header & 0x80) { RMDBGLOG((ENABLE, "[hdmi] ISRC 0..31 =")); for (i = 0; i < 32; i++) { if (i % 4 == 0) RMDBGPRINT((ENABLE, " ")); RMDBGPRINT((ENABLE, "%02X", pHDMI->last_isrc[i])); } RMDBGPRINT((ENABLE, "\n")); if (pISRC && pISRCSize) { RMMemcpy(pISRC, pHDMI->last_isrc, 32); *pISRCSize = 32; } } return RM_OK;}/* parses and prints a gamut metadata packet */RMstatus cap_hdmi_parse_gamut_packet( struct cap_hdmi_instance *pHDMI, RMuint8 *header, RMuint8 *data, struct DH_GamutMetadata *pGamutMetadata){ RMuint32 GBDProfile, AffSeqNum, PacketSeq, CurrSeqNum; RMbool NextField, NoCurrGBD; RMuint32 i, start, len; RMDBGLOG((ENABLE, "[hdmi] new Gamut InfoFrame\n")); NextField = RMunshiftBool(header[1], 7); GBDProfile = RMunshiftBits(header[1], 3, 4); AffSeqNum = RMunshiftBits(header[1], 4, 0); NoCurrGBD = RMunshiftBool(header[2], 7); PacketSeq = RMunshiftBits(header[2], 2, 4); CurrSeqNum = RMunshiftBits(header[2], 4, 0); RMDBGLOG((ENABLE, "[hdmi] Gamut Boundary Description Profile: P%lu\n", GBDProfile)); RMDBGLOG((ENABLE, "[hdmi] Next Field: %s, No Current GBD: %s, Affected Seq.#%lu, Current Seq.#%lu, %s Packet\n", NextField ? "yes" : "no", NoCurrGBD ? "yes" : "no", AffSeqNum, CurrSeqNum, (PacketSeq == 0) ? "Intermediate" : (PacketSeq == 1) ? "First" : (PacketSeq == 2) ? "Last" : (PacketSeq == 3) ? "Only" : "Invalid")); start = 0; len = 28; if ((GBDProfile > 0) && (PacketSeq & 1)) { RMuint32 Length; Length = data[0]; Length = (Length << 8) | data[1]; RMDBGLOG((ENABLE, "[hdmi] GBD Length: %lu, checksum: 0x%02X\n", Length, data[2])); start = 3; len -= start; } RMDBGLOG((ENABLE, "[hdmi] GBD =")); for (i = start; i < len; i++) { if ((i - start) % 4 == 0) RMDBGPRINT((ENABLE, " ")); RMDBGPRINT((ENABLE, "%02X", data[i])); } RMDBGPRINT((ENABLE, "\n")); // TODO parse into struct DH_GamutMetadata (TBD), concatenate sequential frames if necessary return RM_OK;}/* parse vendor-specific info frame */RMstatus cap_hdmi_parse_vendor_info_frame( struct cap_hdmi_instance *pHDMI, RMuint8 *header, RMuint8 *data, RMuint32 *pVendorID, RMuint8 *pVendorData, RMuint32 *pVendorDataSize){ RMuint32 Version, Length, VendorID; RMDBGLOG((ENABLE, "[hdmi] new Vendor InfoFrame\n")); Version = header[1]; Length = header[2]; VendorID = 0; RMinsShiftBits(&VendorID, data[1], 8, 0); RMinsShiftBits(&VendorID, data[2], 8, 8); RMinsShiftBits(&VendorID, data[3], 8, 16); if (pVendorID) *pVendorID = VendorID; if (pVendorData) RMMemcpy(pVendorData, &(data[4]), Length - 3); if (pVendorDataSize) *pVendorDataSize = Length - 3; RMDBGLOG((ENABLE, "[hdmi] IEEE Vendor ID: 0x%06lX, Version: %lu, Length: %lu\n", VendorID, Version, Length)); return RM_OK;}RMstatus cap_hdmi_handle_avi_info_frame( struct cap_hdmi_instance *pHDMI, struct cap_hdmi_avi_info *avi, struct cap_update *pUpdate){ RMstatus err; RMbool upsample_from_422 = FALSE;// RMbool update_mode = FALSE;// RMbool update_zoom = FALSE; struct EMhwlibAspectRatio avi_asp, asp; RMuint32 x, y, w, h; RMbool force; // force update, even if information is unchanged enum EMhwlibScanInfo scan = EMhwlibScanInfo_NoData; RMDBGLOG((FUNCNAME, "%s\n",__func__)); force = ! pHDMI->last_avi.valid; if (force || RMMemcmp(avi, &(pHDMI->last_avi), sizeof(struct cap_hdmi_avi_info))) { cap_hdmi_print_avi_info_frame(pHDMI, NULL, NULL, avi); } // Set up pixel clock reduction in HDMI capture chip according to pixel repetition value if (force || (avi->pixel_rep != pHDMI->last_avi.pixel_rep)) { RMDBGLOG((ENABLE, "newavi - each pixel sent %lu times by source\n", avi->pixel_rep + 1)); err = cap_hdmi_apply_pixelrep(pHDMI, avi->pixel_rep); if (RMSUCCEEDED(err)) { avi->in_pixel_rep = 0; // HDMI chip output is reduced, pixel are no longer repeated } else { if (err == RM_NOT_SUPPORTED) { // TODO: use literal timing information, not reduced one } avi->in_pixel_rep = avi->pixel_rep; } } else if (pHDMI->last_avi.valid) { avi->in_pixel_rep = pHDMI->last_avi.in_pixel_rep; } else { avi->in_pixel_rep = 0; } if (avi->pixel_rep != pHDMI->last_avi.pixel_rep) { // unused for now RMDBGLOG((ENABLE, "newavi - each pixel sent %lu times by source\n", avi->pixel_rep + 1)); } // Apply new color space and color format from AVI if (force || (avi->color_format != pHDMI->last_avi.color_format) || (avi->color_space != pHDMI->last_avi.color_space)) { enum EMhwlibColorSpace cs = pHDMI->InputColorSpace; enum EMhwlibInputColorFormat icf = pHDMI->InputColorFormat; switch (avi->color_format) { case 0: RMDBGLOG((ENABLE, "newavi - RGB 888\n")); icf = EMhwlibInputColorFormat_24BPP; switch (avi->quantisation) { case 0: cs = (avi->vic > 1) ? EMhwlibColorSpace_RGB_16_235 : EMhwlibColorSpace_RGB_0_255; break; case 1: cs = EMhwlibColorSpace_RGB_16_235; break; case 2: cs = EMhwlibColorSpace_RGB_0_255; break; default: RMDBGLOG((ENABLE, "newavi - unknown RGB quantisation range code: %lu\n", avi->quantisation)); cs = (avi->vic > 1) ? EMhwlibColorSpace_RGB_16_235 : EMhwlibColorSpace_RGB_0_255; } switch (avi->color_space) { // colorspace to which RGB should be converted to on YCbCr outputs case 0: RMDBGLOG((ENABLE, "newavi - RGB for undefined YCbCr\n")); break; case 1: RMDBGLOG((ENABLE, "newavi - RGB for YCbCr 601\n")); break; case 2: RMDBGLOG((ENABLE, "newavi - RGB for YCbCr 709\n")); break; case 3: // extended switch (avi->ext_col) { case 0: RMDBGLOG((ENABLE, "newavi - RGB for xvYCC 601\n")); break; case 1: RMDBGLOG((ENABLE, "newavi - RGB for xvYCC 709\n")); break; default: RMDBGLOG((ENABLE, "newavi - unknown extended color space code for RGB: %lu\n", avi->ext_col)); } break; default: RMDBGLOG((ENABLE, "newavi - unknown color space code for RGB: %lu\n", avi->color_space)); } break; case 1: RMDBGLOG((ENABLE, "newavi - YCbCr 4:2:2\n")); upsample_from_422 = TRUE; if (0) // prevent first line of next case from being executed // no break; case 2: RMDBGLOG((ENABLE, "newavi - YCbCr 4:4:4\n")); icf = EMhwlibInputColorFormat_24BPP; switch (avi->color_space) { case 0: RMDBGLOG((ENABLE, "newavi - no data on YCbCr colorspace, assuming VIC default!\n")); if ((avi->vic == 4) || (avi->vic == 5) || (avi->vic == 16) || (avi->vic == 19) || (avi->vic == 20) || ((avi->vic >= 31) && (avi->vic <= 34)) || (avi->vic == 39) || (avi->vic == 40) || (avi->vic == 41) || (avi->vic == 46) || (avi->vic == 47)) { cs = EMhwlibColorSpace_YUV_709; } else { cs = EMhwlibColorSpace_YUV_601; } break; case 1: cs = EMhwlibColorSpace_YUV_601; break; case 2: cs = EMhwlibColorSpace_YUV_709; break; case 3: // extended switch (avi->ext_col) { case 0: cs = EMhwlibColorSpace_xvYCC_601; break; case 1: cs = EMhwlibColorSpace_xvYCC_709; break; default: RMDBGLOG((ENABLE, "newavi - unknown extended color space code: %lu\n", avi->ext_col)); break; } break; default: RMDBGLOG((ENABLE, "newavi - unknown color space code: %lu\n", avi->color_space)); } break; default: RMDBGLOG((ENABLE, "newavi - unknown color sampling code: %lu\n", avi->color_format)); } // handle changes if (upsample_from_422 != pHDMI->upsample_from_422) { pHDMI->upsample_from_422 = upsample_from_422; // TODO switch chip cap_SiI9031_set_422_to_444_upsampling(pHDMI->pChip->instance.pSiI9031, upsample_from_422); } if (cs != pHDMI->InputColorSpace) { RMDBGLOG((ENABLE, "newavi - color space: %s\n", (cs == EMhwlibColorSpace_RGB_0_255) ? "RGB 0-255" : (cs == EMhwlibColorSpace_RGB_16_235) ? "RGB 16-235" : (cs == EMhwlibColorSpace_YUV_601) ? "YUV601" : (cs == EMhwlibColorSpace_YUV_709) ? "YUV709" : (cs == EMhwlibColorSpace_xvYCC_601) ? "xvYCC601" : (cs == EMhwlibColorSpace_xvYCC_709) ? "xvYCC709" : "unknown")); pHDMI->InputColorSpace = cs; if (pUpdate && (pUpdate->APIVersion >= 1)) { pUpdate->InputColorSpaceUpdate = TRUE; } // TODO switch chip cap_SiI9031_set_blanking_color(pHDMI->pChip->instance.pSiI9031, cs); } if (icf != pHDMI->InputColorFormat) { RMDBGLOG((ENABLE, "newavi - sampling mode: %s\n", (icf == EMhwlibInputColorFormat_24BPP) ? ((cs == EMhwlibColorSpace_RGB_0_255) ? "RGB" : "4:4:4") : "4:2:2")); pHDMI->InputColorFormat = icf; if (pUpdate && (pUpdate->APIVersion >= 1)) { pUpdate->InputColorFormatUpdate = TRUE;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -