Skip to content

Commit

Permalink
DNxHD updates with MXF (#35)
Browse files Browse the repository at this point in the history
* DNxHD updates with MXF
This also has examples of mxf outputs for AVID.

Signed-off-by: [email protected] <[email protected]>
(cherry picked from commit c2d54f2)

* Adding frame rate, thanks to Mark Reid for pointing me to this - https://github.com/markreidvfx/pyaaf2/blob/23b61437452e8f18fc445d5a8c8b605972fa2349/src/aaf2/video.py#L12

Signed-off-by: [email protected] <[email protected]>

* Adding a reference to pyaaf2 library, which could be useful for someworkflows. Also updated the DNxHD table with frame-rates. Thanks to Mark Reid for pointing these out.

Signed-off-by: [email protected] <[email protected]>

---------

Signed-off-by: [email protected] <[email protected]>
Co-authored-by: [email protected] <[email protected]>
  • Loading branch information
richardssam and SamRichardsDisney authored Nov 3, 2023
1 parent 62a2172 commit 821a5f4
Show file tree
Hide file tree
Showing 3 changed files with 414 additions and 6 deletions.
192 changes: 190 additions & 2 deletions EncodeDNXHD.md
Original file line number Diff line number Diff line change
@@ -1,7 +1,195 @@
---
layout: default
nav_order: 4.3
nav_order: 4.6
title: DNxHD Encoding
parent: Encoding
parent: Codec Comparisons
---


# DNxHD/DNxHR

Avid [DNxHD](https://en.wikipedia.org/wiki/Avid_DNxHD) ("Digital Nonlinear Extensible High Definition") is a lossy post-production codec that is intended for use for editing as well as a presentation format.

There are a number of pre-defined resolutions, frame-rates and bit-rates that are supported, see [AVID Resolutions](https://en.wikipedia.org/wiki/List_of_Avid_DNxHD_resolutions) for a list. However, we are going to focus on the DNxHR version of the codec, since it allows quite a bit more flexibility for larger image sizes than HD, more flexible frame rates and bit-rates of up to 3730Mbit/s (See [DNxHR-Codec-Bandwidth-Specifications](https://avid.secure.force.com/pkb/articles/en_US/White_Paper/DNxHR-Codec-Bandwidth-Specifications) ).


Supported pixel formats: yuv422p yuv422p10le yuv444p10le gbrp10le

Example encoding:

<!---
name: test_dnxhd_mov
sources:
- sourceimages/chip-chart-1080-16bit-noicc.png.yml
comparisontest:
- testtype: idiff
compare_image: ../sourceimages/chip-chart-1080-16bit-noicc-yuv422p10le.png
- testtype: assertresults
tests:
- assert: less
value: max_error
less: 0.00195
-->
```
ffmpeg -r 24 -start_number 1 -i inputfile.%04d.png -frames:v 200 -c:v dnxhd \
-pix_fmt yuv422p10le -profile:v dnxhr_hqx -sws_flags spline+accurate_rnd+full_chroma_int \
-vf "scale=in_range=full:in_color_matrix=bt709:out_range=tv:out_color_matrix=bt709" \
-color_range 1 -colorspace 1 -color_primaries 1 -color_trc 2 -y outputfile.mov
```


## ffmpeg DNxHR Profiles

| Profile name | Profile description | Profile # | Pix Fmt | Bit Depth | Compression Ratio |
|:----------|:-----------|:-----------|:-----------|:-----------|:-----------|
| dnxhr_lb | Low Bandwidth | 1 | YUV 4:2:2 | 8 | 22:1 |
| dnxhr_sq | Standard Quality | 2 | YUV 4:2:2 | 8 | 7:1 |
| dnxhr_hq | High Quality | 3 | YUV 4:2:2 | 8 | 4.5:1 |
| dnxhr_hqx | High Quality | 4 | YUV 4:2:2 | 12 (*) | 5.5: 1 |
| dnxhr_444 | DNxHR 4:4:4 | 5 | YUV 4:4:4 or RGB | 12 (*) | 4.5:1 |

There really are not any significant flags to be used, changing bit-rate has no effect.

(*) The 12-bit depth is what the codec can support, but does not appear to be supported by ffmpeg, since the encoding only allows 10-bit image data to be encoded.

## ffmpeg RGB support

<!---
name: test_prores444_rgb
sources:
- sourceimages/chip-chart-1080-16bit-noicc.png.yml
comparisontest:
- testtype: idiff
- testtype: assertresults
tests:
- assert: less
value: max_error
less: 0.00195
-->
```
ffmpeg -y -r 24 -i inputfile.%04d.png -vframes 100 \
-c:v dnxhd -profile:v dnxhr_444 \
-vf "scale=in_color_matrix=bt709:out_color_matrix=bt709" \
-color_primaries bt709 -color_range tv -color_trc bt709 -colorspace rgb \
-pix_fmt gbrp10le outputfile.mov
```

## AVID friendly MXF

AVID prefer deliveries in MXF using the Avid Op-Atom format. Generating the Op-Atom format used to be a separate application, but its now integrated into ffmpeg.

<!---
name: test_prores444_mxf
sources:
- sourceimages/chip-chart-1080-16bit-noicc.png.yml
comparisontest:
- testtype: idiff
- testtype: assertresults
tests:
- assert: less
value: max_error
less: 0.00195
-->
```
ffmpeg -y -r 24 -i inputfile.%04d.png -vframes 100 \
-c:v dnxhd -profile:v dnxhr_444 \
-metadata project="MY PROJECT" \
-metadata material_package_name="MY CLIP" \
-b:v 36M -f mxf_opatom outputfile.mxf
```

See [https://johnwarburton.net/blog/?p=50731](https://johnwarburton.net/blog/?p=50731)

## AAF Creation

If you are tightly integrating your pipeline into an AVID workflow, you should checkout [pyaaf2](https://github.com/markreidvfx/pyaaf2). [OTIO To Multi AAF Transcode example](https://github.com/markreidvfx/otio_to_multi_aaf_alab_example) is an example of using OTIO and pyaaf2 to create a AAF file from an OTIO file.

Ideally with AAF files, you would be importing MXF files (like the example above) to minimize the import time to the AVID (so it doesnt require any media transcoding).

## DNxHD Profiles

For example below is an example of DNxHD at 175Mbps at yuv422p10 at resolution 1920x1080.

<!---
name: test_prores422_profile
sources:
- sourceimages/chip-chart-1080-16bit-noicc.png.yml
comparisontest:
- testtype: idiff
compare_image: ../sourceimages/chip-chart-1080-16bit-noicc-yuv422p10le.png
- testtype: assertresults
tests:
- assert: less
value: max_error
less: 0.00195
-->
```
ffmpeg -y -r 24 -i inputfile.%04d.png -vframes 100 \
-c:v dnxhd -b:v 175M \
-vf "scale=in_color_matrix=bt709:out_color_matrix=bt709" \
-color_primaries bt709 -color_range tv -color_trc bt709 -colorspace rgb \
-pix_fmt yuv422p10 outputfile.mov
```

Other combinations of resolution, bitrate and format are:

| Resolution | Bit Rate | Pix Format | Frame Rates |
|:----------|-----------:|:-----------|:-----------|
| 1920x1080p| 175M | yuv422p10 | 23.98, 24 |
| 1920x1080p| 185M | yuv422p10 | 25 |
| 1920x1080p| 365M | yuv422p10 | 50 |
| 1920x1080p| 440M | yuv422p10 | 59.94, 60 |
| 1920x1080p| 115M | yuv422p | 23.97, 24 |
| 1920x1080p| 120M | yuv422p | 25 |
| 1920x1080p| 145M | yuv422p | 29.97, 50 |
| 1920x1080p| 240M | yuv422p | 50 |
| 1920x1080p| 290M | yuv422p | 59.94, 60 |
| 1920x1080p| 175M | yuv422p | 23.97, 24 |
| 1920x1080p| 185M | yuv422p | 25 |
| 1920x1080p| 220M | yuv422p | 29.97 |
| 1920x1080p| 365M | yuv422p | 50 |
| 1920x1080p| 440M | yuv422p | 59.94, 60 |
| 1920x1080i| 185M | yuv422p10 | 25 |
| 1920x1080i| 220M | yuv422p10 | 29.97 |
| 1920x1080i| 120M | yuv422p | 25 |
| 1920x1080i| 145M | yuv422p | 29.97 |
| 1920x1080i| 185M | yuv422p | 25 |
| 1920x1080i| 220M | yuv422p | 29.97 |
| 1440x1080i| 120M | yuv422p | 25 |
| 1440x1080i| 145M | yuv422p | 29.97 |
| 1280x720p| 90M | yuv422p10 | 23.97, 24, 25 |
| 1280x720p| 180M | yuv422p10 | 50, 59.94, 60 |
| 1280x720p| 220M | yuv422p10 | 59.94, 60 |
| 1280x720p| 90M | yuv422p | 23.97, 24, 25 |
| 1280x720p| 110M | yuv422p | 29.97 |
| 1280x720p| 180M | yuv422p | 50 |
| 1280x720p| 220M | yuv422p | 59.94, 60 |
| 1280x720p| 60M | yuv422p | 23.97, 24, 25 |
| 1280x720p| 75M | yuv422p | 29.97 |
| 1280x720p| 120M | yuv422p | 50 |
| 1280x720p| 145M | yuv422p | 59.94, 60 |
| 1920x1080p| 36M | yuv422p | 23.97, 24, 25 |
| 1920x1080p| 45M | yuv422p | 29.97 |
| 1920x1080p| 75M | yuv422p | 50 |
| 1920x1080p| 90M | yuv422p | 59.94, 60 |
| 1920x1080p| 350M | yuv444p10, gbrp10 | 23.97, 24 |
| 1920x1080p| 390M | yuv444p10, gbrp10 | 25 |
| 1920x1080p| 440M | yuv444p10, gbrp10 | 29.97 |
| 1920x1080p| 730M | yuv444p10, gbrp10 | 50 |
| 1920x1080p| 880M | yuv444p10, gbrp10 | 59.94, 60 |
| 960x720p| 42M | yuv422p |
| 960x720p| 60M | yuv422p |
| 960x720p| 75M | yuv422p |
| 960x720p| 115M | yuv422p |
| 1440x1080p| 63M | yuv422p |
| 1440x1080p| 84M | yuv422p |
| 1440x1080p| 100M | yuv422p |
| 1440x1080p| 110M | yuv422p |
| 1440x1080i| 80M | yuv422p |
| 1440x1080i| 90M | yuv422p |
| 1440x1080i| 100M | yuv422p |
| 1440x1080i| 110M | yuv422p |

## TODO

* The output sizes dont vary with different profiles, which seems wildly wrong.
109 changes: 105 additions & 4 deletions enctests/test_configs/dnxhd_color_tests.yml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@

---
test_dnxhd_color:
test_dnxhd_444:
app: ffmpeg
comparisontest:
- testtype: idiff
Expand All @@ -14,15 +14,12 @@ test_dnxhd_color:
-y "{outfile}"
name: test_dnxhd_color
sources:
- ../sourceimages/chip-chart-1080-noicc.png.yml
- ../sourceimages/chip-chart-1080-16bit-noicc.png.yml
- ../sourceimages/smptehdbars_16.png.yml
suffix: .mov
wedges:
dnxhd-yuv444p10le: &basednxhd
-c:v: dnxhd
-profile:v: dnxhr_444
-b:v: 3M
-vf: '"scale=in_color_matrix=bt709:out_color_matrix=bt709"'
-color_primaries: bt709
-color_range: tv
Expand All @@ -36,6 +33,10 @@ test_dnxhd_color:

#-profile:v: main444-10

dnxhd-yuv444p10le-440m:
<< : *basednxhd
-b:v: 440m

dnxhd-gbrp10:
<< : *basednxhd
#-vf: '"scale=in_range=full:in_color_matrix=bt709:out_range=full:out_color_matrix=bt709"'
Expand All @@ -57,9 +58,109 @@ test_dnxhd_color:
#-colorspace: rgb
#-pix_fmt: gbrp10le

test_dnxhd_422:
app: ffmpeg
comparisontest:
- testtype: idiff
compare_image: ../sourceimages/chip-chart-1080-16bit-noicc-yuv422p10le.png
- testtype: assertresults
tests:
- assert: less
value: max_error
less: 0.00195
description: dnxhd color tests of different pix-fmts
encoding_template: ffmpeg -y {input_args} -i "{source}" {encoding_args}
-y "{outfile}"
name: test_dnxhd_color
sources:
- ../sourceimages/chip-chart-1080-16bit-noicc.png.yml
suffix: .mov
wedges:
dnxhqx: &basednxhqx
-c:v: dnxhd
-profile:v: dnxhr_hqx
-b:v: 440m
-vf: '"scale=in_color_matrix=bt709:out_color_matrix=bt709"'
-color_primaries: bt709
-color_range: tv
-color_trc: bt709
-colorspace: bt709
-pix_fmt: yuv422p10le
#-preset: 3
#-tag:v: hvc1


#-profile:v: main444-10

p10_440M:
<< : *basednxhqx
-profile:v: dnxhd
-pix_fmt: yuv422p10
-b:v: 440M

p10_365M:
<< : *basednxhqx
-profile:v: dnxhd
-pix_fmt: yuv422p10
-b:v: 365M

p10_185M:
<< : *basednxhqx
-profile:v: dnxhd
-pix_fmt: yuv422p10
-b:v: 185M

p10_175M:
<< : *basednxhqx
-profile:v: dnxhd
-pix_fmt: yuv422p10
-b:v: 175M

440M:
<< : *basednxhqx
-profile:v: dnxhr_hq
-pix_fmt: yuv422p
-b:v: 440M

185M:
<< : *basednxhqx
-profile:v: dnxhr_hq
-pix_fmt: yuv422p
-b:v: 185M

115M:
<< : *basednxhqx
-profile:v: dnxhr_hq
-pix_fmt: yuv422p
-b:v: 115M

---
reports:
graphs:
- args:
color: name
height: 400
barmode: group
x: media
y: max_error
name: max_error.png
type: bar
- args:
color: name
height: 400
x: media
barmode: group
y: encode_time
name: encode_time.png
type: bar
- args:
color: name
height: 400
x: media
barmode: group
y: filesize
name: filesize.png
type: bar
description: This is testing DNxHR color encoding.
directory: dnxhd-color-encode
name: dnxhd-color-tests
Expand Down
Loading

0 comments on commit 821a5f4

Please sign in to comment.