Loading media/libmediaformatshaper/CodecProperties.cpp +130 −7 Original line number Diff line number Diff line Loading @@ -53,13 +53,6 @@ void CodecProperties::setSupportedMinimumQuality(int vmaf) { mMinimumQuality = vmaf; } int CodecProperties::targetQpMax() { return mTargetQpMax; } void CodecProperties::setTargetQpMax(int qpMax) { mTargetQpMax = qpMax; } void CodecProperties::setMissingQpBoost(double boost) { mMissingQpBoost = boost; } Loading Loading @@ -118,6 +111,11 @@ void CodecProperties::setTuningValue(std::string key, std::string value) { setTargetQpMax(iValue); legal = true; } } else if (!strncmp(key.c_str(), "vq-target-qpmax-", strlen("vq-target-qpmax-"))) { std::string resolution = key.substr(strlen("vq-target-qpmax-")); if (qpMaxPoint(resolution, value)) { legal = true; } } else if (!strcmp(key.c_str(), "vq-target-bpp")) { const char *p = value.c_str(); char *q; Loading Loading @@ -292,6 +290,131 @@ double CodecProperties::getBpp(int32_t width, int32_t height) { return mBpp; } bool CodecProperties::qpMaxPoint(std::string resolution, std::string value) { int32_t width = 0; int32_t height = 0; int qpMax = INT32_MAX; // resolution is "WxH", "W*H" or a standard name like "720p" if (resolution == "1080p") { width = 1080; height = 1920; } else if (resolution == "720p") { width = 720; height = 1280; } else if (resolution == "540p") { width = 540; height = 960; } else if (resolution == "480p") { width = 480; height = 854; } else { size_t sep = resolution.find('x'); if (sep == std::string::npos) { sep = resolution.find('*'); } if (sep == std::string::npos) { ALOGW("unable to parse resolution: '%s'", resolution.c_str()); return false; } std::string w = resolution.substr(0, sep); std::string h = resolution.substr(sep+1); char *q; const char *p = w.c_str(); width = strtol(p, &q, 0); if (q == p) { width = -1; } p = h.c_str(); height = strtol(p, &q, 0); if (q == p) { height = -1; } if (width <= 0 || height <= 0 || width > DIMENSION_LIMIT || height > DIMENSION_LIMIT) { ALOGW("unparseable: width, height '%s'", resolution.c_str()); return false; } } const char *p = value.c_str(); char *q; qpMax = strtol(p, &q, 0); if (q == p) { ALOGW("unparseable qpmax '%s'", value.c_str()); return false; } // convert to our internal 'unspecified' notation if (qpMax == -1) qpMax = INT32_MAX; struct qpmax_point *point = (struct qpmax_point*) malloc(sizeof(*point)); if (point == nullptr) { ALOGW("unable to allocate memory for qpmax point"); return false; } point->pixels = width * height; point->width = width; point->height = height; point->qpMax = qpMax; if (mQpMaxPoints == nullptr) { point->next = nullptr; mQpMaxPoints = point; } else if (point->pixels < mQpMaxPoints->pixels) { // at the front point->next = mQpMaxPoints; mQpMaxPoints = point; } else { struct qpmax_point *after = mQpMaxPoints; while (after->next) { if (point->pixels > after->next->pixels) { after = after->next; continue; } // insert before after->next point->next = after->next; after->next = point; break; } if (after->next == nullptr) { // hasn't gone in yet point->next = nullptr; after->next = point; } } return true; } int CodecProperties::targetQpMax(int32_t width, int32_t height) { // look in the per-resolution list int32_t pixels = width * height; if (mQpMaxPoints) { struct qpmax_point *point = mQpMaxPoints; while (point && point->pixels < pixels) { point = point->next; } if (point) { ALOGV("targetQpMax(w=%d,h=%d) returns %d from qpmax_point w=%d h=%d", width, height, point->qpMax, point->width, point->height); return point->qpMax; } } ALOGV("defaulting to %d qpmax", mTargetQpMax); return mTargetQpMax; } void CodecProperties::setTargetQpMax(int qpMax) { // convert to our internal 'unspecified' notation if (qpMax == -1) qpMax = INT32_MAX; mTargetQpMax = qpMax; } std::string CodecProperties::getMapping(std::string key, std::string kind) { ALOGV("getMapping(key %s, kind %s )", key.c_str(), kind.c_str()); //play with mMappings Loading media/libmediaformatshaper/CodecProperties.h +14 −1 Original line number Diff line number Diff line Loading @@ -69,7 +69,7 @@ class CodecProperties { // qp max bound used to compensate when SupportedMinimumQuality == 0 // 0 == let a system default handle it void setTargetQpMax(int qpmax); int targetQpMax(); int targetQpMax(int32_t width, int32_t height); // target bits-per-pixel (per second) for encoding operations. // This is used to calculate a minimum bitrate for any particular resolution. Loading Loading @@ -123,6 +123,19 @@ class CodecProperties { struct bpp_point *mBppPoints = nullptr; bool bppPoint(std::string resolution, std::string value); // same thing for qpmax -- allow different ones based on resolution // allow different target bits-per-pixel based on resolution // similar to codec 'performance points' // uses 'next largest' (by pixel count) point as minimum bpp struct qpmax_point { struct qpmax_point *next; int32_t pixels; int32_t width, height; int qpMax; }; struct qpmax_point *mQpMaxPoints = nullptr; bool qpMaxPoint(std::string resolution, std::string value); std::mutex mMappingLock; // XXX figure out why I'm having problems getting compiler to like GUARDED_BY std::map<std::string, std::string> mMappings /*GUARDED_BY(mMappingLock)*/ ; Loading media/libmediaformatshaper/CodecSeeding.cpp +14 −3 Original line number Diff line number Diff line Loading @@ -49,28 +49,39 @@ typedef struct { */ static preloadTuning_t featuresAvc[] = { {true, "vq-target-bpp", "0"}, {true, "vq-target-bpp-1080p", "1.90"}, {true, "vq-target-bpp-720p", "2.25"}, {true, "vq-target-bpp-540p", "2.65"}, {true, "vq-target-bpp-480p", "3.00"}, {true, "vq-target-qpmax", "40"}, {true, "vq-target-qpmax", "-1"}, {true, "vq-target-qpmax-1080p", "45"}, {true, "vq-target-qpmax-720p", "43"}, {true, "vq-target-qpmax-540p", "42"}, {true, "vq-target-qpmax-480p", "38"}, {true, "vq-bitrate-phaseout", "1.75"}, {true, "vq-boost-missing-qp", "0.20"}, {true, nullptr, 0} }; static preloadTuning_t featuresHevc[] = { {true, "vq-target-bpp", "0"}, {true, "vq-target-bpp-1080p", "1.50"}, {true, "vq-target-bpp-720p", "1.80"}, {true, "vq-target-bpp-540p", "2.10"}, {true, "vq-target-qpmax", "40"}, {true, "vq-target-qpmax", "-1"}, {true, "vq-target-qpmax-1080p", "45"}, {true, "vq-target-qpmax-720p", "43"}, {true, "vq-target-qpmax-540p", "42"}, {true, "vq-target-qpmax-480p", "39"}, {true, "vq-bitrate-phaseout", "1.75"}, {true, "vq-boost-missing-qp", "0.20"}, {true, nullptr, 0} }; static preloadTuning_t featuresGenericVideo[] = { {true, "vq-target-bpp", "2.00"}, // 0 == off {true, "vq-target-bpp", "0"}, {true, nullptr, 0} }; Loading media/libmediaformatshaper/VQApply.cpp +1 −1 Original line number Diff line number Diff line Loading @@ -115,7 +115,7 @@ int VQApply(CodecProperties *codec, vqOps_t *info, AMediaFormat* inFormat, int f bool qpPresent = hasQpMax(inFormat); // calculate a target QP value int32_t qpmax = codec->targetQpMax(); int32_t qpmax = codec->targetQpMax(width, height); if (!qpPresent) { // user didn't, so shaper wins if (qpmax != INT32_MAX) { Loading Loading
media/libmediaformatshaper/CodecProperties.cpp +130 −7 Original line number Diff line number Diff line Loading @@ -53,13 +53,6 @@ void CodecProperties::setSupportedMinimumQuality(int vmaf) { mMinimumQuality = vmaf; } int CodecProperties::targetQpMax() { return mTargetQpMax; } void CodecProperties::setTargetQpMax(int qpMax) { mTargetQpMax = qpMax; } void CodecProperties::setMissingQpBoost(double boost) { mMissingQpBoost = boost; } Loading Loading @@ -118,6 +111,11 @@ void CodecProperties::setTuningValue(std::string key, std::string value) { setTargetQpMax(iValue); legal = true; } } else if (!strncmp(key.c_str(), "vq-target-qpmax-", strlen("vq-target-qpmax-"))) { std::string resolution = key.substr(strlen("vq-target-qpmax-")); if (qpMaxPoint(resolution, value)) { legal = true; } } else if (!strcmp(key.c_str(), "vq-target-bpp")) { const char *p = value.c_str(); char *q; Loading Loading @@ -292,6 +290,131 @@ double CodecProperties::getBpp(int32_t width, int32_t height) { return mBpp; } bool CodecProperties::qpMaxPoint(std::string resolution, std::string value) { int32_t width = 0; int32_t height = 0; int qpMax = INT32_MAX; // resolution is "WxH", "W*H" or a standard name like "720p" if (resolution == "1080p") { width = 1080; height = 1920; } else if (resolution == "720p") { width = 720; height = 1280; } else if (resolution == "540p") { width = 540; height = 960; } else if (resolution == "480p") { width = 480; height = 854; } else { size_t sep = resolution.find('x'); if (sep == std::string::npos) { sep = resolution.find('*'); } if (sep == std::string::npos) { ALOGW("unable to parse resolution: '%s'", resolution.c_str()); return false; } std::string w = resolution.substr(0, sep); std::string h = resolution.substr(sep+1); char *q; const char *p = w.c_str(); width = strtol(p, &q, 0); if (q == p) { width = -1; } p = h.c_str(); height = strtol(p, &q, 0); if (q == p) { height = -1; } if (width <= 0 || height <= 0 || width > DIMENSION_LIMIT || height > DIMENSION_LIMIT) { ALOGW("unparseable: width, height '%s'", resolution.c_str()); return false; } } const char *p = value.c_str(); char *q; qpMax = strtol(p, &q, 0); if (q == p) { ALOGW("unparseable qpmax '%s'", value.c_str()); return false; } // convert to our internal 'unspecified' notation if (qpMax == -1) qpMax = INT32_MAX; struct qpmax_point *point = (struct qpmax_point*) malloc(sizeof(*point)); if (point == nullptr) { ALOGW("unable to allocate memory for qpmax point"); return false; } point->pixels = width * height; point->width = width; point->height = height; point->qpMax = qpMax; if (mQpMaxPoints == nullptr) { point->next = nullptr; mQpMaxPoints = point; } else if (point->pixels < mQpMaxPoints->pixels) { // at the front point->next = mQpMaxPoints; mQpMaxPoints = point; } else { struct qpmax_point *after = mQpMaxPoints; while (after->next) { if (point->pixels > after->next->pixels) { after = after->next; continue; } // insert before after->next point->next = after->next; after->next = point; break; } if (after->next == nullptr) { // hasn't gone in yet point->next = nullptr; after->next = point; } } return true; } int CodecProperties::targetQpMax(int32_t width, int32_t height) { // look in the per-resolution list int32_t pixels = width * height; if (mQpMaxPoints) { struct qpmax_point *point = mQpMaxPoints; while (point && point->pixels < pixels) { point = point->next; } if (point) { ALOGV("targetQpMax(w=%d,h=%d) returns %d from qpmax_point w=%d h=%d", width, height, point->qpMax, point->width, point->height); return point->qpMax; } } ALOGV("defaulting to %d qpmax", mTargetQpMax); return mTargetQpMax; } void CodecProperties::setTargetQpMax(int qpMax) { // convert to our internal 'unspecified' notation if (qpMax == -1) qpMax = INT32_MAX; mTargetQpMax = qpMax; } std::string CodecProperties::getMapping(std::string key, std::string kind) { ALOGV("getMapping(key %s, kind %s )", key.c_str(), kind.c_str()); //play with mMappings Loading
media/libmediaformatshaper/CodecProperties.h +14 −1 Original line number Diff line number Diff line Loading @@ -69,7 +69,7 @@ class CodecProperties { // qp max bound used to compensate when SupportedMinimumQuality == 0 // 0 == let a system default handle it void setTargetQpMax(int qpmax); int targetQpMax(); int targetQpMax(int32_t width, int32_t height); // target bits-per-pixel (per second) for encoding operations. // This is used to calculate a minimum bitrate for any particular resolution. Loading Loading @@ -123,6 +123,19 @@ class CodecProperties { struct bpp_point *mBppPoints = nullptr; bool bppPoint(std::string resolution, std::string value); // same thing for qpmax -- allow different ones based on resolution // allow different target bits-per-pixel based on resolution // similar to codec 'performance points' // uses 'next largest' (by pixel count) point as minimum bpp struct qpmax_point { struct qpmax_point *next; int32_t pixels; int32_t width, height; int qpMax; }; struct qpmax_point *mQpMaxPoints = nullptr; bool qpMaxPoint(std::string resolution, std::string value); std::mutex mMappingLock; // XXX figure out why I'm having problems getting compiler to like GUARDED_BY std::map<std::string, std::string> mMappings /*GUARDED_BY(mMappingLock)*/ ; Loading
media/libmediaformatshaper/CodecSeeding.cpp +14 −3 Original line number Diff line number Diff line Loading @@ -49,28 +49,39 @@ typedef struct { */ static preloadTuning_t featuresAvc[] = { {true, "vq-target-bpp", "0"}, {true, "vq-target-bpp-1080p", "1.90"}, {true, "vq-target-bpp-720p", "2.25"}, {true, "vq-target-bpp-540p", "2.65"}, {true, "vq-target-bpp-480p", "3.00"}, {true, "vq-target-qpmax", "40"}, {true, "vq-target-qpmax", "-1"}, {true, "vq-target-qpmax-1080p", "45"}, {true, "vq-target-qpmax-720p", "43"}, {true, "vq-target-qpmax-540p", "42"}, {true, "vq-target-qpmax-480p", "38"}, {true, "vq-bitrate-phaseout", "1.75"}, {true, "vq-boost-missing-qp", "0.20"}, {true, nullptr, 0} }; static preloadTuning_t featuresHevc[] = { {true, "vq-target-bpp", "0"}, {true, "vq-target-bpp-1080p", "1.50"}, {true, "vq-target-bpp-720p", "1.80"}, {true, "vq-target-bpp-540p", "2.10"}, {true, "vq-target-qpmax", "40"}, {true, "vq-target-qpmax", "-1"}, {true, "vq-target-qpmax-1080p", "45"}, {true, "vq-target-qpmax-720p", "43"}, {true, "vq-target-qpmax-540p", "42"}, {true, "vq-target-qpmax-480p", "39"}, {true, "vq-bitrate-phaseout", "1.75"}, {true, "vq-boost-missing-qp", "0.20"}, {true, nullptr, 0} }; static preloadTuning_t featuresGenericVideo[] = { {true, "vq-target-bpp", "2.00"}, // 0 == off {true, "vq-target-bpp", "0"}, {true, nullptr, 0} }; Loading
media/libmediaformatshaper/VQApply.cpp +1 −1 Original line number Diff line number Diff line Loading @@ -115,7 +115,7 @@ int VQApply(CodecProperties *codec, vqOps_t *info, AMediaFormat* inFormat, int f bool qpPresent = hasQpMax(inFormat); // calculate a target QP value int32_t qpmax = codec->targetQpMax(); int32_t qpmax = codec->targetQpMax(width, height); if (!qpPresent) { // user didn't, so shaper wins if (qpmax != INT32_MAX) { Loading