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

Passthru Dolby Vision dynamic metadata #4838

Merged
merged 4 commits into from Feb 6, 2023
Merged

Conversation

galad87
Copy link
Contributor

@galad87 galad87 commented Jan 14, 2023

Implements reading and writing the Dolby Vision Configuration Record and the passing of the RPU buffers to x265.
I tested it on some profile 5 samples and the exported mp4 files can be played back properly in QuickTime Player.
Profile 5 seems to require the "dvh1" fourcc.

It adds a function to check whether to enable the dynamic metadata passthru or not, right now it's enabled only if there is no scaling or crop or rotation or pad and if the encoder is x265 10-bit.

x265 requires vbv-bufsize and vbv-maxrate to be set, I added some arbitrary values if they are not set by the user, if someone has got better ideas please tell.

Test on:

  • Windows 10+ (via MinGW)
  • macOS 10.13+
  • Ubuntu Linux

@galad87 galad87 mentioned this pull request Jan 14, 2023
@Nomis101
Copy link
Contributor

Thank you so much for your effort to implement this. I've tested this on two samples. The first one was a file recorded on my iPhone 12, which DOVI 8.7: Dolby Vision, Version 1.0, dvhe.08.07, BL+RPU, HLG compatible.
In this case it worked nicely. The resulting file had the same DOVI information.
Than I've tried with a sample from the movie 'No Time to Die' which does contain both, DOVI 7.6 and HDR10 informations:
Dolby Vision, Version 1.0, dvhe.07.06, BL+EL+RPU, Blu-ray compatible / SMPTE ST 2086, HDR10 compatible.
In this case it only passed the HDR10 information to the resulting file but not the DOVI informations.
I've disabled all cropping, scaling, filters what so ever for both tests.

@galad87
Copy link
Contributor Author

galad87 commented Jan 15, 2023

x265 supports only profile 5 and 8.

@fganter
Copy link

fganter commented Jan 15, 2023

Than I've tried with a sample from the movie 'No Time to Die' which does contain both, DOVI 7.6 and HDR10 informations: Dolby Vision, Version 1.0, dvhe.07.06, BL+EL+RPU, Blu-ray compatible / SMPTE ST 2086, HDR10 compatible. In this case it only passed the HDR10 information to the resulting file but not the DOVI informations. I've disabled all cropping, scaling, filters what so ever for both tests.

Good to know, as "No Time to Die" was going to be the first thing I tried.

@Nomis101
Copy link
Contributor

x265 supports only profile 5 and 8.

Ah, thanks for your explanation. Didn't know it only works for profiles that x265 supports. On the other hand, the doc says x265 supports 8.1, 8.2 and 8.4, but it was working for me with 8.7 from the iPhone.

@galad87
Copy link
Contributor Author

galad87 commented Jan 16, 2023

x265 values are [Dolby Vision bitstream profile ID].[BL signal cross- compatibility ID], the one reported by mediainfo are in the [Dolby Vision bitstream profile ID].[Dolby Vision Level ID] format.
iPhone recording are profile 8 and BL signal cross- compatibility 4.

@galad87
Copy link
Contributor Author

galad87 commented Jan 20, 2023

The latest commits integrate libdovi, so it will convert profile 7 to 8.1 and set the area offsets, and it allow scaling, cropping, and padding.
The issue is that libdovi requires rust compiler and cargoc, so at the moment you have to enable it manually by passing --enable-libdovi to configure and build from the cli on macOS.

@galad87 galad87 force-pushed the dolbyvision branch 2 times, most recently from ccedf6a to 202b920 Compare January 20, 2023 19:02
@Nomis101
Copy link
Contributor

Wow, you are incredible. This works perfectly. It converted the sample from the movie 'No Time to Die' from above nicely from DOVI 7 to DOVI 8. Even with cropping. And it also preserved the HDR10 informations as well.
It did build nicely as x86_64, but I have issues building it as universal binary. And installing cargoc was quite tricky (it didn't like something I had installed in /usr/localso I had to delete to complete folder first and reinstall everything).

@quietvoid
Copy link
Contributor

quietvoid commented Jan 21, 2023

One issue I found is when scaling down and padding, the level 5 metadata is only set for the specified padding.
Even though the video is scaled down preserving the aspect ratio.

For example, scaling 2160p to 1080p and padding top/bottom by 76.
The level 5 ends up with 76 offsets for top/bottom only, while left/right are left zero.
The output video actually has bars on the left and right.

@galad87
Copy link
Contributor Author

galad87 commented Jan 21, 2023

Aren't those left/right bar added by the player? If they are not in the actual video I think the value should be zero.

I noticed that if I pad the padded area is still tone mapped in QuickTime Player, but it could be that the pad filter is not setting the color to pure black, I'll have to investigate.

@sr55
Copy link
Contributor

sr55 commented Jan 21, 2023

Linker trouble on Ubuntu MinGW

/home/scott/toolchains/mingw-w64-8.0.0-gcc-10.2.0/mingw-w64-x86_64/bin/x86_64-w64-mingw32-gcc -std=gnu99 -pipe -fmessage-length=0 -Wall -Wno-format-truncation -g0 -O3 -mfpmath=sse -msse2 -fstack-protector-strong -D_FORTIFY_SOURCE=2 -mno-ms-bitfields -DPTW32_STATIC_LIB -I./libhb/ -I./contrib/include -I./contrib/include/vpl -I./contrib/include/libxml2 -c ../test/test.c -o test/test.o /home/scott/toolchains/mingw-w64-8.0.0-gcc-10.2.0/mingw-w64-x86_64/bin/x86_64-w64-mingw32-g++ -pipe -Wl,-S -static -fmessage-length=0 -Wall -Wno-format-truncation -g0 -O3 -mfpmath=sse -msse2 -fstack-protector-strong -D_FORTIFY_SOURCE=2 -mno-ms-bitfields -DPTW32_STATIC_LIB -I./libhb/ -I./contrib/include -I./contrib/include/vpl -I./contrib/include/libxml2 -o HandBrakeCLI.exe -Wl,--start-group test/parsecsv.o test/test.o ./libhb/libhandbrake.a -L./contrib/lib -lass -lavformat -lavfilter -lavcodec -lavutil -lswresample -lpostproc -lmp3lame -ldvdnav -ldvdread -lfribidi -lswscale -lvpx -ltheoraenc -ltheoradec -lvorbis -lvorbisenc -logg -lx264 -lbluray -lfreetype -lxml2 -lbz2 -lz -ljansson -lharfbuzz -lopus -lspeex -llzma -ldav1d -lturbojpeg -lzimg -lSvtAv1Enc -lvpl -ldovi -lx265 -ldovi -lpthread -lbcrypt -liconv -lws2_32 -lregex -luuid -lole32 -lgdi32 -Wl,--end-group /home/scott/toolchains/mingw-w64-8.0.0-gcc-10.2.0/mingw-w64-x86_64/lib/gcc/x86_64-w64-mingw32/10.2.0/../../../../x86_64-w64-mingw32/bin/ld: libhb/rpu.o:rpu.c:(.text+0x9e): undefined reference to dovi_parse_unspec62_nalu'
/home/scott/toolchains/mingw-w64-8.0.0-gcc-10.2.0/mingw-w64-x86_64/lib/gcc/x86_64-w64-mingw32/10.2.0/../../../../x86_64-w64-mingw32/bin/ld: libhb/rpu.o:rpu.c:(.text+0xf4): undefined reference to dovi_rpu_get_header' /home/scott/toolchains/mingw-w64-8.0.0-gcc-10.2.0/mingw-w64-x86_64/lib/gcc/x86_64-w64-mingw32/10.2.0/../../../../x86_64-w64-mingw32/bin/ld: libhb/rpu.o:rpu.c:(.text+0x10d): undefined reference to dovi_rpu_free_header'
/home/scott/toolchains/mingw-w64-8.0.0-gcc-10.2.0/mingw-w64-x86_64/lib/gcc/x86_64-w64-mingw32/10.2.0/../../../../x86_64-w64-mingw32/bin/ld: libhb/rpu.o:rpu.c:(.text+0x11c): undefined reference to dovi_rpu_get_vdr_dm_data' /home/scott/toolchains/mingw-w64-8.0.0-gcc-10.2.0/mingw-w64-x86_64/lib/gcc/x86_64-w64-mingw32/10.2.0/../../../../x86_64-w64-mingw32/bin/ld: libhb/rpu.o:rpu.c:(.text+0x21b): undefined reference to dovi_rpu_set_active_area_offsets'
/home/scott/toolchains/mingw-w64-8.0.0-gcc-10.2.0/mingw-w64-x86_64/lib/gcc/x86_64-w64-mingw32/10.2.0/../../../../x86_64-w64-mingw32/bin/ld: libhb/rpu.o:rpu.c:(.text+0x228): undefined reference to dovi_rpu_free_vdr_dm_data' /home/scott/toolchains/mingw-w64-8.0.0-gcc-10.2.0/mingw-w64-x86_64/lib/gcc/x86_64-w64-mingw32/10.2.0/../../../../x86_64-w64-mingw32/bin/ld: libhb/rpu.o:rpu.c:(.text+0x23b): undefined reference to dovi_write_unspec62_nalu'
/home/scott/toolchains/mingw-w64-8.0.0-gcc-10.2.0/mingw-w64-x86_64/lib/gcc/x86_64-w64-mingw32/10.2.0/../../../../x86_64-w64-mingw32/bin/ld: libhb/rpu.o:rpu.c:(.text+0x296): undefined reference to dovi_data_free' /home/scott/toolchains/mingw-w64-8.0.0-gcc-10.2.0/mingw-w64-x86_64/lib/gcc/x86_64-w64-mingw32/10.2.0/../../../../x86_64-w64-mingw32/bin/ld: libhb/rpu.o:rpu.c:(.text+0x2e3): undefined reference to dovi_convert_rpu_with_mode'
/home/scott/toolchains/mingw-w64-8.0.0-gcc-10.2.0/mingw-w64-x86_64/lib/gcc/x86_64-w64-mingw32/10.2.0/../../../../x86_64-w64-mingw32/bin/ld: libhb/rpu.o:rpu.c:(.text+0x2ef): undefined reference to dovi_rpu_remove_mapping' /home/scott/toolchains/mingw-w64-8.0.0-gcc-10.2.0/mingw-w64-x86_64/lib/gcc/x86_64-w64-mingw32/10.2.0/../../../../x86_64-w64-mingw32/bin/ld: ./libhb/libhandbrake.a(rpu.o):rpu.c:(.text+0x9e): undefined reference to dovi_parse_unspec62_nalu'
/home/scott/toolchains/mingw-w64-8.0.0-gcc-10.2.0/mingw-w64-x86_64/lib/gcc/x86_64-w64-mingw32/10.2.0/../../../../x86_64-w64-mingw32/bin/ld: ./libhb/libhandbrake.a(rpu.o):rpu.c:(.text+0xf4): undefined reference to dovi_rpu_get_header' /home/scott/toolchains/mingw-w64-8.0.0-gcc-10.2.0/mingw-w64-x86_64/lib/gcc/x86_64-w64-mingw32/10.2.0/../../../../x86_64-w64-mingw32/bin/ld: ./libhb/libhandbrake.a(rpu.o):rpu.c:(.text+0x10d): undefined reference to dovi_rpu_free_header'
/home/scott/toolchains/mingw-w64-8.0.0-gcc-10.2.0/mingw-w64-x86_64/lib/gcc/x86_64-w64-mingw32/10.2.0/../../../../x86_64-w64-mingw32/bin/ld: ./libhb/libhandbrake.a(rpu.o):rpu.c:(.text+0x11c): undefined reference to dovi_rpu_get_vdr_dm_data' /home/scott/toolchains/mingw-w64-8.0.0-gcc-10.2.0/mingw-w64-x86_64/lib/gcc/x86_64-w64-mingw32/10.2.0/../../../../x86_64-w64-mingw32/bin/ld: ./libhb/libhandbrake.a(rpu.o):rpu.c:(.text+0x21b): undefined reference to dovi_rpu_set_active_area_offsets'
/home/scott/toolchains/mingw-w64-8.0.0-gcc-10.2.0/mingw-w64-x86_64/lib/gcc/x86_64-w64-mingw32/10.2.0/../../../../x86_64-w64-mingw32/bin/ld: ./libhb/libhandbrake.a(rpu.o):rpu.c:(.text+0x228): undefined reference to dovi_rpu_free_vdr_dm_data' /home/scott/toolchains/mingw-w64-8.0.0-gcc-10.2.0/mingw-w64-x86_64/lib/gcc/x86_64-w64-mingw32/10.2.0/../../../../x86_64-w64-mingw32/bin/ld: ./libhb/libhandbrake.a(rpu.o):rpu.c:(.text+0x23b): undefined reference to dovi_write_unspec62_nalu'
/home/scott/toolchains/mingw-w64-8.0.0-gcc-10.2.0/mingw-w64-x86_64/lib/gcc/x86_64-w64-mingw32/10.2.0/../../../../x86_64-w64-mingw32/bin/ld: ./libhb/libhandbrake.a(rpu.o):rpu.c:(.text+0x296): undefined reference to dovi_data_free' /home/scott/toolchains/mingw-w64-8.0.0-gcc-10.2.0/mingw-w64-x86_64/lib/gcc/x86_64-w64-mingw32/10.2.0/../../../../x86_64-w64-mingw32/bin/ld: ./libhb/libhandbrake.a(rpu.o):rpu.c:(.text+0x2e3): undefined reference to dovi_convert_rpu_with_mode'
/home/scott/toolchains/mingw-w64-8.0.0-gcc-10.2.0/mingw-w64-x86_64/lib/gcc/x86_64-w64-mingw32/10.2.0/../../../../x86_64-w64-mingw32/bin/ld: ./libhb/libhandbrake.a(rpu.o):rpu.c:(.text+0x2ef): undefined reference to dovi_rpu_remove_mapping' collect2: error: ld returned 1 exit status make: *** [../libhb/module.rules:37: libhb/hb.dll] Error 1 make: *** Waiting for unfinished jobs.... collect2: error: ld returned 1 exit status make: *** [../test/module.rules:49: HandBrakeCLI.exe] Error 1

@quietvoid
Copy link
Contributor

quietvoid commented Jan 21, 2023

Aren't those left/right bar added by the player? If they are not in the actual video I think the value should be zero.

Oh, you're right the video doesn't have them.
Then yes everything's fine.

edit: nvm the new comment, it really is my player adding the bars because the display has higher resolution.

@galad87
Copy link
Contributor Author

galad87 commented Jan 21, 2023

That's the dimensions tab doing some weird things and making your video anamorphic. There isn't an actual border on left and right, it's just that the pixels are not square because it tries to put the borders in, but the resolution limit is 1080p, so it does change the pixel aspect ratio and squeeze everything to get space for borders.

Disable anamorphic, and the resolution limit, to create something more common.

@Nomis101
Copy link
Contributor

Building as universal binary is now fixed for me on macOS.

@jeroenjeremy
Copy link

Building as universal binary is now fixed for me on macOS.

Would you mind making that universal binary available for download? Would love to test on DV iPhone video but am not expert enough to compile myself.
I promise to report back the results!

@jeroenjeremy
Copy link

...

It adds a function to check whether to enable the dynamic metadata passthru or not, right now it's enabled only if there is no scaling or crop or rotation or pad and if the encoder is x265 10-bit.
...

Will this work with Video Toolbox as encoder?

@galad87
Copy link
Contributor Author

galad87 commented Jan 27, 2023

Not yet, only x265 for now.

I tried some iPhone DV videos but QuickTime Player seem to ignore the the DV part in the converted video. Maybe it requires the Ambient Viewing Environment SEI to work?

@Nomis101
Copy link
Contributor

FFmpeg quite recently added a number of patches for Ambient Viewing Environment. Would this help us?

@quietvoid
Copy link
Contributor

quietvoid commented Jan 30, 2023

FYI, libdovi 3.1.0 now automatically does the dovi_rpu_remove_mapping step, with mode 2.
For profile 7 FEL only.

@galad87
Copy link
Contributor Author

galad87 commented Feb 2, 2023

@sr55 mingw should work now, probably you need to install the windows target with:

rustup target add x86_64-pc-windows-gnu

@Nomis101
Copy link
Contributor

Nomis101 commented Feb 2, 2023

Building as universal binary is now fixed for me on macOS.

Would you mind making that universal binary available for download? Would love to test on DV iPhone video but am not expert enough to compile myself. I promise to report back the results!

Sorry, I was busy and have forgotten about this one. Sure, I could, but you can also click on the top on "Actions" and download a build from the "Passthru Dolby Vision dynamic metadata" workflow there. For example this one: https://github.com/HandBrake/HandBrake/actions/runs/4075056980
(I don't know after how many days the build is getting removed)

EDIT: Please ignore the comment above. I have forgotten that you need to explicitly set a flag. I can provide you a UB build on the weekend...

@lucimon97
Copy link

Hi, I ran a test using this and because No Time To Die was mentioned as working I tried that. Dropped all audio and subtitles, selected ultrafast and just told him to send it. I don't know if it disagrees with the encoder speed or what the issue is, but it still dropped the dovi for me. I pastebined the Handbrake log and the mediainfo blurb (for the video portion) for the rip and the encoded file. Maybe I'm doing something wrong or is Windows just not it atm?

@galad87
Copy link
Contributor Author

galad87 commented Feb 3, 2023

It's not enabled in the automatic builds on GitHub yet. You have to build it yourself.

@jeroenjeremy
Copy link

jeroenjeremy commented Feb 3, 2023

Sorry, I was busy and have forgotten about this one. Sure, I could, but you can also click on the top on "Actions" and download a build from the "Passthru Dolby Vision dynamic metadata" workflow there. For example this one: https://github.com/HandBrake/HandBrake/actions/runs/4075056980 (I don't know after how many days the build is getting removed)

Much appreciated! Downloaded this build and tried it on a DV 8.4 home video (iPhone 13 Pro) but it doesn't seem to pass through any DV data (tried all different 265 variations). Maybe Galad87's comment means these improvements are not in this build either?

@Nomis101
Copy link
Contributor

Nomis101 commented Feb 4, 2023

Building as universal binary is now fixed for me on macOS.

Would you mind making that universal binary available for download? Would love to test on DV iPhone video but am not expert enough to compile myself. I promise to report back the results!

[link removed]
(I will remove the build and the link after some days)

@jeroenjeremy
Copy link

jeroenjeremy commented Feb 4, 2023

https://polysom.verilite.de/tmp/HandBrake-20230204105257-a7b67361b-dolbyvision.zip (I will remove the build and the link after some days)

Thanks so much, this build works for an iPhone video, selecting h.265 10-bit as the video encoder.

… vision dynamic metadata if the encoder is x265 and there is no scale/crop/rotate/pad filter.
@jeroenjeremy
Copy link

Would be wonderful if it could also work with encoder Video Toolbox, as it's so much faster.

@galad87
Copy link
Contributor Author

galad87 commented Feb 5, 2023

@quietvoid I am getting errors in two frames at the beginning in dvesverifier: https://gist.github.com/galad87/9a5194ffde78cf89967b2ce7aac4066c

even when passing through the RPU with zero changes.

Something is going not exactly in the right way in x265 or I am passing something wrong to it, do you know a tool to analyse the HEVC NALs and check what's wrong?

@quietvoid
Copy link
Contributor

quietvoid commented Feb 5, 2023

@quietvoid I am getting errors in two frames at the beginning in dvesverifier: https://gist.github.com/galad87/9a5194ffde78cf89967b2ce7aac4066c

even when passing through the RPU with zero changes.

Something is going not exactly in the right way in x265 or I am passing something wrong to it, do you know a tool to analyse the HEVC NALs and check what's wrong?

You can simply dump the RPU with dovi_tool, then use dovi_tool info RPU.bin -f 0 to see the first frame metadata.
The verifier demands specific metadata block levels but they are often not present, even in retail samples.

So there isn't much we can do about it.

I'm not exactly sure about the RPU position errors but this is something you could check with software like hevcesbrowser or just tracing the NALs with ffmpeg.
I'd think it's just the RPU validation errors that propagated to other verifications.

@galad87
Copy link
Contributor Author

galad87 commented Feb 6, 2023

The source file validates in dvesverifier, but the encoded file has got one at max two errors in the first 20 frames. The exported RPU are exactly the same, I have no idea of what's tripping dvesverifier.
It doesn't seem to cause any issue when actually playing back the file.

One last doubt I have: HandBrake can generate black frames to keep audio/video sync in some weird situations, I assume all frames in a Dolby Vision require a RPU, is there a way to generate one for black frames?

@quietvoid
Copy link
Contributor

quietvoid commented Feb 6, 2023

Sorry I had misunderstood. I'm not able to reproduce the verifier errors, even after reencoding with HB.

As for the black frames, there isn't a way to generate them from the C API.
Usually what you'd do is to use the same RPU as the frames after, as long as they are also black.

I guess it is something I'd have to look into. The problem is that generated RPUs are usually not 100% compliant as some metadata levels are missing.
It can be done, I just haven't looked at including generation through the C API.

@galad87
Copy link
Contributor Author

galad87 commented Feb 6, 2023

Usually the black frames are inserted at the beginning, if the video don' start at 0, it doesn't happen too often. I could make it save a random RPU during a scan or something like that.

@galad87 galad87 merged commit 0344426 into HandBrake:master Feb 6, 2023
@jeroenjeremy
Copy link

Can this functionality also be added to Video Toolbox encoding? Let me know if I should open a separate issue.

@rathann
Copy link

rathann commented Sep 6, 2023

Half a year later, only small bits of this are in FFmpeg upstream. Are there any plans to submit the remaining parts? In particular:
contrib/ffmpeg/A27-movenc-enable-dvh1.patch
contrib/ffmpeg/A30-ambient-viewing-fix.patch
contrib/ffmpeg/A33-ambient-viewing-pkt-data.patch

@galad87
Copy link
Contributor Author

galad87 commented Sep 6, 2023

I think you submitted the first one, and I submitted the ambient viewing environment ones. They are on the ffmpeg-devel mailing list.

@rathann
Copy link

rathann commented Sep 6, 2023

Right, I've just found your updated submission. Thanks for being upstream-friendly! It makes my life as a package maintainer easier.

@galad87
Copy link
Contributor Author

galad87 commented Sep 6, 2023

Compiling HandBrake using a different version of FFmpeg or other libraries is still a bug fest, but I guess you already know 😝

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Development

Successfully merging this pull request may close these issues.

None yet

8 participants