videojs / video.js

Video.js - open source HTML5 video player
https://videojs.com
Other
37.51k stars 7.4k forks source link

VHS(m3u8) with HEVC(H.265) support for chrome and edge #8035

Open strbass28 opened 1 year ago

strbass28 commented 1 year ago

Description

video-js 7.20.3 does not work HEVC encoded files transported over VHS even though browser supports HEVC. It does work in Safari on OSX and IOS. Browsers such as chrome with HEVC support can play back the same HEVC files when encapsulated as MP4 files. Is there a plan to add non native HEVC+VHS support?

Maybe i'm missing something and it should work? I'm using ffmpeg to create the m3u8 files and HLS segment lists. I've tried the overrideNative methods on chrome and edge and it had no effect.

I can provide m3u8 playlists or make them accessible online if that helps.

Thanks for all the great work.

Reduced test case

No response

Steps to reproduce

  1. convert a h.265 mp4 file that plays in chrome and video-js and convert it to a m3u8 file. ffmpeg command is something like, ffmpeg -i hevcfile.mp4 -vcodec copy -f hls -hls_segment_type fmp4 -hls_time 1 -hls_list_size 1024 -hls_playlist_type event -hls_flags temp_file+independent_segments+discont_start -hls_allow_cache 0 oudir/index.m3u8
  2. point the video-js demo.html page at the index.m3u8 and change the mime type.
  3. plays in safari.
  4. does not play in edge and chrome. get the dreaded 'corrupt or incompatible file' message.

Errors

No response

What version of Video.js are you using?

video-js 7.20.3

Video.js plugins used.

No response

What browser(s) including version(s) does this occur with?

107.0.5304.110 (Official Build) (arm64)

What OS(es) and version(s) does this occur with?

windows 11, OSX 13.0.1

welcome[bot] commented 1 year ago

👋 Thanks for opening your first issue here! 👋

If you're reporting a 🐞 bug, please make sure you include steps to reproduce it. We get a lot of issues on this repo, so please be patient and we will get back to you as soon as we can. To help make it easier for us to investigate your issue, please follow the contributing guidelines.

gkatsev commented 1 year ago

I've been able to play HEVC in chrome with VHS. For example, https://videojs-http-streaming.netlify.app/?debug=false&autoplay=false&muted=false&fluid=false&minified=false&sync-workers=false&liveui=true&llhls=true&url=https%3A%2F%2Fdemo.unified-streaming.com%2Fk8s%2Ffeatures%2Fstable%2Fvideo%2Ftears-of-steel%2Ftears-of-steel-hevc.ism%2F.m3u8&type=application%2Fx-mpegURL&keysystems=&buffer-water=false&exact-manifest-timings=false&pixel-diff-selector=false&network-info=false&dts-offset=false&override-native=true&preload=auto&mirror-source=true

Do you have a test stream you can share? It's worth noting that Chrome's support heavily depends on hardware support.

video-archivist-bot commented 1 year ago

Hey! We've detected some video files in a comment on this issue. If you'd like to permanently archive these videos and tie them to this project, a maintainer of the project can reply to this issue with the following commands:

strbass28 commented 1 year ago

interesting... your video plays for me in chrome as well.

Here is a link to my HEVC video that does not play in chrome but does play in safari.

[http://3.86.76.131/video-js/demo.html]

Thanks again for the support

gkatsev commented 1 year ago

Looks like one of your issues is that it's a media playlist. With media-playlists only, it gets a lot more complicated. If you create a main manifest that links to this one, it can include codecs for us to use.

For example, it'll be something like:

#EXT-X-STREAM-INF:BANDWIDTH=1024000,CODECS="mp4a.40.2,hvc1.1.6.L150.90",RESOLUTION=1680x750,FRAME-RATE=24,VIDEO-RANGE=SDR,AUDIO="audio-aacl-64",CLOSED-CAPTIONS=NONE
tears-of-steel-hevc-video_eng=902000.m3u8
strbass28 commented 1 year ago

So you think this requires a master/manifest playlist to work? It's not clear to me how ffmpeg can generate that info from a stream. I've tried the master playlist option and it generates a manifest file with just the following and without a #EXT-X-STREAM-INF. It just contains the following.

EXTM3U

EXT-X-VERSION:7

FFMPEG has the SDP and knows this info so I would would think it should be able to.

If you're saying HEVC requires a manifest playlist for HLS to work then maybe this becomes more of a ffmpeg question?

Thanks again for the support.

gkatsev commented 1 year ago

You can always create a main manifest manually for your playlist. I'd expected ffmpeg to be able to generate it, but I'm not sure. Theoretically, it should be possible to play with just a media playlist, but with MSE-based playback it's complicated, so, knowing the codecs ahead of time makes it infinitely easier to deal with. I tried a few other MSE-based players, and they also have issues dealing with media playlist.

ghost commented 1 year ago

@strbass28 I have HEVC, AVC1 and AV1 in use all referenced in a single playlist, If I drop everything out except of the Audio and HEVC stuff it plays for me under Safari and edge, just under chrome I have issues ...

strbass28 commented 1 year ago

I've tested using 3 different camera manufacturers. I receive a h.265 encoded rtp stream from a RTSP feed. Using FFMPEG to generate a manifest and m3u8 playlist. Video-js can play them back in safari. VLC can also play them back without complaint. Using video-js in Edge and Chrome these H.265 streams to not play back.

Using edge or chrome, video-js given a single playlist will result in the 'corrupted stream or incompatible codec' message. If I pass in a master/manifest playlist I get 'no available or supported playlists'.

If I convert the incoming rtsp stream to a mp4 file without changing the codec then safari,edge,chrome can playback the hevc file.

The manifest file generated by ffmpeg looks like this.

EXTM3U

EXT-X-VERSION:7

EXT-X-STREAM-INF:BANDWIDTH=5500000,RESOLUTION=3072x1728

index.m3u8

For some reason,ffmpeg is not putting the codec info the file. Looking at the FFMPEG source from here( https://github.com/FFmpeg/FFmpeg/blob/master/libavformat/hlsplaylist.c) it looks like you need to specify a bandwidth for it to write anything so I got past that. I will try to get codec info into the manifest and see if that helps HEVC playback.

Seams like it would be good for video-js to natively support a single HEVC playlist in chrome and edge since a single playlist of other codecs works there. Any advice is appreciated.

strbass28 commented 1 year ago

using the ffmpeg parameter of, -tag:v hvc1 I get a manifest that looks like the below, but it didn't change anything. Chrome still reports 'no available or supported playlist'.

EXTM3U

EXT-X-VERSION:7

EXT-X-STREAM-INF:BANDWIDTH=5500000,RESOLUTION=3072x1728,CODECS="hvc1.1.4.L150.B01"

index.m3u8

ghost commented 1 year ago

Chrome does not Support HEVC at all. Edge only Support HEVC when you have brought the HEVC license on the Microsoft Store on your Windows PC. Firefox under MacOS is the only Browser besides Safari that does support HEVC.

ghost commented 1 year ago

You will have a much better compatibility when you go with AV1 instead of HEVC

strbass28 commented 1 year ago

I'm testing with RTSP videos coming from commercial surveillance cameras. They advertise H.265 support. I don't think transcoding it to AV1 is practical.

Is it really true that chrome and edge don't have support for HEVC? If I make a mp4 out of the RTSP with the ffmpeg -vcodec copy then chrome and edge can play back the file. ffprobe confirms the file is HEVC. I'm testing chrome on OSX and edge on a fresh install of windows 11. There's a lot of conflicting information but this says chrome can play it back->https://chromestatus.com/feature/5186511939567616 .

This is the output from ffmpeg when creating the m3u8 playlist from a RTSP stream.

Input #0, rtsp, from 'rtsp://127.0.0.1:44293': Metadata: title : Media Presentation Duration: N/A, start: 0.050000, bitrate: N/A Stream #0:0: Video: hevc (Main), yuvj420p(pc, bt709), 3072x1728, 20 fps, 20 tbr, 90k tbn [hls @ 0x55f5cd22e9c0] Opening '/var/www//output/SSp805mzRS95SXI7/hlsvideo_s5XCGqguetOGOm1I/init.mp4' for writing Output #0, hls, to '/var/www//output/SSp805mzRS95SXI7/hlsvideo_s5XCGqguetOGOm1I/index.m3u8': Metadata: title : Media Presentation encoder : Lavf59.28.100 Stream #0:0: Video: hevc (Main) (hvc1 / 0x31637668), yuvj420p(pc, bt709), 3072x1728, q=2-31, 5000 kb/s, 20 fps, 20 tbr, 10240 tbn Stream mapping: Stream #0:0 -> #0:0 (copy)

Seams to me like if chrome can play back HEVC files in mpeg containers then video-js should be able to handle HEVC encodings in HLS playlists.

Thanks for all the feedback.

gkatsev commented 1 year ago

Chrome does not Support HEVC at all

This is not true anymore. With Chrome 107, if the hardware supports HEVC, Chrome will play HEVC.

strbass28 commented 1 year ago

I've confirmed safari, edge, and chrome can playback HEVC encoded mp4 videos. Windows 10 with edge can play back HEVC videos without a HEVC decoder install. Windows 11 requires the purchase of a 99 cent decoder for the video to play in edge.

However, even though mp4 videos play in edge, I haven't been able to play HEVC m3u8 playlists in video-js outside of safari. Safari works great.

let me know if there is anything else to try.

strbass28 commented 1 year ago

If I user a master/manifest with the following then HEVC encoded files from two sources work on chrome. I have no idea how to determine this codec information coming from the sources and ffmpeg doesn't look to be able to generate proper codec information. At least I haven't been able to figure out how to do it. I just copied the codec information from the above hevc manifest example and it has worked from two cameras. Looks like this.

EXTM3U

EXT-X-VERSION:8

variants

EXT-X-STREAM-INF:BANDWIDTH=1814000,CODECS="mp4a.40.2,hvc1.1.6.L150.90"

index.m3u8

ghost commented 1 year ago

@gkatsev My Bad, Chrome now Supports HEVC, finally...

ghost commented 1 year ago

@strbass28 I will now provide you some insights which will most likely solve all your issues.

First, you should have a look at this list:

https://cconcolato.github.io/media-mime-support/

It might be a bit outdated, but 95% is still accurate.

Second, get familiar with HLS packaging, a good point to start are the Apple docs, have a look here:

https://developer.apple.com/documentation/http_live_streaming/understanding_the_http_live_streaming_architecture

These docs also get you familiar with HEVC and HLS packaging, there are many things you have to do in forehand. For example, is your stream mpegts (.ts) or fmp4 (.m4s) segments? If you are trying to pack HEVC into mpegts, it won't work, and it never will as it's simply not compatible, same goes for AV1. You can basically only use mpegts if you are about to just use AVC1 aka h.264 for your video stream.

Have a look at the following manifest, it represents how an AdaptiveBitRate Stream (ABR) has to look like:


#EXTM3U
#EXT-X-VERSION:7
#EXT-X-INDEPENDENT-SEGMENTS
#EXT-X-PLAYLIST-TYPE VOD

#EXT-X-MEDIA:TYPE=AUDIO,GROUP-ID="a-0",NAME="Deutsch (5.1)",CHANNELS=6,AUTOSELECT="YES",DEFAULT="NO",LANGUAGE="de",URI="a-eac3-de-ec-3_384000/master.m3u8"
#EXT-X-MEDIA:TYPE=AUDIO,GROUP-ID="a-0",NAME="English (5.1)",CHANNELS=6,AUTOSELECT="YES",DEFAULT="NO",LANGUAGE="en",URI="a-eac3-en-ec-3_384000/master.m3u8"
#EXT-X-MEDIA:TYPE=AUDIO,GROUP-ID="a-0",NAME="Français (5.1)",CHANNELS=6,AUTOSELECT="YES",DEFAULT="NO",LANGUAGE="fr",URI="a-eac3-fr-ec-3_384000/master.m3u8"

#EXT-X-MEDIA:TYPE=AUDIO,GROUP-ID="a-1",NAME="Deutsch (5.1)",CHANNELS=6,AUTOSELECT="YES",DEFAULT="NO",LANGUAGE="de",URI="a-aac-de-mp4a.40.2_384000/master.m3u8"
#EXT-X-MEDIA:TYPE=AUDIO,GROUP-ID="a-1",NAME="English (5.1)",CHANNELS=6,AUTOSELECT="YES",DEFAULT="NO",LANGUAGE="en",URI="a-aac-en-mp4a.40.2_384000/master.m3u8"
#EXT-X-MEDIA:TYPE=AUDIO,GROUP-ID="a-1",NAME="Français (5.1)",CHANNELS=6,AUTOSELECT="YES",DEFAULT="NO",LANGUAGE="fr",URI="a-aac-fr-mp4a.40.2_384000/master.m3u8"

#EXT-X-MEDIA:TYPE=AUDIO,GROUP-ID="a-2",NAME="Deutsch (5.1)",CHANNELS=2,AUTOSELECT="YES",DEFAULT="NO",LANGUAGE="de",URI="a-aac_he-de-mp4a.40.5_128000/master.m3u8"
#EXT-X-MEDIA:TYPE=AUDIO,GROUP-ID="a-2",NAME="English (5.1)",CHANNELS=2,AUTOSELECT="YES",DEFAULT="NO",LANGUAGE="en",URI="a-aac_he-en-mp4a.40.5_128000/master.m3u8"
#EXT-X-MEDIA:TYPE=AUDIO,GROUP-ID="a-2",NAME="Français (5.1)",CHANNELS=2,AUTOSELECT="YES",DEFAULT="NO",LANGUAGE="fr",URI="a-aac_he-fr-mp4a.40.5_128000/master.m3u8"

#EXT-X-MEDIA:TYPE=SUBTITLES,GROUP-ID="s-0",NAME="Deutsch",FORCED="NO",AUTOSELECT="YES",DEFAULT="NO",LANGUAGE="de",URI="s-vtt-de/master.m3u8"
#EXT-X-MEDIA:TYPE=SUBTITLES,GROUP-ID="s-0",NAME="Deutsch (Forced)",FORCED="NO",AUTOSELECT="YES",DEFAULT="NO",LANGUAGE="de",URI="s-vtt-de-forced/master.m3u8"
#EXT-X-MEDIA:TYPE=SUBTITLES,GROUP-ID="s-0",NAME="English",FORCED="NO",AUTOSELECT="YES",DEFAULT="NO",LANGUAGE="en",URI="s-vtt-en/master.m3u8"
#EXT-X-MEDIA:TYPE=SUBTITLES,GROUP-ID="s-0",NAME="English (Forced)",FORCED="NO",AUTOSELECT="YES",DEFAULT="NO",LANGUAGE="en",URI="s-vtt-en-forced/master.m3u8"
#EXT-X-MEDIA:TYPE=SUBTITLES,GROUP-ID="s-0",NAME="Français",FORCED="NO",AUTOSELECT="YES",DEFAULT="NO",LANGUAGE="fr",URI="s-vtt-fr/master.m3u8"
#EXT-X-MEDIA:TYPE=SUBTITLES,GROUP-ID="s-0",NAME="Français (Forced)",FORCED="NO",AUTOSELECT="YES",DEFAULT="NO",LANGUAGE="fr",URI="s-vtt-fr-forced/master.m3u8"

#EXT-X-STREAM-INF:AVERAGE-BANDWIDTH=5102592,BANDWIDTH=5612851,VIDEO-RANGE=SDR,CLOSED-CAPTIONS=NONE,HDCP-LEVEL=NONE,RESOLUTION=1920x1080,FRAME-RATE=24.0,CODECS="hvc1.1.4.L126.B0,ec-3",AUDIO="a-0",SUBTITLES="s-0"
v-hevc-1080p-hvc1.1.4.L126.B0_SDR/master.m3u8

#EXT-X-STREAM-INF:AVERAGE-BANDWIDTH=5102592,BANDWIDTH=5612851,VIDEO-RANGE=SDR,CLOSED-CAPTIONS=NONE,HDCP-LEVEL=NONE,RESOLUTION=1920x1080,FRAME-RATE=24.0,CODECS="hvc1.1.4.L126.B0,mp4a.40.2",AUDIO="a-1",SUBTITLES="s-0"
v-hevc-1080p-hvc1.1.4.L126.B0_SDR/master.m3u8

#EXT-X-STREAM-INF:AVERAGE-BANDWIDTH=4846592,BANDWIDTH=5331251,VIDEO-RANGE=SDR,CLOSED-CAPTIONS=NONE,HDCP-LEVEL=NONE,RESOLUTION=1920x1080,FRAME-RATE=24.0,CODECS="hvc1.1.4.L126.B0,mp4a.40.5",AUDIO="a-2",SUBTITLES="s-0"
v-hevc-1080p-hvc1.1.4.L126.B0_SDR/master.m3u8

#EXT-X-STREAM-INF:AVERAGE-BANDWIDTH=3529728,BANDWIDTH=3882700,VIDEO-RANGE=SDR,CLOSED-CAPTIONS=NONE,HDCP-LEVEL=NONE,RESOLUTION=1280x720,FRAME-RATE=24.0,CODECS="hvc1.1.4.L126.B0,ec-3",AUDIO="a-0",SUBTITLES="s-0"
v-hevc-720p-hvc1.1.4.L126.B0_SDR/master.m3u8

#EXT-X-STREAM-INF:AVERAGE-BANDWIDTH=3529728,BANDWIDTH=3882700,VIDEO-RANGE=SDR,CLOSED-CAPTIONS=NONE,HDCP-LEVEL=NONE,RESOLUTION=1280x720,FRAME-RATE=24.0,CODECS="hvc1.1.4.L126.B0,mp4a.40.2",AUDIO="a-1",SUBTITLES="s-0"
v-hevc-720p-hvc1.1.4.L126.B0_SDR/master.m3u8

#EXT-X-STREAM-INF:AVERAGE-BANDWIDTH=3273728,BANDWIDTH=3601100,VIDEO-RANGE=SDR,CLOSED-CAPTIONS=NONE,HDCP-LEVEL=NONE,RESOLUTION=1280x720,FRAME-RATE=24.0,CODECS="hvc1.1.4.L126.B0,mp4a.40.5",AUDIO="a-2",SUBTITLES="s-0"
v-hevc-720p-hvc1.1.4.L126.B0_SDR/master.m3u8

#EXT-X-STREAM-INF:AVERAGE-BANDWIDTH=1956864,BANDWIDTH=2152550,VIDEO-RANGE=SDR,CLOSED-CAPTIONS=NONE,HDCP-LEVEL=NONE,RESOLUTION=640x480,FRAME-RATE=24.0,CODECS="hvc1.1.4.L126.B0,ec-3",AUDIO="a-0",SUBTITLES="s-0"
v-hevc-480p-hvc1.1.4.L126.B0_SDR/master.m3u8

#EXT-X-STREAM-INF:AVERAGE-BANDWIDTH=1956864,BANDWIDTH=2152550,VIDEO-RANGE=SDR,CLOSED-CAPTIONS=NONE,HDCP-LEVEL=NONE,RESOLUTION=640x480,FRAME-RATE=24.0,CODECS="hvc1.1.4.L126.B0,mp4a.40.2",AUDIO="a-1",SUBTITLES="s-0"
v-hevc-480p-hvc1.1.4.L126.B0_SDR/master.m3u8

#EXT-X-STREAM-INF:AVERAGE-BANDWIDTH=1700864,BANDWIDTH=1870950,VIDEO-RANGE=SDR,CLOSED-CAPTIONS=NONE,HDCP-LEVEL=NONE,RESOLUTION=640x480,FRAME-RATE=24.0,CODECS="hvc1.1.4.L126.B0,mp4a.40.5",AUDIO="a-2",SUBTITLES="s-0"
v-hevc-480p-hvc1.1.4.L126.B0_SDR/master.m3u8

If you don't have any use for Adaption Sets, meaning multiple version(s) of the same video at different quality levels, simply have it look like this for example:

#EXTM3U
#EXT-X-VERSION:7
#EXT-X-INDEPENDENT-SEGMENTS
#EXT-X-PLAYLIST-TYPE VOD

#EXT-X-MEDIA:TYPE=AUDIO,GROUP-ID="a-0",NAME="Deutsch (5.1)",CHANNELS=6,AUTOSELECT="YES",DEFAULT="NO",LANGUAGE="de",URI="a-eac3-de-ec-3_384000/master.m3u8"
#EXT-X-MEDIA:TYPE=AUDIO,GROUP-ID="a-0",NAME="English (5.1)",CHANNELS=6,AUTOSELECT="YES",DEFAULT="NO",LANGUAGE="en",URI="a-eac3-en-ec-3_384000/master.m3u8"
#EXT-X-MEDIA:TYPE=AUDIO,GROUP-ID="a-0",NAME="Français (5.1)",CHANNELS=6,AUTOSELECT="YES",DEFAULT="NO",LANGUAGE="fr",URI="a-eac3-fr-ec-3_384000/master.m3u8"

#EXT-X-MEDIA:TYPE=AUDIO,GROUP-ID="a-1",NAME="Deutsch (5.1)",CHANNELS=6,AUTOSELECT="YES",DEFAULT="NO",LANGUAGE="de",URI="a-aac-de-mp4a.40.2_384000/master.m3u8"
#EXT-X-MEDIA:TYPE=AUDIO,GROUP-ID="a-1",NAME="English (5.1)",CHANNELS=6,AUTOSELECT="YES",DEFAULT="NO",LANGUAGE="en",URI="a-aac-en-mp4a.40.2_384000/master.m3u8"
#EXT-X-MEDIA:TYPE=AUDIO,GROUP-ID="a-1",NAME="Français (5.1)",CHANNELS=6,AUTOSELECT="YES",DEFAULT="NO",LANGUAGE="fr",URI="a-aac-fr-mp4a.40.2_384000/master.m3u8"

#EXT-X-MEDIA:TYPE=AUDIO,GROUP-ID="a-2",NAME="Deutsch (5.1)",CHANNELS=2,AUTOSELECT="YES",DEFAULT="NO",LANGUAGE="de",URI="a-aac_he-de-mp4a.40.5_128000/master.m3u8"
#EXT-X-MEDIA:TYPE=AUDIO,GROUP-ID="a-2",NAME="English (5.1)",CHANNELS=2,AUTOSELECT="YES",DEFAULT="NO",LANGUAGE="en",URI="a-aac_he-en-mp4a.40.5_128000/master.m3u8"
#EXT-X-MEDIA:TYPE=AUDIO,GROUP-ID="a-2",NAME="Français (5.1)",CHANNELS=2,AUTOSELECT="YES",DEFAULT="NO",LANGUAGE="fr",URI="a-aac_he-fr-mp4a.40.5_128000/master.m3u8"

#EXT-X-MEDIA:TYPE=SUBTITLES,GROUP-ID="s-0",NAME="Deutsch",FORCED="NO",AUTOSELECT="YES",DEFAULT="NO",LANGUAGE="de",URI="s-vtt-de/master.m3u8"
#EXT-X-MEDIA:TYPE=SUBTITLES,GROUP-ID="s-0",NAME="Deutsch (Forced)",FORCED="NO",AUTOSELECT="YES",DEFAULT="NO",LANGUAGE="de",URI="s-vtt-de-forced/master.m3u8"
#EXT-X-MEDIA:TYPE=SUBTITLES,GROUP-ID="s-0",NAME="English",FORCED="NO",AUTOSELECT="YES",DEFAULT="NO",LANGUAGE="en",URI="s-vtt-en/master.m3u8"
#EXT-X-MEDIA:TYPE=SUBTITLES,GROUP-ID="s-0",NAME="English (Forced)",FORCED="NO",AUTOSELECT="YES",DEFAULT="NO",LANGUAGE="en",URI="s-vtt-en-forced/master.m3u8"
#EXT-X-MEDIA:TYPE=SUBTITLES,GROUP-ID="s-0",NAME="Français",FORCED="NO",AUTOSELECT="YES",DEFAULT="NO",LANGUAGE="fr",URI="s-vtt-fr/master.m3u8"
#EXT-X-MEDIA:TYPE=SUBTITLES,GROUP-ID="s-0",NAME="Français (Forced)",FORCED="NO",AUTOSELECT="YES",DEFAULT="NO",LANGUAGE="fr",URI="s-vtt-fr-forced/master.m3u8"

#EXT-X-STREAM-INF:AVERAGE-BANDWIDTH=5102592,BANDWIDTH=5612851,VIDEO-RANGE=SDR,CLOSED-CAPTIONS=NONE,HDCP-LEVEL=NONE,RESOLUTION=1920x1080,FRAME-RATE=24.0,CODECS="hvc1.1.4.L126.B0,ec-3",AUDIO="a-0",SUBTITLES="s-0"
v-hevc-1080p-hvc1.1.4.L126.B0_SDR/master.m3u8

Hope it helps. FYI, VideoJS does currently ignore Forced subs flags at the manifest, if you do FORCED="YES" the subtitle will disappear for selection, thats why is switched to "NO" for all subs, even when they are actually forced.