H264 from AVC Intra Colours Wrong

Here you can submit bugreports
emcodem
Posts: 1918
Joined: Wed Sep 19, 2018 8:11 am

Re: H264 from AVC Intra Colours Wrong

Post by emcodem »

graham728 wrote: Sat Feb 01, 2025 1:32 pm I'm not sure if the Adobe Media Encoder MXF is buggy
Unfortunately Premiere has never been optimal when it comes to the exported Files Metadata.
Sure might be that it worked before in ffastrans and maybe works later but that does not change the fact that AME exports a file with different Metadata in Stream vs. Container. in your specific case.
We recently discovered the exact same problem for XAVC export at work, e.g. XAVC-L was tagged correctly but XAVC-I had the exact same problem as your file did. Sure we opened a case with Adobe so they can resolve the issue in future versions. Also as we have strict file quality restrictions, we cannot use the AME feature that produces wrongly tagged files (XAVC-I export in this case) and must wait for an updated version that fixes the issue.
emcodem, wrapping since 2009 you got the rhyme?
Pogle
Posts: 17
Joined: Fri Mar 27, 2020 10:03 am

Re: H264 from AVC Intra Colours Wrong

Post by Pogle »

Hi! I've just encountered the level lange problem too (v1.4.1). Has anyone tested v1.4.2.10?
We have a lot of MXF files (1920x1080, 10 bit, 25p, 50i, OP1a, AVC Intra 100) with incorrect metadata (Mediainfo - color range: limited, color range original: full). In my FFAStrans workflows the misinterpreted level range only appears if I use the watermark filter to insert a logo.
A/V Media Decoder (doesn't matter if used or bypassed) > watermark filter > h.264 encoder >> levels shifted
A/V Media Decoder (doesn't matter if used or bypassed) > other filters (resize, TC burn in) > h.264 encoder >> levels not shifted
When I use AVC Intra files with only one color range info (= limited) everything is fine.
Why is only the watermark filter leading to this problem? Does it try to match the level range of the video to the level range of the logo?
User avatar
FranceBB
Posts: 304
Joined: Sat Jun 25, 2016 3:43 pm
Contact:

Re: H264 from AVC Intra Colours Wrong

Post by FranceBB »

Pogle wrote: Thu Jul 31, 2025 4:44 pm Has anyone tested v1.4.2.10?
The upcoming v1.4.2 won't save you from this because it's not technically a bug, the source metadata is wrong, we're just trying to do "the right thing" under the hood.
Pogle wrote: Thu Jul 31, 2025 4:44 pm We have a lot of MXF files (1920x1080, 10 bit, 25p, 50i, OP1a, AVC Intra 100) with incorrect metadata (Mediainfo - color range: limited, color range original: full).
Yep, that basically happens when the metadata in the mxf container was set to limited tv range, but the raw_video.h264 stream was encoded as full pc range and therefore you end up with a mismatch.
Pogle wrote: Thu Jul 31, 2025 4:44 pm In my FFAStrans workflows the misinterpreted level range only appears if I use the watermark filter to insert a logo.
Why is only the watermark filter leading to this problem?
Well, the very short answer would be: because we're going through an RGB roundtrip.
Let me explain.
Back in the days there were two main functions to paint an image over a video in Avisynth as a frameserver: Overlay and Layer. The first was working in YUV, while the latter was working in RGB. We're talking about a time when there were only RGB24, RGB32, YV12, YUY2 available. Anyway, in FFAStrans we picked the latter, so Layer, which is why we're going to RGB.
(As a tiny side note, plenty of other sampling, colorspaces and bit depth have been added to this awesome frameserver and the layer function now supports most of them).

Anyway, what happens under the hood in FFAStrans is:

1) We index the source with FFVideoSource()
2) We convert it to RGB24 with ConverttoRGB24()
3) We index the image with ImageSource() and set it of as many frames as the source video
4) We "overlay" the two with the Layer() function
5) We go back to YUV

The issue occurs at point 2.

In Avisynth that would correspond to something like this:

Code: Select all

#Indexing the source
FFVideoSource("test.mxf")

#Bringing everything to RGB
ConverttoRGB24() # <- here the issue occurs
video=last

#Indexing the picture
ImageSource("test.png", start=0, end=video.FrameCount, fps=25, pixel_type="RGB24")
picture=last

#Overlay them one of top of the other
Layer(video, picture, op="add", opacity=0.5, x=0, y=0)

#Going back to YUV
ConverttoYV24()
Obviously in the actual watermark node the opacity, x and y are actually variables as they're dependent on the input that the user is inserting, but I've just set them like this here as an example.

So, since this is the world wide web, let's take two of the most common things: colorbars (to mock the video source) and a picture of a cat I took in May while walking towards the office (to simulate the image).

As you can see the Colorbars() are limited tv range going from 0.0 to 0.7V (i.e 16-235 in 8bit) aside from the "superblack" section that goes below:

Image

When I convert this to RGB with ConverttoRGB24() this becomes Full PC Range with the white touching 255 and the black touching 0.

Image

When we overlay the picture of the cat in RGB Full PC Range nothing bad happens as we're still in 0-255:

Image

And when we go back to YUV we're back in Limited TV Range, so 16-235

Image


The problem occurs when the source is limited tv range but is actually flagged as full pc range. In Avisynth when an indexer like FFVideoSource() is invoked, it will "index" the source and output an uncompressed A/V stream living in RAM that you can work with in the frameserver. This means that in the case of your AVC Intra Class files with the container set to limited and the stream set to full, it will say "full" as it will honor whatever the raw_video.h264 was encoded as. It's possible to see this by checking the _ColorRange() value of the frame properties where 0 means "Full PC Range" and 1 means "Limited TV Range". Anyway, to simulate this, we can use PropSet("_ColorRange", 0).

What happens when we do this:

Code: Select all

#Indexing the source
ColorBars(848, 480, pixel_type="YV24")
ChangeFPS(25)

PropSet("_ColorRange", 0)

#Bringing everything to RGB Full PC Range
ConverttoRGB24()
is that the ConverttoRGB24() function will say "oh, cool, I have a full pc range source, no need to change levels from limited to full", so it will leave everything as it is, then we're gonna go through the rest of the flow and have the picture overlaid in RGB and guess what happens when we go back to YUV at the very end with ConverttoYV24()? Well, it *thinks* that it's dealing with a Full PC Range source in RGB so it will convert the levels back to Limited TV Range to go to YUV, but actually we were already in limited tv range, so we get the "limited of limited", so everything is shifted twice, hence the issue:

Image


The only way to overcome this would be to change the frame properties right after indexing and to do that you can add a Custom AVS Script and set it like this:

Code: Select all

#Set to Limited TV Range
m_clip=propSet(m_clip, "_ColorRange", 1)

return m_clip
graham728
Posts: 95
Joined: Sat Oct 13, 2018 10:54 pm

Re: H264 from AVC Intra Colours Wrong

Post by graham728 »

Hi,

Sorry to bring this back up - I can see that this was fixed in your new version, which is great!

I'm wondering if I can get a little help as to what the fix was? I have a custom Python script I'm using for some automation and the same thing is happening. FFMPEG is lifting the colours on Adobe MXF AVC Intra files due to it having (I think) two colour metadata tags of Limited and Full within the metadata. Adobe have stated this is correct as the 2005 spec for AVC states it must have this. Although, other professional transcoders don't do this to AVC MXF files and my python app works perfectly with them.

The encoding code I'm using is below - any pointers would be great!

Code: Select all

def transcode_video(self, input_file, output_file):
    """Transcode single video file using ffmpeg"""
    # Get video duration and framerate for progress calculation
    duration = self.get_video_duration(input_file)
    source_fps = self.get_video_framerate(input_file)
    
    # Update current file info
    filename = os.path.basename(input_file)
    fps_info = f" (Source: {source_fps:.2f}fps)" if source_fps else ""
    self.current_file_var.set(f"Processing: {filename}{fps_info}")
    self.current_progress_var.set(0)
    self.current_file_start_time = time.time()
    
    # Build ffmpeg command - STANDARD SETTINGS FOR ALL FILES
    cmd = [
        'ffmpeg',
        '-i', input_file,
        '-y',  # Overwrite output files without asking
        '-progress', 'pipe:1',  # Output progress to stdout
    ]
    
    # Video filters - standard processing for all files
    video_filters = ['yadif=0:-1:0', 'scale=1280:720']
    if source_fps:
        video_filters.append(f'fps={source_fps}')
    
    video_filter = ','.join(video_filters)
    
    cmd.extend([
        '-vf', video_filter,
        '-c:v', 'libx264',  # H.264 video codec
        '-b:v', '2M',  # 2 Mbps video bitrate
        '-maxrate', '2M',
        '-bufsize', '4M',
        '-profile:v', 'high',
        '-level', '4.0',
        '-pix_fmt', 'yuv420p',
        '-color_range', 'tv',  # Limited range output
        '-color_primaries', 'bt709',
        '-color_trc', 'bt709',
        '-colorspace', 'bt709',
        '-c:a', 'aac',  # AAC audio codec
        '-b:a', '320k',  # 320 kbps audio bitrate
        '-ac', '2',  # Stereo audio
        '-ar', '48000',  # 48kHz sample rate
        '-movflags', '+faststart',  # Progressive download
        output_file
    ])
User avatar
FranceBB
Posts: 304
Joined: Sat Jun 25, 2016 3:43 pm
Contact:

Re: H264 from AVC Intra Colours Wrong

Post by FranceBB »

it's probably not "lifting" them but rather just passing the wrong metadata despite setting the -color_range tv in the command line. Check the Mediainfo of the encoded file. If it still shows the limited/full mismatch, then that's likely the cause.
Try to add a good old -map_metadata -1 in the FFMpeg command line and check if the metadata mismatch is still there.
graham728
Posts: 95
Joined: Sat Oct 13, 2018 10:54 pm

Re: H264 from AVC Intra Colours Wrong

Post by graham728 »

Thanks FranceBB

I've added the code below - the output is still lighter than the source.

Code: Select all

# Build ffmpeg command - STANDARD SETTINGS FOR ALL FILES
cmd = [
    'ffmpeg',
    '-i', input_file,
    '-y',  
    '-map_metadata', '-1', 
    '-progress', 'pipe:1',  
]

# Video filters - standard processing for all files
video_filters = ['yadif=0:-1:0', 'scale=1280:720']
if source_fps:
    video_filters.append(f'fps={source_fps}')

video_filter = ','.join(video_filters)

cmd.extend([
    '-vf', video_filter,
    '-c:v', 'libx264',  # H.264 video codec
    '-b:v', '2M',  # 2 Mbps video bitrate
    '-maxrate', '2M',
    '-bufsize', '4M',
    '-profile:v', 'high',
    '-level', '4.0',
    '-pix_fmt', 'yuv420p',
    '-color_range', 'tv',  # Limited range output
    '-color_primaries', 'bt709',
    '-color_trc', 'bt709',
    '-colorspace', 'bt709',
    '-c:a', 'aac',  # AAC audio codec
    '-b:a', '320k',  # 320 kbps audio bitrate
    '-ac', '2',  # Stereo audio
    '-ar', '48000',  # 48kHz sample rate
    '-movflags', '+faststart',  # Progressive download
    output_file
])
___


Source AVC Intra has this double metadata for colour which Adobe are claiming is correct. Even though Telestream Vantage AVC Intra files do not have this.
Color range :
Limited
colour_range_Original :
Full

__

H264 Output

Video
ID :
1
Format :
AVC
Format/Info :
Advanced Video Codec
Format profile :
High@L4
Format settings :
CABAC / 4 Ref Frames
Format settings, CABAC :
Yes
Format settings, Reference frames :
4 frames
Codec ID :
avc1
Codec ID/Info :
Advanced Video Coding
Duration :
25 s 0 ms
Bit rate :
1 232 kb/s
Nominal bit rate :
2 000 kb/s
Maximum bit rate :
2 000 kb/s
Width :
1 280 pixels
Height :
720 pixels
Display aspect ratio :
16:9
Frame rate mode :
Constant
Frame rate :
25.000 FPS
Color space :
YUV
Chroma subsampling :
4:2:0
Bit depth :
8 bits
Scan type :
Progressive
Bits/(Pixel*Frame) :
0.053
Stream size :
3.67 MiB (93%)
Writing library :
x264 core 164 r3108 31e19f9
Encoding settings :
cabac=1 / ref=3 / deblock=1:0:0 / analyse=0x3:0x113 / me=hex / subme=7 / psy=1 / psy_rd=1.00:0.00 / mixed_ref=1 / me_range=16 / chroma_me=1 / trellis=1 / 8x8dct=1 / cqm=0 / deadzone=21,11 / fast_pskip=1 / chroma_qp_offset=-2 / threads=15 / lookahead_threads=2 / sliced_threads=0 / nr=0 / decimate=1 / interlaced=0 / bluray_compat=0 / constrained_intra=0 / bframes=3 / b_pyramid=2 / b_adapt=1 / b_bias=0 / direct=1 / weightb=1 / open_gop=0 / weightp=2 / keyint=250 / keyint_min=25 / scenecut=40 / intra_refresh=0 / rc_lookahead=40 / rc=cbr / mbtree=1 / bitrate=2000 / ratetol=1.0 / qcomp=0.60 / qpmin=0 / qpmax=69 / qpstep=4 / vbv_maxrate=2000 / vbv_bufsize=4000 / nal_hrd=none / filler=0 / ip_ratio=1.40 / aq=1:1.00
Color range :
Limited
Color primaries :
BT.709
Transfer characteristics :
BT.709
Matrix coefficients :
BT.709
Codec configuration box :
avcC
Attachments
example.png
example.png (821.62 KiB) Viewed 111059 times
emcodem
Posts: 1918
Joined: Wed Sep 19, 2018 8:11 am

Re: H264 from AVC Intra Colours Wrong

Post by emcodem »

@ graham728
My guess would be that the range is really compressed because input is flagged full and you specify tv output range.
We need to find a way to override/assume the input range.

One way to do that is to use this as an input option (before -i):
-bsf:v h264_metadata=video_full_range_flag=0

a full successful command:

Code: Select all

ffmpeg -bsf:v h264_metadata=video_full_range_flag=1 -i C:\temp\out0.mp4 c:\temp\outforcetv.mp4
map_metadata does nothing in these regards, the term metadata in ffmpeg does not refer to this type of "technical metadata" of the input file but more stuff like "produced by gopro" metadata
Adobe have stated this is correct as the 2005 spec for AVC states it must have this.
The only standard that counts for XAVC is RDD32 but i dont have in mind if it mentions h264 metadata at all, probably not, can check that tomorrow. However i think RDD32 is from 2017 so i doubt that it links to a h264 ITU paper from 2005
emcodem, wrapping since 2009 you got the rhyme?
graham728
Posts: 95
Joined: Sat Oct 13, 2018 10:54 pm

Re: H264 from AVC Intra Colours Wrong

Post by graham728 »

Great! Thanks Emcodem - that appears to have done the trick. Many thanks!
emcodem
Posts: 1918
Joined: Wed Sep 19, 2018 8:11 am

Re: H264 from AVC Intra Colours Wrong

Post by emcodem »

I just found out its definitely not only Adobe producing such XAVC files, Sony does it too. So after all Adobe might have a good reason to do it how they do it. If Sony does it on their cameras, we cannot really force Adobe to do it different to sony..
mixedrange.jpg
mixedrange.jpg (115.67 KiB) Viewed 110862 times
In above Image we see only files delivery statistics from 2 years that have mixed full/limited signalling, all of them are flagged limited in mxf container and full in h264 stream (regarding to mediainfo). Most of them are from Sony (no wonder, we are on XDCAM and all Premiere can produce XDCAM but not all Sony cams can).
emcodem, wrapping since 2009 you got the rhyme?
graham728
Posts: 95
Joined: Sat Oct 13, 2018 10:54 pm

Re: H264 from AVC Intra Colours Wrong

Post by graham728 »

Yeah Adobe seemed rather confused AVC Intra MXF was being used for mastering video content too. It took a few attempts to get them to understand that I wasn't transcoding/rendering camera media, but rather Premiere Pro sequences.

We use AVC Intra 100 as that is the same codec we use in DPP AS-11 formats here in the UK.

Funnily enough, we can't use their AS-11 preset as Vidchecker doesn't like its colour metadata either! (Separate issue) - It's another case of Adobe being technically correct but not conforming to how the industry is really using the formats.
Post Reply