Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

MediaConvert CreateJobTemplate error for Baseline profiles #1582

Closed
3 tasks done
tigrato opened this issue Feb 7, 2022 · 7 comments
Closed
3 tasks done

MediaConvert CreateJobTemplate error for Baseline profiles #1582

tigrato opened this issue Feb 7, 2022 · 7 comments
Assignees
Labels
bug This issue is a bug. p3 This is a minor priority issue service-api This issue is due to a problem in a service API, not the SDK implementation. workaround-available

Comments

@tigrato
Copy link

tigrato commented Feb 7, 2022

Documentation

Describe the bug

When creating a simple encoding template job for H264 video output with Baseline profile the number NumberBFramesBetweenReferenceFrames has to be sent as 0 (Baseline does not support Bframes between reference frames).
The field NumberBFramesBetweenReferenceFrames: int32 is only serialized if the provided value is not zero so it is never sent here

Expected behavior

The system allow me to create the JobTemplate without errors

Current behavior

MediaConvert API returns an error mentioning that NumberBFramesBetweenReferenceFrames must be <=0 OR that the Profile must be changed to something different than Baseline (If I sent the NumberBFramesBetweenReferenceFrames <0 the media convert api returns other error)

MediaConvert: CreateJobTemplate, https response error StatusCode: 400, RequestID: 083e9ebb-36b3-414b-8dd3-cbc50d2edbf8, BadRequestException: /outputGroups/0/outputs/3/videoDescription/codecSettings/h264Settings/codecProfile: Should match all dependencies: See other errors for more details | /outputGroups/0/outputs/3/videoDescription/codecSettings/h264Settings: Should match exactly one schema defined in "oneOf" | /outputGroups/0/outputs/3/videoDescription/codecSettings/h264Settings: numberBFramesBetweenReferenceFrames is a required property | /outputGroups/0/outputs/3/videoDescription/codecSettings/h264Settings/codecProfile: Should be equal to one of the allowed values in ["HIGH","HIGH_10BIT","HIGH_422","HIGH_422_10BIT","MAIN"]

Steps to Reproduce

Create via GO API a template with the Following H264 config

H264Settings: &types.H264Settings{
                AdaptiveQuantization: "HIGH",
                Bitrate: 1768615,
                CodecLevel: "LEVEL_3_1",
                CodecProfile: "BASELINE",
                DynamicSubGop: "STATIC",
                EntropyEncoding: "CAVLC",
                FieldEncoding: "PAFF",
                FlickerAdaptiveQuantization: "DISABLED",
                FramerateControl: "SPECIFIED",
                FramerateConversionAlgorithm: "DUPLICATE_DROP",
                FramerateDenominator: 1,
                FramerateNumerator: 25,
                GopBReference: "DISABLED",
                GopClosedCadence: 1,
                GopSize: 50.0,
                GopSizeUnits: "FRAMES",
                HrdBufferInitialFillPercentage: 0,
                HrdBufferSize: 0,
                InterlaceMode: "PROGRESSIVE",
                MaxBitrate: 0,
                MinIInterval: 0,
                NumberBFramesBetweenReferenceFrames: 0,
                NumberReferenceFrames: 2,
                ParControl: "SPECIFIED",
                ParDenominator: 1,
                ParNumerator: 1,
                QualityTuningLevel: "SINGLE_PASS",
                QvbrSettings: nil,
                RateControlMode: "CBR",
                RepeatPps: "DISABLED",
                ScanTypeConversionMode: "",
                SceneChangeDetect: "ENABLED",
                Slices: 1,
                SlowPal: "DISABLED",
                Softness: 0,
                SpatialAdaptiveQuantization: "ENABLED",
                Syntax: "DEFAULT",
                Telecine: "NONE",
                TemporalAdaptiveQuantization: "ENABLED",
                UnregisteredSeiTimecode: "DISABLED",
              },

Possible Solution

Mark NumberBFramesBetweenReferenceFrames to be serialized if the Baseline profile is selected even if it is zero or change the media convert behaviour to set it as 0 if baseline profile is found.

AWS Go SDK version used

v1.16

Compiler and Version used

1.17

Operating System and version

MacOS 11.6

@tigrato tigrato added bug This issue is a bug. needs-triage This issue or PR still needs to be triaged. labels Feb 7, 2022
@vudh1 vudh1 self-assigned this Mar 9, 2022
@vudh1
Copy link
Contributor

vudh1 commented Apr 29, 2022

Hi, is this still persisting with the latest version of SDK?

@vudh1 vudh1 added response-requested Waiting on additional info and feedback. Will move to "closing-soon" in 7 days. and removed needs-triage This issue or PR still needs to be triaged. labels Apr 29, 2022
@github-actions
Copy link

github-actions bot commented May 2, 2022

This issue has not received a response in 1 week. If you want to keep this issue open, please just leave a comment below and auto-close will be canceled.

@github-actions github-actions bot added the closing-soon This issue will automatically close in 4 days unless further comments are made. label May 2, 2022
@tigrato
Copy link
Author

tigrato commented May 6, 2022

@vudh1 yes, it is still present

@github-actions github-actions bot removed closing-soon This issue will automatically close in 4 days unless further comments are made. response-requested Waiting on additional info and feedback. Will move to "closing-soon" in 7 days. labels May 7, 2022
@vudh1 vudh1 removed their assignment Aug 25, 2022
@RanVaknin RanVaknin added the needs-triage This issue or PR still needs to be triaged. label Sep 2, 2022
@RanVaknin RanVaknin added p3 This is a minor priority issue m Effort estimation: medium labels Nov 10, 2022
@RanVaknin RanVaknin self-assigned this Jan 9, 2023
@RanVaknin
Copy link
Contributor

RanVaknin commented Jan 9, 2023

Hi @tigrato ,

Sorry for the really long wait time. This issue took time to investigate.

The problem is that the default value 0, is being ignored even though you are trying to set it explicitly.
This is because of the way the mediaconvert service team exports their model does not work correctly with Smithy based SDKs (Kotlin, Rust, Go, Swift..) In specific, those exports lack the "Default" trait which indicates default values that should be serialized.

In your case NumberBFramesBetweenReferenceFrames is set to 0, but 0 is also the default value for it so the field is ignored in serialization.
Unfortunately right now there is no solution for this and these individual parameters will have to be patched by hand. A broad solution will be addressed in the future as part of a cross-SDK effort.

In the meantime, you can check out my workaround code. In short, what the code does is:

  • Create a custom middleware
  • In that middleware we get the request JSON body, and hard-insert the missing field and value and re-write the body.
  • Lastly we append the custom middleware after the Serialize step.

⚠️ Please note that this code works with the parameters I have made up, and might look a bit different for you.

func main() {

	customResolver := aws.EndpointResolverWithOptionsFunc(func(service, region string, options ...interface{}) (aws.Endpoint, error) {
		if service == mediaconvert.ServiceID && region == "us-east-1" {
			return aws.Endpoint{
				PartitionID:   "aws",
				URL:           "https://q25wbt2lc.mediaconvert.us-east-1.amazonaws.com",
				SigningRegion: "us-east-1",
			}, nil
		}
		return aws.Endpoint{}, &aws.EndpointNotFoundError{}
	})

	myMiddleware := middleware.SerializeMiddlewareFunc("MyTestMiddleware",
		func(ctx context.Context, input middleware.SerializeInput, next middleware.SerializeHandler,
		) (
			output middleware.SerializeOutput, metadata middleware.Metadata, err error,
		) {
			req, ok := input.Request.(*smithyhttp.Request)
			if !ok {
				return output, metadata, fmt.Errorf("unexpected transport: %T", input.Request)
			}

			// get the body from the request
			bodyStream := req.GetStream()
			buf := new(strings.Builder)
			_, err = io.Copy(buf, bodyStream)
			actualBodyString := buf.String()

			// the location after which we want to insert the parameter.
			substring := `h264Settings":{`
			index := strings.Index(actualBodyString, substring)

			// re-constructing the body
			newBodyString := actualBodyString[:index+len(substring)] + `"NumberBFramesBetweenReferenceFrames":0,` + actualBodyString[len(substring)+index:]
			newStream := strings.NewReader(newBodyString)

			// matching the content length
			req.ContentLength = int64(len(newBodyString))
			input.Request = req

			// overriding the body
			input.Request, err = req.SetStream(newStream)
			if err != nil {
				panic(err)
			}

			return next.HandleSerialize(ctx, input)
		})

	cfg, err := config.LoadDefaultConfig(context.TODO(), config.WithEndpointResolverWithOptions(customResolver), config.WithClientLogMode(aws.LogRequestWithBody|aws.LogResponseWithBody))
	if err != nil {
		log.Fatalf("unable to load SDK config, %v", err)
	}

	client := mediaconvert.NewFromConfig(cfg, func(options *mediaconvert.Options) {
		options.APIOptions = append(options.APIOptions, func(stack *middleware.Stack) error {
			return stack.Serialize.Add(myMiddleware, middleware.After)
		})

	})

	// this is a fake template, your input fields might look different
	out, err := client.CreateJobTemplate(context.Background(), &mediaconvert.CreateJobTemplateInput{
		Name: aws.String("1582_template"),
		Settings: &types.JobTemplateSettings{
			OutputGroups: []types.OutputGroup{
				{
					OutputGroupSettings: &types.OutputGroupSettings{
						Type: "CMAF_GROUP_SETTINGS",

						CmafGroupSettings: &types.CmafGroupSettings{
							SegmentLength:  1,
							FragmentLength: 1,
						},
					},
					Outputs: []types.Output{
						{
							ContainerSettings: &types.ContainerSettings{
								Container: "CMFC",
							},
							VideoDescription: &types.VideoDescription{
								CodecSettings: &types.VideoCodecSettings{
									Codec: types.VideoCodecH264,
									H264Settings: &types.H264Settings{
										AdaptiveQuantization:                "HIGH",
										Bitrate:                             1768615,
										CodecLevel:                          "LEVEL_3_1",
										CodecProfile:                        "BASELINE",
										DynamicSubGop:                       "STATIC",
										EntropyEncoding:                     "CAVLC",
										FieldEncoding:                       "PAFF",
										FlickerAdaptiveQuantization:         "DISABLED",
										FramerateControl:                    "SPECIFIED",
										FramerateConversionAlgorithm:        "DUPLICATE_DROP",
										FramerateDenominator:                1,
										FramerateNumerator:                  25,
										GopBReference:                       "DISABLED",
										GopClosedCadence:                    1,
										GopSize:                             50.0,
										GopSizeUnits:                        "FRAMES",
										HrdBufferInitialFillPercentage:      0,
										HrdBufferSize:                       0,
										InterlaceMode:                       "PROGRESSIVE",
										MaxBitrate:                          0,
										MinIInterval:                        0,
										NumberBFramesBetweenReferenceFrames: 0,
										NumberReferenceFrames:               2,
										ParControl:                          "SPECIFIED",
										ParDenominator:                      1,
										ParNumerator:                        1,
										QualityTuningLevel:                  "SINGLE_PASS",
										QvbrSettings:                        nil,
										RateControlMode:                     "CBR",
										RepeatPps:                           "DISABLED",
										ScanTypeConversionMode:              "",
										SceneChangeDetect:                   "ENABLED",
										Slices:                              1,
										SlowPal:                             "DISABLED",
										Softness:                            0,
										SpatialAdaptiveQuantization:         "ENABLED",
										Syntax:                              "DEFAULT",
										Telecine:                            "NONE",
										TemporalAdaptiveQuantization:        "ENABLED",
										UnregisteredSeiTimecode:             "DISABLED",
									},
								},
							},
						},
					},
				},
			},
		},
	})

	if err != nil {
		panic(err)
	}
}

Let me know if this helps at all.
I'm going to leave this issue open so we can address it down the line.

Thanks again for your patience,
Ran~

@RanVaknin RanVaknin added response-requested Waiting on additional info and feedback. Will move to "closing-soon" in 7 days. service-api This issue is due to a problem in a service API, not the SDK implementation. workaround-available and removed needs-triage This issue or PR still needs to be triaged. m Effort estimation: medium labels Jan 9, 2023
@tigrato
Copy link
Author

tigrato commented Jan 9, 2023

Hey, @RanVaknin thanks for the response.
I ended up with something similar to your workaround to force the inclusion of the missing values.
Hope this gets fixed soon so I can get rid of this code.

@github-actions github-actions bot removed the response-requested Waiting on additional info and feedback. Will move to "closing-soon" in 7 days. label Jan 10, 2023
@RanVaknin
Copy link
Contributor

Hi @tigrato ,

We are tracking this in a separate ticket aws/aws-sdk#577

Closing this in favor of tracking it there.
Thanks,
Ran~

@github-actions
Copy link

⚠️COMMENT VISIBILITY WARNING⚠️

Comments on closed issues are hard for our team to see.
If you need more assistance, please either tag a team member or open a new issue that references this one.
If you wish to keep having a conversation with other community members under this issue feel free to do so.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug This issue is a bug. p3 This is a minor priority issue service-api This issue is due to a problem in a service API, not the SDK implementation. workaround-available
Projects
None yet
Development

No branches or pull requests

3 participants