ossrs / srs

SRS is a simple, high-efficiency, real-time video server supporting RTMP, WebRTC, HLS, HTTP-FLV, SRT, MPEG-DASH, and GB28181.
https://ossrs.io
MIT License
24.7k stars 5.28k forks source link

DVR: The mp4 file from DVR for camera can't play on window, MacOS, iOS #4065

Open hieunv opened 1 month ago

hieunv commented 1 month ago

Describe the bug I are using SRS to record RTMP stream from camera, but the file can't play with IOS/MAC OS, Window. I found that, the issue can fix by change format video header from yuvj420p(pc, bt709) to yuv420p(tv, bt709) by this comamnd ffmpeg -i original.mp4 -c copy -bsf:v h264_metadata=video_full_range_flag=0 change_to_tv.mp4

Version Docker ossrs/srs:3 , ossrs/srs:5 , ossrs/srs:6

To Reproduce Steps to reproduce the behavior:

  1. I using librtmp and capture NALU fram H264 on camera and AAC audio send to the SRS, and we can't change format color on camera.

Expected behavior Can you provide an option on SRS to change header of mp4 file to yuv420

Additional context I send 4 shot video

https://github.com/ossrs/srs/assets/4393102/2579daed-9904-4770-b449-3c978e3b5365

https://github.com/ossrs/srs/assets/4393102/b2dcb537-5901-492a-88e5-a2eaed899692

https://github.com/ossrs/srs/assets/4393102/809eecf3-c93b-4398-9d74-4e9900272de1

https://github.com/ossrs/srs/assets/4393102/3f679902-8d25-4f98-9993-62ecc5f5fe70

camera --> rtmp-srs --> original.mp4 original.mp4 --> change header to tv color -> change_to_tv.mp4 //ffmpeg -i original.mp4 -c copy -bsf:v h264_metadata=video_full_range_flag=0 change_to_tv.mp4 original.mp4 --> rtmp-srs --> conver_pc.mp4 change_to_tv.mp4 --> rtmp-srs --> conver_tv.mp4

The change_to_tv.mp4 and convert_tv.mp4 can play on window/ios the original.mp4 vs convert_pc.mp4 can't not play on window/ios

winlinvip commented 1 month ago

Workaround: Utilize the recording feature of Oryx.

TRANS_BY_GPT4

suzp1984 commented 1 month ago

video_full_range_flag is belong to a sps parameter. But srs only support part of sps demux. Maybe I can add more sps demux/remux features to srs later.

To this question, the pixel format is determined by this way:

First, read sps vui parameters, to get sps->vui.video_full_range_flag; https://github.com/FFmpeg/FFmpeg/blob/63697d3350b1975c05be126d466659885c09d2e1/libavcodec/h2645_vui.c#L62 Then, set color_range in AVContext to AVCOL_RANGE_JPEG or AVCOL_RANGE_MPEG by above value. https://github.com/FFmpeg/FFmpeg/blob/63697d3350b1975c05be126d466659885c09d2e1/libavcodec/h264_slice.c#L1105 Then, get pix_fmt from the color_range. https://github.com/FFmpeg/FFmpeg/blob/63697d3350b1975c05be126d466659885c09d2e1/libavcodec/h264_slice.c#L892-L895

So, the pix_fmt become AV_PIX_FMT_YUVJ420P, which is marked as deprecated in ffmpeg, if video_full_range_flag > 0.

hieunv commented 1 month ago

Thank @suzp1984 and @winlinvip, I found the new thing. I can pack the .mp4 file on camera by libmp4v2 with video_full_range_flag >0 and the video still can play on MAC/WIN/IOS I guess the video_full_range_flag=0 using for TV, buildboard... so it don't need enough attribute, and Video players easily accept it. The video player need more metadata on video header in case The video_full_range_flag > 0. I used ffmpeg stream mp4 file pack by libmp4v2 to srs server by rtmp. And the file from DVR still can play on MAC/WIN/IOS. The problem now, I haven't found a difference between playable files and non-playable files

hieunv commented 1 month ago

I attach file : video-libmp4v2-3M.mp4 can play on default player of all OS, include Win/IOS/MAC

https://github.com/ossrs/srs/assets/4393102/4acb0e8b-cbdf-4c4c-a7e2-4ba3c991a8e4

Camera streamed rtmp and saved by DVR mode with name original, that can't play on default video player of WIN/IOS/MAC

https://github.com/ossrs/srs/assets/4393102/d36ced5a-ba47-484f-9507-a5a43d6fcc51

I didn't find diffirence thing beetwen 2 files

suzp1984 commented 1 month ago

goto srs/trunk folder. make srs_mp4_parser. ./objs/srs_mp4_parser original.mp4 verbose ./objs/srs_mp4_parser video-libmp4v2-3M.mp4 verbose The mp4 container details will be printed, I don't know every single bytes means, but they are different. Anyway, srs_mp4_parser maybe helpful to dig deeper.

And I don't think video-libmp4v2-3M.mp4 plays well in MacOS with QuickTime Player. Compare the ffplay with QuickTime Player, I found QuickTime Player only render top-left (around 1/4) picture compared with ffplay, and Quicktime Player is silent, no voice.

So video-libmp4v2-3M.mp4 still has problem.