static bool ParseBaselineVideoConfiguration()

in src/cdi/baseline_profiles_1_00.c [482:703]


static bool ParseBaselineVideoConfiguration(const CdiAvmConfig* config_ptr, CdiAvmBaselineConfigCommon* baseline_ptr)
{
    bool ret = true;
    CdiAvmBaselineConfig* baseline_config_ptr = (CdiAvmBaselineConfig*)baseline_ptr;

    // Make a copy of the data array since CdiOsStrTokR is destructive. +1 for terminating NUL character.
    char copy_str[sizeof(config_ptr->data) + 1];
    memcpy(copy_str, config_ptr->data, config_ptr->data_size);
    copy_str[config_ptr->data_size] = '\0';

    CdiAvmVideoConfig* video_config_ptr = &baseline_config_ptr->video_config;

    // Set non-zero, optional, default video configuration values.
    video_config_ptr->par_width = 1;
    video_config_ptr->par_height = 1;

    // Break the string up into semicolon separated tokens.
    int i = 0;
    char* param_save_ptr = NULL;
    for (char* param_ptr = copy_str ; ret && NULL != param_ptr ; i++) {
        param_ptr = CdiOsStrTokR((i == 0) ? param_ptr : NULL, "; ", &param_save_ptr);
        if (param_ptr != NULL) {
            char* value_ptr = strchr(param_ptr, '=');
            if (NULL != value_ptr) {
                // Replace '=' with NUL character so ptr is terminated. Increment value_ptr so it points to the value
                // which is already NUL terminated by CdiOsStrTokR().
                *(value_ptr++) = '\0';
            }
            if (0 == CdiOsStrCaseCmp(param_ptr, "cdi_profile_version")) {
                if (NULL == value_ptr) {
                    CDI_LOG_THREAD(kLogError, "video profile version parameter value is missing");
                    ret = false;
                } else {
                    if (!CdiAvmParseBaselineVersionString(value_ptr, &video_config_ptr->version)) {
                        CDI_LOG_THREAD(kLogError, "unable to parse video profile version parameter value [%s]",
                                       value_ptr);
                        ret = false;
                    }
                }
            } else if (0 == CdiOsStrCaseCmp(param_ptr, "sampling")) {
                if (NULL == value_ptr) {
                    CDI_LOG_THREAD(kLogError, "video sampling parameter value is missing");
                    ret = false;
                } else {
                    int key = CdiAvmKeyStringToEnum(kKeyAvmVideoSamplingType, value_ptr,
                                                    &video_config_ptr->version);
                    if (CDI_INVALID_ENUM_VALUE == key) {
                        CDI_LOG_THREAD(kLogError, "unknown video sampling value [%s]", value_ptr);
                        ret = false;
                    } else {
                        video_config_ptr->sampling = (CdiAvmVideoSampling)key;
                    }
                }
            } else if (0 == CdiOsStrCaseCmp(param_ptr, "depth")) {
                if (NULL == value_ptr) {
                    CDI_LOG_THREAD(kLogError, "video depth parameter value is missing");
                    ret = false;
                } else {
                    int bit_depth = atoi(value_ptr);
                    switch (bit_depth) {
                        case 8:
                            video_config_ptr->depth = kCdiAvmVidBitDepth8;
                            break;
                        case 10:
                            video_config_ptr->depth = kCdiAvmVidBitDepth10;
                            break;
                        case 12:
                            video_config_ptr->depth = kCdiAvmVidBitDepth12;
                            break;
                        default:
                            CDI_LOG_THREAD(kLogError, "invalid video bit depth value [%s]", value_ptr);
                            ret = false;
                            break;
                    }
                }
            } else if (0 == CdiOsStrCaseCmp(param_ptr, "width")) {
                if (NULL == value_ptr) {
                    CDI_LOG_THREAD(kLogError, "video width parameter value is missing");
                    ret = false;
                } else {
                    video_config_ptr->width = atoi(value_ptr);
                }
            } else if (0 == CdiOsStrCaseCmp(param_ptr, "height")) {
                if (NULL == value_ptr) {
                    CDI_LOG_THREAD(kLogError, "video height parameter value is missing");
                    ret = false;
                } else {
                    video_config_ptr->height = atoi(value_ptr);
                }
            } else if (0 == CdiOsStrCaseCmp(param_ptr, "exactframerate")) {
                if (NULL == value_ptr) {
                    CDI_LOG_THREAD(kLogError, "video exactframerate parameter value is missing");
                    ret = false;
                } else {
                    char* denominator_ptr = strchr(value_ptr, '/');
                    if (NULL != denominator_ptr) {
                        *(denominator_ptr++) = '\0';
                        video_config_ptr->frame_rate_den = atoi(denominator_ptr);
                    } else {
                        video_config_ptr->frame_rate_den = 1;
                    }
                    video_config_ptr->frame_rate_num = atoi(value_ptr);
                }
            } else if (0 == CdiOsStrCaseCmp(param_ptr, "colorimetry")) {
                if (NULL == value_ptr) {
                    CDI_LOG_THREAD(kLogError, "video colorimetry parameter value is missing");
                    ret = false;
                } else {
                    int key = CdiAvmKeyStringToEnum(kKeyAvmVideoColorimetryType, value_ptr,
                                                    &video_config_ptr->version);
                    if (CDI_INVALID_ENUM_VALUE == key) {
                        CDI_LOG_THREAD(kLogError, "unknown video colorimetry value [%s]", value_ptr);
                        ret = false;
                    } else {
                        video_config_ptr->colorimetry = (CdiAvmColorimetry)key;
                    }
                }
            } else if (0 == CdiOsStrCaseCmp(param_ptr, "interlace")) {
                if (NULL != value_ptr) {
                    CDI_LOG_THREAD(kLogWarning, "value for video interlace parameter ignored [%s]", value_ptr);
                } else {
                    video_config_ptr->interlace = true;
                }
            } else if (0 == CdiOsStrCaseCmp(param_ptr, "segmented")) {
                if (NULL != value_ptr) {
                    CDI_LOG_THREAD(kLogWarning, "value for video segmented parameter ignored [%s]", value_ptr);
                } else {
                    video_config_ptr->segmented = true;
                }
            } else if (0 == CdiOsStrCaseCmp(param_ptr, "TCS")) {
                if (NULL == value_ptr) {
                    CDI_LOG_THREAD(kLogError, "video TCS parameter value is missing");
                    ret = false;
                } else {
                    int key = CdiAvmKeyStringToEnum(kKeyAvmVideoTcsType, value_ptr,
                                                    &video_config_ptr->version);
                    if (CDI_INVALID_ENUM_VALUE == key) {
                        CDI_LOG_THREAD(kLogError, "unknown video TCS value [%s]", value_ptr);
                        ret = false;
                    } else {
                        video_config_ptr->tcs = (CdiAvmVideoTcs)key;
                    }
                }
            } else if (0 == CdiOsStrCaseCmp(param_ptr, "RANGE")) {
                if (NULL == value_ptr) {
                    CDI_LOG_THREAD(kLogError, "video RANGE parameter value is missing");
                    ret = false;
                } else {
                    int key = CdiAvmKeyStringToEnum(kKeyAvmVideoRangeType, value_ptr,
                                                    &video_config_ptr->version);
                    if (CDI_INVALID_ENUM_VALUE == key) {
                        CDI_LOG_THREAD(kLogError, "unknown video RANGE value [%s]", value_ptr);
                        ret = false;
                    } else {
                        video_config_ptr->range = (CdiAvmVideoRange)key;
                    }
                }
            } else if (0 == CdiOsStrCaseCmp(param_ptr, "PAR")) {
                if (NULL == value_ptr) {
                    CDI_LOG_THREAD(kLogError, "video exactframerate parameter value is missing");
                    ret = false;
                } else {
                    char* height_ptr = strchr(value_ptr, ':');
                    if (NULL != height_ptr) {
                        *(height_ptr++) = '\0';
                        video_config_ptr->par_height = atoi(height_ptr);
                    }
                    video_config_ptr->par_width = atoi(value_ptr);
                }
            } else if (0 == CdiOsStrCaseCmp(param_ptr, "alpha_included")) {
                if (NULL == value_ptr) {
                    CDI_LOG_THREAD(kLogError, "video alpha_included parameter value is missing");
                    ret = false;
                } else {
                    if (0 == CdiOsStrCaseCmp(value_ptr, "enabled")) {
                        video_config_ptr->alpha_channel = kCdiAvmAlphaUsed;
                    } else if (0 != CdiOsStrCaseCmp(value_ptr, "disabled")) {
                        CDI_LOG_THREAD(kLogWarning, "invalid video alpha_included depth value [%s]", value_ptr);
                    }
                }
            } else if (0 == CdiOsStrCaseCmp(param_ptr, "partial_frame")) {
                if (NULL == value_ptr) {
                    CDI_LOG_THREAD(kLogError, "video alpha_included parameter value is missing");
                    ret = false;
                } else {
                    // Save address in original copy and length in case error message needs to be logged.
                    char* value_save_str = value_ptr - copy_str + (char*)config_ptr->data;
                    int value_save_length = strlen(value_ptr);

                    bool partial_frame_parsed = false;
                    char* height_ptr = strchr(value_ptr, 'x');
                    if (NULL != height_ptr) {
                        *(height_ptr++) = '\0';
                        char* hoffset_ptr = strchr(height_ptr, '+');
                        if (NULL != hoffset_ptr) {
                            *(hoffset_ptr++) = '\0';
                            char* voffset_ptr = strchr(hoffset_ptr, '+');
                            if (NULL != voffset_ptr) {
                                *(voffset_ptr++) = '\0';
                                video_config_ptr->horizontal_size = atoi(value_ptr);
                                video_config_ptr->vertical_size = atoi(height_ptr);
                                video_config_ptr->start_horizontal_pos = atoi(hoffset_ptr);
                                video_config_ptr->start_vertical_pos = atoi(voffset_ptr);
                                partial_frame_parsed = true;
                            }
                        }
                    }
                    if (!partial_frame_parsed) {
                        // Restore entire value back to its place in copy_str.
                        memcpy(value_ptr, value_save_str, value_save_length);
                        CDI_LOG_THREAD(kLogError, "invalid video partial_frame value [%s]", value_ptr);
                        ret = false;
                    }
                }
            } else {
                CDI_LOG_THREAD(kLogWarning, "unknown parameter/value in video configuration string [%s]", param_ptr);
            }
        }
    }

    return ret;
}