Skip to content
This repository was archived by the owner on Feb 25, 2025. It is now read-only.

Conversation

@cikelengfeng
Copy link
Contributor

iOS external texture supports rendering NV12 pixelbuffer

At present, the external texture of iOS only supports pixelbuffer in BGRA32 format, but many times we need to use pixelbuffer in YUV format, such as NV12. Compared with BGRA32, NV12 requires less memory (about 37.5% of BGRA32), so we need to support rendering pixelbuffer in NV12 format.

Related Issues

flutter/flutter#31041

Tests

Because I am modifying the existing code, I need to add test cases to the existing unit tests of ios_external_texture_gl and ios_external_texture_metal, but I did not find these unit tests. Could anyone tell me where they are?

Checklist

Before you create this PR confirm that it meets all requirements listed below by checking the relevant checkboxes ([x]). This will ensure a smooth and quick review process.

  • I read the contributor guide and followed the process outlined there for submitting PRs.
  • I signed the CLA.
  • I read and followed the C++, Objective-C, Java style guides for the engine.
  • I read the tree hygiene wiki page, which explains my responsibilities.
  • I updated/added relevant documentation.
  • All existing and new tests are passing.
  • I am willing to follow-up on review comments in a timely manner.

Breaking Change

Did any tests fail when you ran them? Please read handling breaking changes.

@flutter-dashboard
Copy link

It looks like this pull request may not have tests. Please make sure to add tests before merging. If you need an exemption to this rule, contact Hixie on the #hackers channel in Chat.

Reviewers: Read the Tree Hygiene page and make sure this patch meets those guidelines before LGTMing.

@googlebot
Copy link

We found a Contributor License Agreement for you (the sender of this pull request), but were unable to find agreements for all the commit author(s) or Co-authors. If you authored these, maybe you used a different email address in the git commits than was used to sign the CLA (login here to double check)? If these were authored by someone else, then they will need to sign a CLA as well, and confirm that they're okay with these being contributed to Google.
In order to pass this check, please resolve this problem and then comment @googlebot I fixed it.. If the bot doesn't comment, it means it doesn't think anything has changed.

ℹ️ Googlers: Go here for more info.

1 similar comment
@googlebot
Copy link

We found a Contributor License Agreement for you (the sender of this pull request), but were unable to find agreements for all the commit author(s) or Co-authors. If you authored these, maybe you used a different email address in the git commits than was used to sign the CLA (login here to double check)? If these were authored by someone else, then they will need to sign a CLA as well, and confirm that they're okay with these being contributed to Google.
In order to pass this check, please resolve this problem and then comment @googlebot I fixed it.. If the bot doesn't comment, it means it doesn't think anything has changed.

ℹ️ Googlers: Go here for more info.

@auto-assign auto-assign bot requested a review from gaaclarke July 28, 2020 13:12
@cikelengfeng cikelengfeng force-pushed the ios_nv12_external_texture branch from c36edc5 to 917b4fa Compare July 28, 2020 13:18
@googlebot
Copy link

CLAs look good, thanks!

ℹ️ Googlers: Go here for more info.

1 similar comment
@googlebot
Copy link

CLAs look good, thanks!

ℹ️ Googlers: Go here for more info.

@googlebot
Copy link

We found a Contributor License Agreement for you (the sender of this pull request), but were unable to find agreements for all the commit author(s) or Co-authors. If you authored these, maybe you used a different email address in the git commits than was used to sign the CLA (login here to double check)? If these were authored by someone else, then they will need to sign a CLA as well, and confirm that they're okay with these being contributed to Google.
In order to pass this check, please resolve this problem and then comment @googlebot I fixed it.. If the bot doesn't comment, it means it doesn't think anything has changed.

ℹ️ Googlers: Go here for more info.

1 similar comment
@googlebot
Copy link

We found a Contributor License Agreement for you (the sender of this pull request), but were unable to find agreements for all the commit author(s) or Co-authors. If you authored these, maybe you used a different email address in the git commits than was used to sign the CLA (login here to double check)? If these were authored by someone else, then they will need to sign a CLA as well, and confirm that they're okay with these being contributed to Google.
In order to pass this check, please resolve this problem and then comment @googlebot I fixed it.. If the bot doesn't comment, it means it doesn't think anything has changed.

ℹ️ Googlers: Go here for more info.

@cikelengfeng cikelengfeng force-pushed the ios_nv12_external_texture branch from 5cf1479 to 774e383 Compare July 29, 2020 04:29
@googlebot
Copy link

CLAs look good, thanks!

ℹ️ Googlers: Go here for more info.

1 similar comment
@googlebot
Copy link

CLAs look good, thanks!

ℹ️ Googlers: Go here for more info.

@cikelengfeng cikelengfeng force-pushed the ios_nv12_external_texture branch from da0f59e to 3306b72 Compare July 29, 2020 08:51
@cikelengfeng
Copy link
Contributor Author

@gaaclarke Could you help me review this pr?

Copy link
Member

@gaaclarke gaaclarke left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks @cikelengfeng I'm not sure about automated testing for this @chinmaygarde may have some ideas. Do you have code that that exercises this that can be run manually?

The code is failing format checks, can you please address all of the CI issues as well.

SkISize size{yBackendTexture.width(), yBackendTexture.height()};
sk_sp<SkImage> image =
SkImage::MakeFromYUVATextures(context, kRec601_SkYUVColorSpace, nv12TextureHandles,
yuvaIndices, size, kTopLeft_GrSurfaceOrigin, nullptr);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit: nullptr argument would benefit from an argument name comment

Copy link
Contributor Author

@cikelengfeng cikelengfeng Jul 31, 2020

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is to keep the style consistent with the original code. Do I need to modify the original code according to your suggestions?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

done

return image;
}

bool IOSExternalTextureGL::IsTexturesAvailable() {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This should be a const method.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

done

fml::CFRef<CVOpenGLESTextureCacheRef> cache_ref_;
fml::CFRef<CVOpenGLESTextureRef> texture_ref_;
fml::CFRef<CVPixelBufferRef> buffer_ref_;
OSType pixelFormat = 0;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

These variables don't adhere to the google c++ style guide, use pixel_format_. Same goes for down below.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

done.

CVMetalTextureRef y_metal_texture_raw = NULL;
{
auto cv_return =
CVMetalTextureCacheCreateTextureFromImage(kCFAllocatorDefault, // allocator
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please use checked argument name comments (these are checked by the linter):

CVMetalTextureCacheCreateTextureFromImage(/*allocator=*/ kCFAllocatorDefault,

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is also to keep the style consistent with the original code. Do I need to modify the original code according to your suggestions?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

done

CVMetalTextureCacheCreateTextureFromImage(kCFAllocatorDefault, // allocator
texture_cache_, // texture cache
pixel_buffer, // source image
NULL, // texture attributes
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

s/NULL/nullptr

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Since NULL was used in the original code, in order to keep the style consistent, I also used NULL, do I need to change all to nullptr?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

done

SkYUVAIndex{1, SkColorChannel::kR}, // Read U data from the red channel of the second texture
SkYUVAIndex{1,
SkColorChannel::kG}, // Read V data from the green channel of the second texture
SkYUVAIndex{-1, SkColorChannel::kA}}; //-1 means to omit the alpha data of YUVA
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If we are omitting the alpha data, why is this method referring to yuva?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Because some YUV formats have alpha channels (such as AYUV), skia may need to be compatible with such formats. In addition, I refer to the implementation of SkImage::MakeFromNV12TexturesCopy.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

And NV12 has no alpha channel.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should we change the name of this method then? It's called WrapYUVAExternalPixelBuffer.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

good idea,it should be WrapNV12ExternalPixelBuffer

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

done

@cikelengfeng
Copy link
Contributor Author

cikelengfeng commented Jul 31, 2020

Thanks @cikelengfeng I'm not sure about automated testing for this @chinmaygarde may have some ideas. Do you have code that that exercises this that can be run manually?

The code is failing format checks, can you please address all of the CI issues as well.

This is the Flutter camera plugin. I modified the code to support the output of NV12 pixelbuffer. The engine compiled with this pr can run. You may view the memory usage through the instruments tool at runtime.
camera.zip
1920x1080 resolution BGRA32 memory information:
a27d441c-ec35-476a-b3ed-998ec79fae53
1920x1080 resolution NV12 memory information:
1351aa4b-eded-4e03-9efd-5fe71fc0a01a

And the failed checks only output Step('format and dart test') (retcode: 1). How should I solve this problem?

@cikelengfeng cikelengfeng force-pushed the ios_nv12_external_texture branch from 3306b72 to 6112658 Compare July 31, 2020 06:32
@gaaclarke
Copy link
Member

This sounds good to me. I just have a few style nits left. I imagine there is a performance gain too since the camera is probably using YUV natively. The GPU was probably performing a pixel conversion to get ABGR or whatever.

Can you post a PR to the camera plugin that takes advantage of this work and link it here? You will probably have to have it disabled for now until this change lands on stable. If we can't get tests for it, we should at least have that. Let's wait to see if chinmay has any better idea about automated testing.

@cikelengfeng
Copy link
Contributor Author

This sounds good to me. I just have a few style nits left. I imagine there is a performance gain too since the camera is probably using YUV natively. The GPU was probably performing a pixel conversion to get ABGR or whatever.

Can you post a PR to the camera plugin that takes advantage of this work and link it here? You will probably have to have it disabled for now until this change lands on stable. If we can't get tests for it, we should at least have that. Let's wait to see if chinmay has any better idea about automated testing.

Yes, but I don’t think we need to worry. GPU needs to use a shader to convert YUV to ABGR. This is what GPU is good at. It is very fast.
The PR of the camera is here.

Copy link
Member

@gaaclarke gaaclarke left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I manually tested the PR to make sure existing behavior doesn't break on iOS. I don't have a good idea how to automate tests for this but the OP was able to provide steps to manually test it with their PR to the camera plugin. LGTM.

@befovy
Copy link

befovy commented Oct 17, 2020

Hi, anyone can help me? How to dynamically check if engien support nv12 texture in a flutter video player plugin?

@cikelengfeng
Copy link
Contributor Author

Hi, anyone can help me? How to dynamically check if engien support nv12 texture in a flutter video player plugin?

It is not yet possible to dynamically check, can you talk about your usage scenario in detail?

@befovy
Copy link

befovy commented Oct 24, 2020

Hi, anyone can help me? How to dynamically check if engien support nv12 texture in a flutter video player plugin?

It is not yet possible to dynamically check, can you talk about your usage scenario in detail?

Hi, I developed a flutter video player https://github.com/befovy/fijkplayer. It use flutter engine texture to display video.
Currently, I return a bgra pixelbuffer in https://github.com/befovy/fijkplayer/blob/master/ios/Classes/FijkPlayer.m#L243.

I want to upgrade fijkplayer then return yuv pixelbuffer to flutter engine, but I also want fijkplayer works in old flutter version.

@cikelengfeng
Copy link
Contributor Author

Hi, anyone can help me? How to dynamically check if engien support nv12 texture in a flutter video player plugin?

It is not yet possible to dynamically check, can you talk about your usage scenario in detail?

Hi, I developed a flutter video player https://github.com/befovy/fijkplayer. It use flutter engine texture to display video.
Currently, I return a bgra pixelbuffer in https://github.com/befovy/fijkplayer/blob/master/ios/Classes/FijkPlayer.m#L243.

I want to upgrade fijkplayer then return yuv pixelbuffer to flutter engine, but I also want fijkplayer works in old flutter version.

I'm afraid we can't do it, because even if you add a query interface to the latest version, if the user uses a version that supports NV12 but does not have this interface (such as 1.22), your code will still produce incorrect behavior.
I suggest that you may create another version of your library and specify SDK constraints in the pubspec file of this version, such as:

environment:
  sdk: '>=2.1.0 <3.0.0'
  flutter: ^1.22.0

see: https://dart.dev/tools/pub/pubspec#sdk-constraints

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants