Jump to content

adding a new encoder - interface issues


Recommended Posts

Posted

Hello,

 

I've been able to add a new encoder (h264_v4l2m2m) to emby, by adding it to the list in MediaBrowser.MediaEncoding/Encoder/EncoderValidator.cs, and adding its ffmpeg options to MediaBrowser.Controller/MediaEncoding/EncodingHelper.cs (e.g. the pix_fmt, etc...). I've tested it by setting it as the defaultEncoder in EncodingHelper.cs and it works.

However, I have issues adding it to the list of encoders in the GUI dropdown.

I have added it to the dropdown in MediaBrowser.WebDashboard/dashboard-ui/encodingsettings.html - I've even tried modifying existing options there - but no change there is actually reflected in the interface. I even tried modifying the deployed code (e.g. /srv/MediaBrowser.Mono.3.2.8.0/dashboard-ui/encodingsettings.html) but the encoding page still ignores all my edits. Any idea why this happens??

 

Thanks.

 

Posted

Nevermind, I think it was the browser just caching the html... it it showing up now :)

Posted

Thanks. If you want to submit a pull request I can look at integrating it. Thanks !

Posted

Thanks. If you want to submit a pull request I can look at integrating it. Thanks !

 

I am testing it, and while it works, there are issues when starting the video from a position that is not the start - the "-ss" parameter.

So I still have to work on the ffmpeg patches - but this has nothing to do with Emby :). Gstreamer works much better, but it's also harder to integrate into Emby :(

 

Nevertheless, since emby checks if encoder is available before using it, I think it's safe to add it -- I didn't actually cloned the entire repo so it's easier for me to just post the commit here (it applies successfully on the 3.2.8 release):

(also available at http://paste.debian.net/922751/)

commit 53f82f538a76b862677f584713d2c3e66cf9a2e0
Author: memeka <mihailescu2m@[member="gmail"].com>
Date:   Mon Mar 20 12:46:12 2017 +1030

    Add h264_v4l2m2m hw-encoder for Exynos MFC arm platforms (requires ffmpeg support)

diff --git a/MediaBrowser.Controller/MediaEncoding/EncodingHelper.cs b/MediaBrowser.Controller/MediaEncoding/EncodingHelper.cs
index 80b9cc1..156f62f 100644
--- a/MediaBrowser.Controller/MediaEncoding/EncodingHelper.cs
+++ b/MediaBrowser.Controller/MediaEncoding/EncodingHelper.cs
@@ -56,6 +56,10 @@ namespace MediaBrowser.Controller.MediaEncoding
                 {
                     return GetAvailableEncoder("h264_omx", defaultEncoder);
                 }
+		if (string.Equals(hwType, "h264_v4l2m2m", StringComparison.OrdinalIgnoreCase))
+		{
+		    return GetAvailableEncoder("h264_v4l2m2m", defaultEncoder);
+		}
                 if (string.Equals(hwType, "vaapi", StringComparison.OrdinalIgnoreCase) && !string.IsNullOrWhiteSpace(encodingOptions.VaapiDevice))
                 {
                     if (IsVaapiSupported(state))
@@ -649,7 +653,8 @@ namespace MediaBrowser.Controller.MediaEncoding
             if (!string.IsNullOrEmpty(request.Profile))
             {
                 if (!string.Equals(videoEncoder, "h264_omx", StringComparison.OrdinalIgnoreCase) &&
-                    !string.Equals(videoEncoder, "h264_vaapi", StringComparison.OrdinalIgnoreCase))
+                    !string.Equals(videoEncoder, "h264_vaapi", StringComparison.OrdinalIgnoreCase) &&
+		    !string.Equals(videoEncoder, "h264_v4l2m2m", StringComparison.OrdinalIgnoreCase))
                 {
                     // not supported by h264_omx
                     param += " -profile:v " + request.Profile;
@@ -700,7 +705,8 @@ namespace MediaBrowser.Controller.MediaEncoding
                             break;
                     }
                 }
-                else if (!string.Equals(videoEncoder, "h264_omx", StringComparison.OrdinalIgnoreCase))
+                else if (!string.Equals(videoEncoder, "h264_omx", StringComparison.OrdinalIgnoreCase) &&
+			 !string.Equals(videoEncoder, "h264_v4l2m2m", StringComparison.OrdinalIgnoreCase))
                 {
                     param += " -level " + level;
                 }
@@ -713,11 +719,17 @@ namespace MediaBrowser.Controller.MediaEncoding
 
             if (!string.Equals(videoEncoder, "h264_omx", StringComparison.OrdinalIgnoreCase) &&
                 !string.Equals(videoEncoder, "h264_qsv", StringComparison.OrdinalIgnoreCase) &&
-                !string.Equals(videoEncoder, "h264_vaapi", StringComparison.OrdinalIgnoreCase))
+                !string.Equals(videoEncoder, "h264_vaapi", StringComparison.OrdinalIgnoreCase) &&
+		!string.Equals(videoEncoder, "h264_v4l2m2m", StringComparison.OrdinalIgnoreCase))
             {
                 param = "-pix_fmt yuv420p " + param;
             }
 
+	    if (string.Equals(videoEncoder, "h264_v4l2m2m", StringComparison.OrdinalIgnoreCase))
+	    {
+		param = "-pix_fmt nv21 " + param;
+	    }
+
             return param;
         }
 
diff --git a/MediaBrowser.MediaEncoding/Encoder/EncoderValidator.cs b/MediaBrowser.MediaEncoding/Encoder/EncoderValidator.cs
index 9c1189f..84530c5 100644
--- a/MediaBrowser.MediaEncoding/Encoder/EncoderValidator.cs
+++ b/MediaBrowser.MediaEncoding/Encoder/EncoderValidator.cs
@@ -142,6 +142,7 @@ namespace MediaBrowser.MediaEncoding.Encoder
                 "hevc_omx",
                 "h264_vaapi",
                 "hevc_vaapi",
+		"h264_v4l2m2m",
                 "ac3"
             };
 
diff --git a/MediaBrowser.WebDashboard/dashboard-ui/encodingsettings.html b/MediaBrowser.WebDashboard/dashboard-ui/encodingsettings.html
index bf66c4f..abcb211 100644
--- a/MediaBrowser.WebDashboard/dashboard-ui/encodingsettings.html
+++ b/MediaBrowser.WebDashboard/dashboard-ui/encodingsettings.html
@@ -12,6 +12,7 @@
                         <option value="h264_omx">OpenMAX OMX (experimental)</option>
                         <option value="nvenc">Nvidia NVENC (experimental)</option>
                         <option value="vaapi">Video Acceleration API (VA API) (experimental)</option>
+			<option value="h264_v4l2m2m">Exynos V4L2 MFC Encoder (experimental)</option>
                     </select>
                     <div class="fieldDescription">${LabelHardwareAccelerationTypeHelp}</div>
                 </div>
Posted

PS: here's a server log from transcoding an avi to h264:

http://129.127.248.18:8096/emby/videos/0263a73ae384c2feef7b07256f1a8c97/hls1/main/0.ts?DeviceId=39bd3c935755c4f8f5fb742f0026f67ae17b13f9&MediaSourceId=0263a73ae384c2feef7b07256f1a8c97&VideoCodec=h264&AudioCodec=aac,mp3&AudioStreamIndex=1&VideoBitrate=564578178&AudioBitrate=127704&Level=51&Profile=high&PlaySessionId=50dde92a0ce0453393f49d9cec59f9a2&api_key=fc1ea2d54e3d47aface5f29be7fd0792&CopyTimestamps=false&TranscodingMaxAudioChannels=6&EnableSubtitlesInManifest=false&Tag=014fae5077a8f8d2ee962659fef2a772&RequireAvc=true

{"Protocol":"File","Id":"0263a73ae384c2feef7b07256f1a8c97","Path":"/home/odroid/Video/mono.avi","Type":"Default","Container":"avi","Name":"SD/MSMPEG4/MP3","IsRemote":false,"ETag":"014fae5077a8f8d2ee962659fef2a772","RunTimeTicks":80035230000,"ReadAtNativeFramerate":false,"SupportsTranscoding":true,"SupportsDirectStream":true,"SupportsDirectPlay":true,"IsInfiniteStream":false,"RequiresOpening":false,"RequiresClosing":false,"SupportsProbing":true,"VideoType":"VideoFile","MediaStreams":[{"Codec":"msmpeg4","CodecTag":"DIV3","TimeBase":"4171/100000","CodecTimeBase":"4171/100000","IsInterlaced":false,"BitRate":573722,"RefFrames":1,"IsDefault":false,"IsForced":false,"Height":288,"Width":512,"AverageFrameRate":23.97507,"RealFrameRate":23.97507,"Type":"Video","AspectRatio":"16:9","Index":0,"IsExternal":false,"IsTextSubtitleStream":false,"SupportsExternalStream":false,"PixelFormat":"yuv420p","Level":-99,"IsAnamorphic":false},{"Codec":"mp3","TimeBase":"1/15963","CodecTimeBase":"1/44100","DisplayTitle":"MP3 stereo","IsInterlaced":false,"ChannelLayout":"stereo","BitRate":127704,"Channels":2,"SampleRate":44100,"IsDefault":false,"IsForced":false,"Type":"Audio","Index":1,"IsExternal":false,"IsTextSubtitleStream":false,"SupportsExternalStream":false,"Level":0,"IsAnamorphic":false}],"PlayableStreamFileNames":[],"Formats":[],"Bitrate":706525,"RequiredHttpHeaders":{}}

/usr/local/bin/ffmpeg -i file:"/home/odroid/Video/mono.avi" -map_metadata -1 -map_chapters -1 -threads 1 -map 0:0 -map 0:1 -map -0:s -codec:v:0 h264_v4l2m2m -pix_fmt nv21  -b:v 573722 -maxrate 573722 -bufsize 1147444 -vsync -1 -force_key_frames "expr:gte(t,n_forced*3)" -vf "scale=trunc(min(max(iw\,ih*dar)\,720)/2)*2:trunc(ow/dar/2)*2" -copyts -codec:a:0 copy -f segment -max_delay 5000000 -avoid_negative_ts disabled -start_at_zero -segment_time 3  -individual_header_trailer 0 -segment_format mpegts -segment_list_type m3u8 -segment_start_number 0 -segment_list "/home/odroid/src/emby/Emby-3.2.8/Tools/Linux_Build_Scripts/mediabrowser/MediaBrowser.Mono.3.2.8.0/ProgramData-Server/transcoding-temp/2069e3eb5f725dc5640f19cf1a3988d8.m3u8" -y "/home/odroid/src/emby/Emby-3.2.8/Tools/Linux_Build_Scripts/mediabrowser/MediaBrowser.Mono.3.2.8.0/ProgramData-Server/transcoding-temp/2069e3eb5f725dc5640f19cf1a3988d8%d.ts"


ffmpeg version 3.0.2 Copyright (c) 2000-2016 the FFmpeg developers
  built with gcc 6.3.0 (Debian 6.3.0-6) 20170205
  configuration: --prefix=/usr/local --libdir=/usr/local/lib --incdir=/usr/local/include --pkg-config-flags=--static --enable-gpl --enable-static --enable-avresample --enable-avisynth --enable-gnutls --enable-ladspa --enable-libass --enable-libbluray --enable-libbs2b --enable-libcaca --enable-libcdio --enable-libflite --enable-libfontconfig --enable-libfreetype --enable-libfribidi --enable-libgme --enable-libgsm --enable-libmodplug --enable-libmp3lame --enable-libopus --enable-libpulse --enable-librubberband --enable-librtmp --enable-libshine --enable-libsnappy --enable-libsoxr --enable-libspeex --enable-libssh --enable-libtheora --enable-libtwolame --enable-libvorbis --enable-libvpx --enable-libwavpack --enable-libwebp --enable-libx265 --enable-libxvid --enable-libzvbi --enable-openal --enable-opengl --disable-stripping
  libavutil      55. 17.103 / 55. 17.103
  libavcodec     57. 24.102 / 57. 24.102
  libavformat    57. 25.100 / 57. 25.100
  libavdevice    57.  0.101 / 57.  0.101
  libavfilter     6. 31.100 /  6. 31.100
  libavresample   3.  0.  0 /  3.  0.  0
  libswscale      4.  0.100 /  4.  0.100
  libswresample   2.  0.101 /  2.  0.101
  libpostproc    54.  0.100 / 54.  0.100
Input #0, avi, from 'file:/home/odroid/Video/mono.avi':
  Duration: 02:13:23.52, start: 0.000000, bitrate: 706 kb/s
    Stream #0:0: Video: msmpeg4v3 (DIV3 / 0x33564944), yuv420p, 512x288, 573 kb/s, 23.98 fps, 23.98 tbr, 23.98 tbn, 23.98 tbc
    Stream #0:1: Audio: mp3 (U[0][0][0] / 0x0055), 44100 Hz, stereo, s16p, 127 kb/s
[h264_v4l2m2m @ 0x808132a0] Device path not set, probing /dev/video*
[h264_v4l2m2m @ 0x808132a0] Using device /dev/video11
[h264_v4l2m2m @ 0x808132a0] mfc-enc: gop_size: 12
[h264_v4l2m2m @ 0x808132a0] mfc-enc: enabling bitrate control if required rate 573722 > 1
[h264_v4l2m2m @ 0x808132a0] mfc-enc: max b-frames: 0
[h264_v4l2m2m @ 0x808132a0] mfc-enc: h264 profile: 4
[h264_v4l2m2m @ 0x808132a0] mfc-enc: min/max quantizer scale: (2, 31)
[h264_v4l2m2m @ 0x808132a0] mfc-enc: h264 level: V4L2_MPEG_VIDEO_H264_LEVEL_4_0
Output #0, segment, to '/home/odroid/src/emby/Emby-3.2.8/Tools/Linux_Build_Scripts/mediabrowser/MediaBrowser.Mono.3.2.8.0/ProgramData-Server/transcoding-temp/2069e3eb5f725dc5640f19cf1a3988d8%d.ts':
  Metadata:
    encoder         : Lavf57.25.100
    Stream #0:0: Video: h264 (h264_v4l2m2m), nv21, 512x288, q=2-31, 573 kb/s, 23.98 fps, 90k tbn, 23.98 tbc
    Metadata:
      encoder         : Lavc57.24.102 h264_v4l2m2m
    Stream #0:1: Audio: mp3 (U[0][0][0] / 0x0055), 44100 Hz, stereo, 127 kb/s
Stream mapping:
  Stream #0:0 -> #0:0 (msmpeg4v3 (msmpeg4) -> h264 (h264_v4l2m2m))
  Stream #0:1 -> #0:1 (copy)
Press [q] to stop, [?] for help
[h264_v4l2m2m @ 0x808132a0] Performing useless memcpy() on output pool because buffers do not match
[h264_v4l2m2m @ 0x808132a0] This could be avoided by using av_v4l_buffer_pool_get_buffer*() or av_v4l_buffer_pool_make_pipe()
[segment @ 0x80814170] Timestamps are unset in a packet for stream 0. This is deprecated and will stop working in the future. Fix your code to set the timestamps properly
[segment @ 0x80814170] Encoder did not produce proper pts, making some up.
frame=  297 fps=0.0 q=-0.0 size=N/A time=00:00:13.02 bitrate=N/A speed=  26x    
frame=  737 fps=736 q=-0.0 size=N/A time=00:00:31.51 bitrate=N/A speed=31.5x    
frame= 1114 fps=742 q=-0.0 size=N/A time=00:00:47.03 bitrate=N/A speed=31.3x    
frame= 1535 fps=767 q=-0.0 size=N/A time=00:01:04.53 bitrate=N/A speed=32.2x  
Posted

Ok, so after investigating, I am not sure where the issue is...

 

If I transcode to a file (e.g. mp4), then i can play the file normally, and go to any location ... there's no issue in the transcoded file.

 

However, when using Emby, sometimes playback stops after a while, and going to a random location is not working (so e.g. Resume never works).

I think the issue is because of HLS (e.g. the playback stops at the end of a segment). Are there any specific encoding options for HLS that I need to be aware of (and implement them in the encoder)? 

 

For reference, this is the mediainfo of an encoded mp4 file: http://paste.debian.net/922759/

This is the mediainfo for an encoded .ts segment done by emby: http://paste.debian.net/922760/

And this is the mediainfo for the m3u8 playlist generated by emby: http://paste.debian.net/922762/
 
Is there anything there that stands out that might explain why players have issues with segments?
Posted

Well if you're working directly with the encoder, then i would compare timestamps within segment files to that of what is generated by libx264. If the timestamps are not right then that will definitely cause those kinds of issues.

Posted

Well if you're working directly with the encoder, then i would compare timestamps within segment files to that of what is generated by libx264. If the timestamps are not right then that will definitely cause those kinds of issues.

 

So i guess:

[segment @ 0x80814170] Timestamps are unset in a packet for stream 0. This is deprecated and will stop working in the future. Fix your code to set the timestamps properly
[segment @ 0x80814170] Encoder did not produce proper pts, making some up.

is the issue.

 

I get this warning also when transcoding to a mp4 file, but somehow there are no issues playing that file -- maybe having 1 file is ok for generating timestamps, but not multiple files?

Posted

HLS is just a little more complicated than streaming a single file so it's important that timestamps are set properly or there are going to be problems.

Posted (edited)

HLS is just a little more complicated than streaming a single file so it's important that timestamps are set properly or there are going to be problems.

 

So it looks like the encoder driver was not setting any timestamp on the encoded packets. A small kernel patch to just copy timestamps from the input packets, and now everything is working nicely! :)

(so it was not emby or ffmpeg :D)

 

So yeah, now exynos5422 arm boards can do hw transcoding with emby*! :)

 

* provided they use ffmpeg from https://github.com/mihailescu2m/FFmpeg/

Edited by memeka
  • 2 years later...
Posted

@@memeka

 

The upcoming Emby Server 4.2 will have h264_omx built-in for Raspberry Pi hardware encoding. Thanks guys.

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
×
×
  • Create New...