LoginSignup
1
1

More than 1 year has passed since last update.

iOS yuv videoRangeからyuv full rangeに変換する

Posted at

h.264動画でmetal処理するときよくyuv video rangeの動画がきていて、 full rang + rgb変換しないと処理できないので、knowhowとして残したいと思ってます。

方法1

自前でmetal変換

fragment float4 yuvVideoRangeToRGBFragmentShader(ColorInOut in [[ stage_in ]],
                               texture2d<float> baseYTexture [[ texture(0) ]],
                               texture2d<float> baseCbCrTexture [[ texture(1) ]]) {
   constexpr sampler colorSampler;
   const float4x4 ycbcrToRGBTransform = float4x4(
       float4(+1.0000f, +1.0000f, +1.0000f, +0.0000f),
       float4(+0.0000f, -0.3441f, +1.7720f, +0.0000f),
       float4(+1.4020f, -0.7141f, +0.0000f, +0.0000f),
       float4(-0.7010f, +0.5291f, -0.8860f, +1.0000f)
   );
   float4 baseYUVColor = float4(baseYTexture.sample(colorSampler, in.texCoords).r,
                                baseCbCrTexture.sample(colorSampler, in.texCoords).rg,
                                1.0f);
   // yuv video range to full range
   baseYUVColor.r = (baseYUVColor.r - (16.0f/255.0f)) * (255.0f/(235.0f-16.0f));
   baseYUVColor.g = (baseYUVColor.g - (16.0f/255.0f)) * (255.0f/(240.0f-16.0f));
   baseYUVColor.b = (baseYUVColor.b - (16.0f/255.0f)) * (255.0f/(240.0f-16.0f));


   // yuv to rgb
   float4 baseColor = ycbcrToRGBTransform * baseYUVColor;

   return baseColor;
}

方法2

AVAssetReaderTrackOutputのoutputSettingsでfull rangeに指定して、iOS側が変換してくれる

kCVPixelFormatType_420YpCbCr8BiPlanarFullRange は yuv full rangeで、
rgb直欲しい場合はkCVPixelFormatType_32BGRAしてすればいい。

 let outputSettings: [String: Any] = [
       // full rangeに指定
         kCVPixelBufferPixelFormatTypeKey as String: kCVPixelFormatType_420YpCbCr8BiPlanarFullRange,
         kCVPixelBufferMetalCompatibilityKey as String: true
       ]

let output = AVAssetReaderTrackOutput(track: asset.tracks(withMediaType: AVMediaType.video)[0], outputSettings: outputSettings)

おわり

方法1のほうがパフォーマンスとしていいが、方法2はOS側処理してくれるので、楽ではあるが、ほかの処理入れたいときにはパフォーマンスちょっと落ちる。

おまけ

hevc with aplha処理

hevc with aplha動画のpixelFormatがkCVPixelFormatType_420YpCbCr8VideoRange_8A_TriPlanarになっていて、
コードのコメント見るとyuv部分はvideo rangeだが、alpha部分はfull rangeなので、
処理するときは要注意。

kCVPixelFormatType_420YpCbCr8VideoRange_8A_TriPlanarソースのコメント:
/* first and second planes as per 420YpCbCr8BiPlanarVideoRange (420v), alpha 8 bits in third plane full-range. No CVPlanarPixelBufferInfo struct. */

参考:
https://developer.apple.com/documentation/corevideo/kcvpixelformattype_420ypcbcr8biplanarvideorange
https://developer.apple.com/documentation/corevideo/kcvpixelformattype_420ypcbcr8biplanarfullrange
https://developer.apple.com/documentation/corevideo/kcvpixelformattype_32bgra

1
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
1