plugins icon indicating copy to clipboard operation
plugins copied to clipboard

[video_player_tizen] Videos are playing with software codec

Open huluwa-dev opened this issue 1 year ago • 37 comments

I tried to play an HLS video with video_player_tizen, but when the video quality automatically updated to 1080P, the playback started stuttering significantly. I assume the video was played using a software codec, as other video-playing apps work well (like YouTube), even with 4K videos.

Could you help me confirm whether this plugin uses a software decoder for video playback? Thanks.

This is the code snippet:


class VideoPlayerWidget extends ConsumerStatefulWidget {
  const VideoPlayerWidget({
    super.key,
  });

  @override
  ConsumerState createState() => _VideoPlayerWidgetState();
}

class _VideoPlayerWidgetState extends ConsumerState<VideoPlayerWidget> {
  late VideoPlayerController _controller;

  @override
  void initState() {
    super.initState();
    _controller = VideoPlayerController.networkUrl(
        Uri.parse('https://test-streams.mux.dev/x36xhzz/x36xhzz.m3u8'))
      ..initialize().then((_) {
        // Ensure the first frame is shown after the video is initialized, even before the play button has been pressed.
        setState(() {});
      });
  }

  bool get _videoReady => _controller.value.isInitialized == true;

  @override
  Widget build(BuildContext context) {
    return _buildVideoPlayer();
  }

  Widget _buildVideoPlayer() {
    return Container(
      width: double.infinity,
      height: double.infinity,
      color: context.theme.black,
      child: _videoReady
          ? VideoPlayer(_controller)
          : Center(
              child: CircularProgressIndicator(
                color: Colors.white,
              ),
            ),
    );
  }

  @override
  void dispose() {
    _controller.dispose();
    super.dispose();
  }
}

huluwa-dev avatar Oct 24 '24 03:10 huluwa-dev

Hi, thank you for your interest.

video_player_tizen is implemented using player.h provided by TizenSDK. (https://docs.tizen.org/application/native/api/iot-headed/6.0/group__CAPI__MEDIA__PLAYER__MODULE.html) Basic Media spcification can be found at the link below. https://developer.samsung.com/smarttv/develop/specifications/media-specifications.html https://developer.samsung.com/smarttv/develop/specifications/tv-model-groups.html

(This may vary depending on the device's model, specifications, and Tizen version.) Tizen 8.0 provides an API that can find out the codec type (HW, SW, DEFAULT) of the video in the Player module. When I checked on my test device, the DEFAULT value was returned, and this can be SW or HW depending on the system priority. And I checked in the logs of my test tv device that the SW codec is being used. (Tizen 8.0) Maybe, if nothing else is set, it will work as a SW decoder.

If you have a Tizen 8.0 development environment set up, you can test the test code below. https://github.com/JSUYA/plugins/commit/efe4140de95ba2f7d24920b74b2d0a4415d11165

JSUYA avatar Oct 24 '24 06:10 JSUYA

Hi @JSUYA , thanks for your quick reply.

Did you mean that you have ran the code I provided and confirmed that the Tizen OS decoded the video(https://test-streams.mux.dev/x36xhzz/x36xhzz.m3u8) with a SW codec?

If that is the case, could you help me to get an video example(url) which can be played with a HW codec? Thanks.

huluwa-dev avatar Oct 24 '24 07:10 huluwa-dev

Hi @JSUYA , thanks for your quick reply.

Did you mean that you have ran the code I provided and confirmed that the Tizen OS decoded the video(https://test-streams.mux.dev/x36xhzz/x36xhzz.m3u8) with a SW codec?

If that is the case, could you help me to get an video example(url) which can be played with a HW codec? Thanks.

@huluwa-dev Hello, do you play video on TV device?

xiaowei-guan avatar Oct 24 '24 07:10 xiaowei-guan

Hi @JSUYA , thanks for your quick reply.

Did you mean that you have ran the code I provided and confirmed that the Tizen OS decoded the video(https://test-streams.mux.dev/x36xhzz/x36xhzz.m3u8) with a SW codec?

yes I played https://test-streams.mux.dev/x36xhzz/x36xhzz.m3u8 Your code looks like it uses flutter riverpod. (because of ConsumerStatefulWidget). this will not affect the decoder. I tested it in the example of video_player and only changed the url. (https://github.com/JSUYA/plugins/commit/efe4140de95ba2f7d24920b74b2d0a4415d11165)

If that is the case, could you help me to get an video example(url) which can be played with a HW codec? Thanks.

Unfortunately I don't know much about content that forces the use of HW codec.

JSUYA avatar Oct 24 '24 09:10 JSUYA

Hi @xiaowei-guan Yes, I played the video on a Samsung TV with Tizen 6.0. Tomorrow I will post the TV's model information.

huluwa-dev avatar Oct 24 '24 10:10 huluwa-dev

Hi @JSUYA , thanks for your quick reply. Did you mean that you have ran the code I provided and confirmed that the Tizen OS decoded the video(https://test-streams.mux.dev/x36xhzz/x36xhzz.m3u8) with a SW codec?

yes I played https://test-streams.mux.dev/x36xhzz/x36xhzz.m3u8 Your code looks like it uses flutter riverpod. (because of ConsumerStatefulWidget). this will not affect the decoder. I tested it in the example of video_player and only changed the url. (JSUYA@efe4140)

If that is the case, could you help me to get an video example(url) which can be played with a HW codec? Thanks.

Unfortunately I don't know much about content that forces the use of HW codec.

Thanks for the confirmation.

As you are one of the contributors, do you know anybody who can help to make this plugin work with HW codec. SW codec is inefficient and produces poor user experience. I believe it could improve the performance a lot by utilizing a HW codec.

Thank you for your time.

huluwa-dev avatar Oct 24 '24 10:10 huluwa-dev

I downloaded the video with yt-dlp

yt-dlp https://test-streams.mux.dev/x36xhzz/x36xhzz.m3u8

and checked the video's information with FFmpeg.

ffmpeg -i x36xhzz\ \[x36xhzz\].mp4
ffmpeg version 7.0.2 Copyright (c) 2000-2024 the FFmpeg developers
  built with Apple clang version 16.0.0 (clang-1600.0.26.3)
  configuration: --prefix=/opt/homebrew/Cellar/ffmpeg/7.0.2_1 --enable-shared --enable-pthreads --enable-version3 --cc=clang --host-cflags= --host-ldflags='-Wl,-ld_classic' --enable-ffplay --enable-gnutls --enable-gpl --enable-libaom --enable-libaribb24 --enable-libbluray --enable-libdav1d --enable-libharfbuzz --enable-libjxl --enable-libmp3lame --enable-libopus --enable-librav1e --enable-librist --enable-librubberband --enable-libsnappy --enable-libsrt --enable-libssh --enable-libsvtav1 --enable-libtesseract --enable-libtheora --enable-libvidstab --enable-libvmaf --enable-libvorbis --enable-libvpx --enable-libwebp --enable-libx264 --enable-libx265 --enable-libxml2 --enable-libxvid --enable-lzma --enable-libfontconfig --enable-libfreetype --enable-frei0r --enable-libass --enable-libopencore-amrnb --enable-libopencore-amrwb --enable-libopenjpeg --enable-libspeex --enable-libsoxr --enable-libzmq --enable-libzimg --disable-libjack --disable-indev=jack --enable-videotoolbox --enable-audiotoolbox --enable-neon
  libavutil      59.  8.100 / 59.  8.100
  libavcodec     61.  3.100 / 61.  3.100
  libavformat    61.  1.100 / 61.  1.100
  libavdevice    61.  1.100 / 61.  1.100
  libavfilter    10.  1.100 / 10.  1.100
  libswscale      8.  1.100 /  8.  1.100
  libswresample   5.  1.100 /  5.  1.100
  libpostproc    58.  1.100 / 58.  1.100
Input #0, mov,mp4,m4a,3gp,3g2,mj2, from 'x36xhzz [x36xhzz].mp4':
  Metadata:
    major_brand     : isom
    minor_version   : 512
    compatible_brands: isomiso2avc1mp41
    encoder         : Lavf61.1.100
  Duration: 00:10:34.59, start: 0.000000, bitrate: 6154 kb/s
  Stream #0:0[0x1](und): Audio: aac (LC) (mp4a / 0x6134706D), 44100 Hz, stereo, fltp, 151 kb/s (default)
      Metadata:
        handler_name    : SoundHandler
        vendor_id       : [0][0][0][0]
  Stream #0:1[0x2](und): Video: h264 (High) (avc1 / 0x31637661), yuv420p(progressive), 1920x1080 [SAR 1:1 DAR 16:9], 5985 kb/s, 60 fps, 60 tbr, 90k tbn (default)
      Metadata:
        handler_name    : VideoHandler
        vendor_id       : [0][0][0][0]

It is an H.264 video, it should be played with HW codec on most devices. But unfortunately, video_player_tizen plays it with SW codec.

It would be great if the tizen team could solve this problem.

huluwa-dev avatar Oct 24 '24 10:10 huluwa-dev

Hi @JSUYA , thanks for your quick reply. Did you mean that you have ran the code I provided and confirmed that the Tizen OS decoded the video(https://test-streams.mux.dev/x36xhzz/x36xhzz.m3u8) with a SW codec?

yes I played https://test-streams.mux.dev/x36xhzz/x36xhzz.m3u8 Your code looks like it uses flutter riverpod. (because of ConsumerStatefulWidget). this will not affect the decoder. I tested it in the example of video_player and only changed the url. (JSUYA@efe4140)

If that is the case, could you help me to get an video example(url) which can be played with a HW codec? Thanks.

Unfortunately I don't know much about content that forces the use of HW codec.

Thanks for the confirmation.

As you are one of the contributors, do you know anybody who can help to make this plugin work with HW codec. SW codec is inefficient and produces poor user experience. I believe it could improve the performance a lot by utilizing a HW codec.

Thank you for your time.

If you want to have a better performance, we suggest you use video_player_videohole. If you are a partner of Samsung, we suggest you use video_player_avplay.

xiaowei-guan avatar Oct 24 '24 11:10 xiaowei-guan

@huluwa-dev The video_player_videohole and video_player_avplay only support TV device.

xiaowei-guan avatar Oct 24 '24 11:10 xiaowei-guan

@huluwa-dev The video_player_videohole and video_player_avplay only support TV device.

Hi, thanks for the suggestion, I tried video_player_videohole, but some error occured, I think that's because the video I tried is not with DRM, I will post the detail of the errors tomorrow.

huluwa-dev avatar Oct 24 '24 12:10 huluwa-dev

Hi @xiaowei-guan is video_player_videohole suitable for playing a content without DRM?

EricLinPixelforce avatar Oct 25 '24 01:10 EricLinPixelforce

@huluwa-dev The video_player_videohole and video_player_avplay only support TV device.

Hi, thanks for the suggestion, I tried video_player_videohole, but some error occured, I think that's because the video I tried is not with DRM, I will post the detail of the errors tomorrow.

I can play the URL with video_player_videohole and video_player. video_player_videohole plugin has a goode performance, because video_player_videohole render the video on video plane layer, not on graphic layer.

if your app just for Tizen TV device, we suggest you use video_player_videohole plugin

xiaowei-guan avatar Oct 25 '24 03:10 xiaowei-guan

Hi @xiaowei-guan is video_player_videohole suitable for playing a content without DRM?

@EricLinPixelforce Hi, if your app just run on Tizen TV device, we suggest you use video_player_videohole plugin, video_player_videohole also supports play DRM content, you need to be a partner of samsung.

xiaowei-guan avatar Oct 25 '24 03:10 xiaowei-guan

As you are one of the contributors, do you know anybody who can help to make this plugin work with HW codec. SW codec is inefficient and produces poor user experience. I believe it could improve the performance a lot by utilizing a HW codec.

Thank you for your time.

@huluwa-dev If you're just testing purposes, you can temporarily use the internal API(Does not guarantee operation) and I've created a commit to test it. (There is absolutely no guarantee that this commit will be merged into master.) https://github.com/JSUYA/plugins/commit/c8f94dba3bc02ac511027634a1c8cd7f591f5461 With this patch, try using VideoPlayerTizen.forceUseHwDecoder = true; before calling Initialize of VideoController.

As I said before...Tizen 8.0 provides an API that can set the decoder. So if you are in an environment with Tizen 8.0, this operation maybe guaranteed, but in other environments (6.0, 6.5, 7.0), the operation may not be guaranteed. Also, when using the HW decoder, there was a abnormal behavior(?) in which certain contents on my device were initially displayed in a small screen size and then restored.

As far as I know, TV devices basically use HW decoder if HW decoder is available. The basic settings are not fixed to HW or SW. So, it is due to internal logic that your device uses SW decoder for playback. (There may be various reasons, such as device performance. If there is a difference with other apps, there may be a difference in the video player.) Therefore, if you want better performance or environment, you can use video_player_avplay or video_player_videohole.

JSUYA avatar Oct 25 '24 06:10 JSUYA

Hi @xiaowei-guan is video_player_videohole suitable for playing a content without DRM?

@EricLinPixelforce Hi, if your app just run on Tizen TV device, we suggest you use video_player_videohole plugin, video_player_videohole also supports play DRM content, you need to be a partner of samsung.

Hi, thanks for the great news. Can video_player_videohole also play non-DRM contents?

I already regisered a Samsung seller account and will distribute a TV app to the Tizen store within a month.

huluwa-dev avatar Oct 25 '24 12:10 huluwa-dev

@huluwa-dev The video_player_videohole and video_player_avplay only support TV device.

Hi, thanks for the suggestion, I tried video_player_videohole, but some error occured, I think that's because the video I tried is not with DRM, I will post the detail of the errors tomorrow.

I can play the URL with video_player_videohole and video_player. video_player_videohole plugin has a goode performance, because video_player_videohole render the video on video plane layer, not on graphic layer.

if your app just for Tizen TV device, we suggest you use video_player_videohole plugin

Hi, I tried to play the URL with video_player_videohole, but the player keeps producing an error

 [ERROR:flutter/runtime/dart_vm_initializer.cc(41)] Unhandled Exception: PlatformException(Pause, Player pause failed, null, null)
#0      VideoPlayerVideoholeApi.pause (package:video_player_videohole/src/messages.g.dart:790:7)
<asynchronous suspension>
#1      VideoPlayerController._applyPlayPause (package:video_player_videohole/video_player.dart:610:7)
<asynchronous suspension>

My code:


class VideoholdPlayerWidget extends StatefulWidget {

  const VideoholdPlayerWidget({
    super.key,
  });

  @override
  State<VideoholdPlayerWidget> createState() => _VideoholdPlayerWidgetState();
}

class _VideoholdPlayerWidgetState extends State<VideoholdPlayerWidget> {
  late VideoPlayerController _controller;

  @override
  void initState() {
    super.initState();
    _initPlayer();
  }

  void _initPlayer() {
    _controller = VideoPlayerController.network(
      // widget.videoUrl,
      "https://test-streams.mux.dev/x36xhzz/x36xhzz.m3u8",
    );
    _controller.addListener(() => setState(() {}));
    _controller.initialize().then((_) => setState(() {}));
  }

  @override
  Widget build(BuildContext context) {
    return Center(
      child: AspectRatio(
        aspectRatio: _controller.value.aspectRatio,
        child: Stack(
          alignment: Alignment.bottomCenter,
          children: <Widget>[
            VideoPlayer(_controller),
            ClosedCaption(text: _controller.value.caption.text),
            GestureDetector(
              onTap: () {
                _controller.value.isPlaying
                    ? _controller.pause()
                    : _controller.play();
              },
            ),
            VideoProgressIndicator(_controller, allowScrubbing: true),
          ],
        ),
      ),
    );
  }

  @override
  void dispose() {
    _controller.dispose();
    super.dispose();
  }
}

I would appreciate it if you could give me any suggestions. Thanks.

EricLinPixelforce avatar Oct 29 '24 04:10 EricLinPixelforce

@xiaowei-guan I also tried to play it with video_player_avplayer. I got this error:

[E] 
(process:1400): GLib-CRITICAL **: 15:22:16.399: g_path_get_basename: assertion 'file_name != NULL' failed
[E] 
(<unknown>:1400): GStreamer-WARNING **: 15:22:16.621: Failed to load plugin '/opt/usr/apps/com.traininpink.tv/lib/libgsthls.so': libclearkey.so.0: cannot open shared object file: Operation not permitted
[I] size of instance = 1240
size of class = 1428
[I] size of basesrc = 448
size of basesrcclass = 404
[E] 
(<unknown>:1400): GStreamer-WARNING **: 15:22:17.423: Failed to load plugin '/usr/lib/gstreamer-1.0/libgsthls.so': libclearkey.so.0: cannot open shared object file: Operation not permitted

My code:

class AVPlayerWidget extends StatefulWidget {

  const AVPlayerWidget({
    super.key,
  });

  @override
  State<AVPlayerWidget> createState() => _AVPlayerWidgetState();
}

class _AVPlayerWidgetState extends State<AVPlayerWidget> {
  late VideoPlayerController _controller;

  @override
  void initState() {
    super.initState();
    _initPlayer();
  }

  void _initPlayer() {
    _controller = VideoPlayerController.network(
      "https://test-streams.mux.dev/x36xhzz/x36xhzz.m3u8",
    );
    _controller.addListener(() => setState(() {}));
    _controller.initialize().then((_) => setState(() {}));
  }

  @override
  Widget build(BuildContext context) {
    return Center(
      child: AspectRatio(
        aspectRatio: _controller.value.aspectRatio,
        child: Stack(
          alignment: Alignment.bottomCenter,
          children: <Widget>[
            VideoPlayer(_controller),
            ClosedCaption(text: _controller.value.caption.text),
            GestureDetector(
              onTap: () {
                _controller.value.isPlaying
                    ? _controller.pause()
                    : _controller.play();
              },
            ),
            VideoProgressIndicator(_controller, allowScrubbing: true),
          ],
        ),
      ),
    );
  }

  @override
  void dispose() {
    _controller.dispose();
    super.dispose();
  }
}

EricLinPixelforce avatar Oct 29 '24 04:10 EricLinPixelforce

@JSUYA @xiaowei-guan The TV is a Samsung TV, model code: UA75BU8000WXXY (the model name should be 75" BU8000), with Tizen 6.5 running on it.

EricLinPixelforce avatar Oct 29 '24 05:10 EricLinPixelforce

As you are one of the contributors, do you know anybody who can help to make this plugin work with HW codec. SW codec is inefficient and produces poor user experience. I believe it could improve the performance a lot by utilizing a HW codec. Thank you for your time.

@huluwa-dev If you're just testing purposes, you can temporarily use the internal API(Does not guarantee operation) and I've created a commit to test it. (There is absolutely no guarantee that this commit will be merged into master.) JSUYA@c8f94db With this patch, try using VideoPlayerTizen.forceUseHwDecoder = true; before calling Initialize of VideoController.

As I said before...Tizen 8.0 provides an API that can set the decoder. So if you are in an environment with Tizen 8.0, this operation maybe guaranteed, but in other environments (6.0, 6.5, 7.0), the operation may not be guaranteed. Also, when using the HW decoder, there was a abnormal behavior(?) in which certain contents on my device were initially displayed in a small screen size and then restored.

As far as I know, TV devices basically use HW decoder if HW decoder is available. The basic settings are not fixed to HW or SW. So, it is due to internal logic that your device uses SW decoder for playback. (There may be various reasons, such as device performance. If there is a difference with other apps, there may be a difference in the video player.) Therefore, if you want better performance or environment, you can use video_player_avplay or video_player_videohole.

Thanks for the solution, I tried it on the TV, but still, it utilized HW codec to decode the video, because it was lagging.

EricLinPixelforce avatar Oct 29 '24 05:10 EricLinPixelforce

@huluwa-dev The video_player_videohole and video_player_avplay only support TV device.

Hi, thanks for the suggestion, I tried video_player_videohole, but some error occured, I think that's because the video I tried is not with DRM, I will post the detail of the errors tomorrow.

I can play the URL with video_player_videohole and video_player. video_player_videohole plugin has a goode performance, because video_player_videohole render the video on video plane layer, not on graphic layer. if your app just for Tizen TV device, we suggest you use video_player_videohole plugin

Hi, I tried to play the URL with video_player_videohole, but the player keeps producing an error

 [ERROR:flutter/runtime/dart_vm_initializer.cc(41)] Unhandled Exception: PlatformException(Pause, Player pause failed, null, null)
#0      VideoPlayerVideoholeApi.pause (package:video_player_videohole/src/messages.g.dart:790:7)
<asynchronous suspension>
#1      VideoPlayerController._applyPlayPause (package:video_player_videohole/video_player.dart:610:7)
<asynchronous suspension>

My code:


class VideoholdPlayerWidget extends StatefulWidget {

  const VideoholdPlayerWidget({
    super.key,
  });

  @override
  State<VideoholdPlayerWidget> createState() => _VideoholdPlayerWidgetState();
}

class _VideoholdPlayerWidgetState extends State<VideoholdPlayerWidget> {
  late VideoPlayerController _controller;

  @override
  void initState() {
    super.initState();
    _initPlayer();
  }

  void _initPlayer() {
    _controller = VideoPlayerController.network(
      // widget.videoUrl,
      "https://test-streams.mux.dev/x36xhzz/x36xhzz.m3u8",
    );
    _controller.addListener(() => setState(() {}));
    _controller.initialize().then((_) => setState(() {}));
  }

  @override
  Widget build(BuildContext context) {
    return Center(
      child: AspectRatio(
        aspectRatio: _controller.value.aspectRatio,
        child: Stack(
          alignment: Alignment.bottomCenter,
          children: <Widget>[
            VideoPlayer(_controller),
            ClosedCaption(text: _controller.value.caption.text),
            GestureDetector(
              onTap: () {
                _controller.value.isPlaying
                    ? _controller.pause()
                    : _controller.play();
              },
            ),
            VideoProgressIndicator(_controller, allowScrubbing: true),
          ],
        ),
      ),
    );
  }

  @override
  void dispose() {
    _controller.dispose();
    super.dispose();
  }
}

I would appreciate it if you could give me any suggestions. Thanks.

Hello, @EricLinPixelforce I can play the URL(https://test-streams.mux.dev/x36xhzz/x36xhzz.m3u8) by videohole sample code. code sample as follows:

class _HlsRomoteVideo extends StatefulWidget {
  @override
  State<_HlsRomoteVideo> createState() => _HlsRomoteVideoState();
}

class _HlsRomoteVideoState extends State<_HlsRomoteVideo> {
  late VideoPlayerController _controller;

  @override
  void initState() {
    super.initState();
    _controller = VideoPlayerController.network(
        'https://test-streams.mux.dev/x36xhzz/x36xhzz.m3u8');

    _controller.addListener(() {
      if (_controller.value.hasError) {
        print(_controller.value.errorDescription);
      }
      setState(() {});
    });
    _controller.setLooping(true);
    _controller.initialize().then((_) => setState(() {}));
    _controller.play();
  }

plugin logs

I/VideoPlayerVideoHolePlugin(16752): media_player.cc: GetDuration(316) > [MediaPlayer] Video duration: 33002.
I/VideoPlayerVideoHolePlugin(16752): media_player.cc: Create(67) > [MediaPlayer] uri: https://test-streams.mux.dev/x36xhzz/x36xhzz.m3u8, drm_type: 0.
I/VideoPlayerVideoHolePlugin(16752): media_player.cc: OnBuffering(648) > [MediaPlayer] Buffering percent: 0.
I/VideoPlayerVideoHolePlugin(16752): media_player.cc: OnBuffering(648) > [MediaPlayer] Buffering percent: 1.
I/VideoPlayerVideoHolePlugin(16752): media_player.cc: OnBuffering(648) > [MediaPlayer] Buffering percent: 2.
I/VideoPlayerVideoHolePlugin(16752): media_player.cc: OnBuffering(648) > [MediaPlayer] Buffering percent: 3.
I/VideoPlayerVideoHolePlugin(16752): media_player.cc: OnBuffering(648) > [MediaPlayer] Buffering percent: 4.
I/VideoPlayerVideoHolePlugin(16752): media_player.cc: OnBuffering(648) > [MediaPlayer] Buffering percent: 5.
I/VideoPlayerVideoHolePlugin(16752): media_player.cc: OnBuffering(648) > [MediaPlayer] Buffering percent: 6.
I/VideoPlayerVideoHolePlugin(16752): media_player.cc: OnBuffering(648) > [MediaPlayer] Buffering percent: 7.
I/VideoPlayerVideoHolePlugin(16752): media_player.cc: OnBuffering(648) > [MediaPlayer] Buffering percent: 8.

xiaowei-guan avatar Oct 29 '24 05:10 xiaowei-guan

@xiaowei-guan I also tried to play it with video_player_avplayer. I got this error:

[E] 
(process:1400): GLib-CRITICAL **: 15:22:16.399: g_path_get_basename: assertion 'file_name != NULL' failed
[E] 
(<unknown>:1400): GStreamer-WARNING **: 15:22:16.621: Failed to load plugin '/opt/usr/apps/com.traininpink.tv/lib/libgsthls.so': libclearkey.so.0: cannot open shared object file: Operation not permitted
[I] size of instance = 1240
size of class = 1428
[I] size of basesrc = 448
size of basesrcclass = 404
[E] 
(<unknown>:1400): GStreamer-WARNING **: 15:22:17.423: Failed to load plugin '/usr/lib/gstreamer-1.0/libgsthls.so': libclearkey.so.0: cannot open shared object file: Operation not permitted

My code:

class AVPlayerWidget extends StatefulWidget {

  const AVPlayerWidget({
    super.key,
  });

  @override
  State<AVPlayerWidget> createState() => _AVPlayerWidgetState();
}

class _AVPlayerWidgetState extends State<AVPlayerWidget> {
  late VideoPlayerController _controller;

  @override
  void initState() {
    super.initState();
    _initPlayer();
  }

  void _initPlayer() {
    _controller = VideoPlayerController.network(
      "https://test-streams.mux.dev/x36xhzz/x36xhzz.m3u8",
    );
    _controller.addListener(() => setState(() {}));
    _controller.initialize().then((_) => setState(() {}));
  }

  @override
  Widget build(BuildContext context) {
    return Center(
      child: AspectRatio(
        aspectRatio: _controller.value.aspectRatio,
        child: Stack(
          alignment: Alignment.bottomCenter,
          children: <Widget>[
            VideoPlayer(_controller),
            ClosedCaption(text: _controller.value.caption.text),
            GestureDetector(
              onTap: () {
                _controller.value.isPlaying
                    ? _controller.pause()
                    : _controller.play();
              },
            ),
            VideoProgressIndicator(_controller, allowScrubbing: true),
          ],
        ),
      ),
    );
  }

  @override
  void dispose() {
    _controller.dispose();
    super.dispose();
  }
}

If you want to use avplay plugin, you need to be a partner of samsung.

xiaowei-guan avatar Oct 29 '24 05:10 xiaowei-guan

@xiaowei-guan Thanks for the reply. Now I can play it with your code sample in a created new project. But still got error in my existing project. That's weird. I will check the difference and find the reason.

EricLinPixelforce avatar Oct 29 '24 06:10 EricLinPixelforce

@xiaowei-guan I found the reason, if I call play after the video is initialized, the error will occur

 _controller.initialize().then((_) {
      setState(() {});
      _controller.play();
    });

But if I play it without waiting for the initilization, it works well.

 _controller.initialize().then((_) {
      setState(() {});
    });
    _controller.play();

EricLinPixelforce avatar Oct 29 '24 06:10 EricLinPixelforce

Hi @xiaowei-guan Currently I am playing videos with video_player_videohole, I tried to detect if the video playing is finished with the following code

 _videoPlayerController.addListener(() {
      print(
          "_videoPlayerController.value.position = ${_videoPlayerController.value.position.inSeconds}, _videoPlayerController.value.duration.start = ${_videoPlayerController.value.duration.start.inSeconds}, _videoPlayerController.value.duration.end = ${_videoPlayerController.value.duration.end.inSeconds}");
      if (_videoPlayerController.value.position >=
              _videoPlayerController.value.duration.end &&
          _videoPlayerController.value.position.inMilliseconds != 0) {
        widget.onFinished?.call();
      }
    });

Finally I got this log and never detected it.

[I] flutter: _videoPlayerController.value.position = 23, _videoPlayerController.value.duration.start = 0, _videoPlayerController.value.duration.end = 26
[I] flutter: _videoPlayerController.value.position = 23, _videoPlayerController.value.duration.start = 0, _videoPlayerController.value.duration.end = 26
[I] flutter: _videoPlayerController.value.position = 23, _videoPlayerController.value.duration.start = 0, _videoPlayerController.value.duration.end = 26
[I] flutter: _videoPlayerController.value.position = 24, _videoPlayerController.value.duration.start = 0, _videoPlayerController.value.duration.end = 26
[I] flutter: _videoPlayerController.value.position = 24, _videoPlayerController.value.duration.start = 0, _videoPlayerController.value.duration.end = 26
[I] flutter: _videoPlayerController.value.position = 24, _videoPlayerController.value.duration.start = 0, _videoPlayerController.value.duration.end = 26
[I] flutter: _videoPlayerController.value.position = 24, _videoPlayerController.value.duration.start = 0, _videoPlayerController.value.duration.end = 26
[E] [ERROR:flutter/runtime/dart_vm_initializer.cc(41)] Unhandled Exception: PlatformException(Pause, Player pause failed, null, null)
#0      VideoPlayerVideoholeApi.pause (package:video_player_videohole/src/messages.g.dart:790:7)
<asynchronous suspension>
#1      VideoPlayerController._applyPlayPause (package:video_player_videohole/video_player.dart:610:7)
<asynchronous suspension>
#2      VideoPlayerController.pause (package:video_player_videohole/video_player.dart:533:5)
<asynchronous suspension>
#3      VideoPlayerController.initialize.eventListener.<anonymous closure> (package:video_player_videohole/video_player.dart:426:24)
<asynchronous suspension>

_videoPlayerController.value.position never reached the end.

Could you help me to resolve it? Thanks.

EricLinPixelforce avatar Nov 05 '24 07:11 EricLinPixelforce

Hello, @EricLinPixelforce , I have checked the position value, the value of position really cannot reach the end. Do you need a completed event from the player?

xiaowei-guan avatar Nov 05 '24 08:11 xiaowei-guan

Hello, @EricLinPixelforce , I have checked the position value, the value of position really cannot reach the end. Do you need a completed event from the player?

Yes, that's exactly what I want! I would be grateful if you could expose the event.

EricLinPixelforce avatar Nov 05 '24 08:11 EricLinPixelforce

Hello, @EricLinPixelforce , I have checked the position value, the value of position really cannot reach the end. Do you need a completed event from the player?

Yes, that's exactly what I want! I would be grateful if you could expose the event.

Ok, I will add it.

xiaowei-guan avatar Nov 05 '24 09:11 xiaowei-guan

@EricLinPixelforce Please verify this new PR #766

xiaowei-guan avatar Nov 05 '24 11:11 xiaowei-guan

@EricLinPixelforce Please verify this new PR #766

Looks good, thanks. Have you tested it?

EricLinPixelforce avatar Nov 06 '24 02:11 EricLinPixelforce

@EricLinPixelforce Please verify this new PR #766

Looks good, thanks. Have you tested it?

Yes, I have tested it at my side. you can verify this PR at your side.

xiaowei-guan avatar Nov 06 '24 03:11 xiaowei-guan