UPnP / DLNA Media Server for MediaPortal 2 (6 Viewers)

MJGraf

Retired Team Member
  • Premium Supporter
  • January 13, 2006
    2,478
    1,385
    @FreakyJ
    Thanks for asking - and sorry for only a short answer as I don't have much time currently...

    First of all, I think "ImpersonationService.ExecuteWithResourceAccessAsync" is more similar to what you Need than "ProcessUtils.TryExecuteAsync". The first one supports impersonation, which may be necessary if you want ffmpeg to transcode a video that is accessible through a NetoworkNeighborhoofResourceAccessor pointing to e.g. a NAS for which you need credentials to access it. The code of these two is nearly identical - except for the impersonation.

    The reasons why it is a bit "hacky" are mainly two:
    • The Process class doesn't support starting a process with different credentials. To be able to do so at all, we need to use reflection.
    • The Process class often leads to dead-locks when you want to read the standard-output and -error streams.
    As to aborting the process, we currently only have a timeout value that terminates the process automatically when the timeout is reached. Following the TAP pattern I could well imagine that we have an overload of the method that accepts a CancellationToken instead of a timeout. That way you can terminate the process via the CancellationToken. I could even imagine that we move the main part of the code to the method with the CancellationToken parameter and let the overload with the timeout just call the first one with a cancellationToken that cancels automatically when the timeout is reached.

    As to your second question, this seems more complicated. What these methods currently do is they return a task that completes, when the Process is finished (i.e. exited automatically or terminated after the timeout). Then they return a ProcessExcutionResult that contains anything that was written to stdout and stderr during executing the process (in form of strings).
    What you need seems to be a way to read stdout WHILE the process is running. And this is not what these classes and methods were meant for...
    I'll think about that one a bit - maybe I have some more ideas...
     

    henso

    Development Group
  • Team MediaPortal
  • February 16, 2012
    2,341
    829
    Home Country
    Denmark Denmark
    I am trying to port the MPExtended StreamingService.
    If I understand you right you want to create a service similar to the FanArtService just for transcoded streams instead? So you could make requests like:
    Code:
    /TranscodeService/[GUID]?container=MKV&vcodec=H264&acodec=MP3
    and then you would get the stream for that. In the DLAN response we could then just pass a link to the transcoding service for the particular media item. If that's the plan I think it's a good idea! Or am I misunderstanding something?
    Because our Webserver doesn't handle Multithreading
    I have been playing a little with the HttpServer but to me it seems it running the requests asynchronously, so I don't see why one request should block another. I also made a little test program that sends multiple requests in parallel to a http test module with a 500ms delay. After a fresh start the response time is around 2 seconds (because of .NET precompiling?), but a few seconds later the average response time is around 500ms at around 100 requests/second. If the HttpServer is not multithreaded should the average response time not be higher?
     

    FreakyJ

    Retired Team Member
  • Premium Supporter
  • July 25, 2010
    4,024
    1,420
    Home Country
    Germany Germany
    Thanks for asking - and sorry for only a short answer as I don't have much time currently...
    No problem! I am happy about every answer :)

    First of all, I think "ImpersonationService.ExecuteWithResourceAccessAsync" is more similar to what you Need than "ProcessUtils.TryExecuteAsync".
    Thanks to your detailed explanations during the importer rework I know that and I am using this function :) But the ProcessUtils.TryExecuteAsync function is the underlaying problem^^ But I guess you know that :p

    I could well imagine that we have an overload of the method that accepts a CancellationToken instead of a timeout.
    That would be fine for me, I would feel more comfortable if you could do the changes, somehow I am afraid to screw it up :(

    What you need seems to be a way to read stdout WHILE the process is running. And this is not what these classes and methods were meant for...
    I'll think about that one a bit - maybe I have some more ideas...
    Thank you very much. I am looking forward to hear back from you :)

    But no rush, it is working right now and there is a todo in the code so that I won't forget :)
     

    FreakyJ

    Retired Team Member
  • Premium Supporter
  • July 25, 2010
    4,024
    1,420
    Home Country
    Germany Germany
    If I understand you right you want to create a service similar to the FanArtService just for transcoded streams instead? So you could make requests like:
    Yes you understood me correct, but I changed my mind again. :whistle: I was in the middle of the porting process and than I realized that this code isn't better than the code we already have.(y)
    So I decided to split your code in smaller peaces so that it is easier to understand what is happening. Also I am trying to separate the FFMpeg specific parts from the rest. You already have an option to choose from transcoders (kind of: TranscoderBinPath), so maybe we will add other transcoders in the future and it would be much easier if the FFMpeg code is already spitted from the rest.
    I hope you are comfortable with this. I really like your work and feel a bit sorry that I am messing around there so much.

    I have been playing a little with the HttpServer but to me it seems it running the requests asynchronously, so I don't see why one request should block another.
    That is really create(y) Thank you!
    I think you should try something else: You start to transfer a file and than send another request and see if you get an answer. Do you know what I mean?

    I made some small changes to analyzer interface. Hope it's OK with you. ;)
    Looking good to me :)

    I am heavily working on the MediaConverter.cs file. Just for your information^^ I will push as soon as it is compiling again.

    Another point:
    I limited the video bitrate in the default profile so the filesize is now around 2GB instead of 12 GB (for a 50 min Episode). But the quality isn't the best anymore :(
    I think this is due to the ultrafastpreset I am using. Have to do some further testing.

    Another problem I've found:
    While ffmpeg is still transcoding you can't seek. But I couldn't come up with a solution yet... I did some reading but I really don't know how to tackle this. Do you have an idea?
     

    henso

    Development Group
  • Team MediaPortal
  • February 16, 2012
    2,341
    829
    Home Country
    Denmark Denmark
    Good to hear from you! ;)

    Yes you understood me correct, but I changed my mind again.
    I was also thinking about how this would be possible with all the DLNA specific headers and such.

    Also I am trying to separate the FFMpeg specific parts from the rest.
    My initial idea was also to have support for different transcoder binaries just like MPExtended. The VLC transcoder never really worked for me though (heavy pixilated video) so I settled on the ffmpeg binaries instead.

    You already have an option to choose from transcoders
    TranscoderBinPath and TranscoderArguments were meant for user to experiment with other transcoders and/or transcoder arguments. {input}, {subtitle} and {output} are placeholders that could be used in the argument string to be replaces by the actual values. I was aiming for the community to create new DLNA device profiles, just like Serviio does.

    I really like your work and feel a bit sorry that I am messing around there so much.
    Don't think about it. It's no issue for me. I will look you a bit over the shoulders though, to check if you remove something I think is important. :p

    You start to transfer a file and than send another request and see if you get an answer. Do you know what I mean?
    I know what you mean. I will try that when I find time.

    I am heavily working on the MediaConverter.cs file.
    I will try to minimize my changes to that file, to minimize you merge burden. Actually I was confronted with you changes at my last sync and the merge dialog made no sense to me. It also appeared as if I had changed almost everything in the solution and had to commit a lot of changes somebody made. I ended up cloning the repository, merging my changes with WinMerge and then commiting. Any merging tips for Git noob?

    2GB instead of 12 GB (for a 50 min Episode).
    What type of source media were you using?

    Do you have an idea?
    The DLNA.ORG_FLAGS specifies seeking capabilities, maybe that's your problem? See DlnaForthField.cs.

    On a side note I tried compiling a ffmpeg version with QuickSync and NVENC support and succeeded. My development machine only supports NVENC for a H264 codec (no QuickSync). So I played a little with that. Seems NVENC is a little more picky about encoding parameters than SW encoding is but the speed was good and quality wise I saw no big difference. But it was a small sample so this does not really say anything about the quality.
     

    FreakyJ

    Retired Team Member
  • Premium Supporter
  • July 25, 2010
    4,024
    1,420
    Home Country
    Germany Germany
    My initial idea was also to have support for different transcoder binaries just like MPExtended. The VLC transcoder never really worked for me though (heavy pixilated video) so I settled on the ffmpeg binaries instead.
    fair enough :) But I think we agree that it would still be nice to have support for different encoders regardless if it vlc, ffmpeg or something complete different^^

    I will try to minimize my changes to that file, to minimize you merge burden.
    I had to kind off reapply your changes made here: https://github.com/MediaPortal/MediaPortal-2/commit/ee0f62351087b87c36d48827addd678ae0e70876
    I hope I haven't screwed anything up, but it seems like it is still working^^

    It also appeared as if I had changed almost everything in the solution and had to commit a lot of changes somebody made.
    It happened to me, too. :) Suddenly a .git*something* file popped off in the repo which wasn't in the version control. It was responsible for changing the new lines somehow. I just deleted that file and than everything was fine again :)

    What type of source media were you using?
    Allgemein
    UniqueID/String : 174704328384445386652477233632116214006 (0x836ED46A2A86D5B0BF34B04C9A1808F6)
    Vollständiger Name : O:\Serien\Covert Affairs\Staffel 01\Covert Affairs - 1x01 - Pilot.mkv
    Format : Matroska
    Format-Version : Version 2
    Dateigröße : 2,79 GiB
    Dauer : 1h 20min
    Gesamte Bitrate : 4 976 Kbps
    Kodierungs-Datum : UTC 2011-09-14 00:25:55
    Kodierendes Programm : mkvmerge v4.4.0 ('Die Wiederkehr') gebaut am Oct 31 2010 21:52:48
    verwendete Encoder-Bibliothek : libebml v1.0.0 + libmatroska v1.0.0

    Video
    ID : 1
    Format : AVC
    Format/Info : Advanced Video Codec
    Format-Profil : High@L3.1
    Format-Einstellungen für CABAC : Nein
    Format-Einstellungen für ReFrames : 2 frames
    Codec-ID : V_MPEG4/ISO/AVC
    Dauer : 1h 20min
    Bitrate : 4 045 Kbps
    Breite : 1 280 Pixel
    Höhe : 720 Pixel
    Bildseitenverhältnis : 16:9
    Modus der Bildwiederholungsrate : konstant
    Bildwiederholungsrate : 23,976 FPS
    ColorSpace : YUV
    ChromaSubsampling : 4:2:0
    BitDepth/String : 8 bits
    Scantyp : progressiv
    Bits/(Pixel*Frame) : 0.183
    Stream-Größe : 2,27 GiB (81%)
    Default : Ja
    Forced : Nein
    colour_range : Limited
    colour_primaries : BT.709
    transfer_characteristics : BT.709
    matrix_coefficients : BT.709

    Audio #1
    ID : 2
    Format : AC-3
    Format/Info : Audio Coding 3
    Format_Settings_ModeExtension : CM (complete main)
    Format-Einstellungen für Endianess : Big
    Codec-ID : A_AC3
    Dauer : 1h 20min
    Bitraten-Modus : konstant
    Bitrate : 448 Kbps
    Kanäle : 6 Kanäle
    Kanal-Positionen : Front: L C R, Side: L R, LFE
    Samplingrate : 48,0 KHz
    Stream-Größe : 257 MiB (9%)
    Sprache : Deutsch
    Default : Ja
    Forced : Nein

    Audio #2
    ID : 3
    Format : AC-3
    Format/Info : Audio Coding 3
    Format_Settings_ModeExtension : CM (complete main)
    Format-Einstellungen für Endianess : Big
    Codec-ID : A_AC3
    Dauer : 1h 20min
    Bitraten-Modus : konstant
    Bitrate : 384 Kbps
    Kanäle : 2 Kanäle
    Kanal-Positionen : Front: L R
    Samplingrate : 48,0 KHz
    Stream-Größe : 220 MiB (8%)
    Sprache : Englisch
    Default : Nein
    Forced : Nein

    The DLNA.ORG_FLAGS specifies seeking capabilities, maybe that's your problem? See DlnaForthField.cs.
    I don't really know, you can reproduce the problem by adding this to the default profile:
    Code:
    <VideoTarget container="Mpeg2Ts" videoCodec="H264" videoMaxBitrate="4000" audioCodec="Aac" forceTranscoding="true">
            <VideoSource />
          </VideoTarget>
    You can see the complete duration, but you can't seek (at least in WMP). If you use matroska instead of Mpeg2Ts you don't even get the duration (even when the file is completely transcoded). I know that mkv stores the duration at the end like mp4.

    On a side note I tried compiling a ffmpeg version with QuickSync and NVENC support and succeeded.
    Really nice work! Sadly I use a AMD CPU and never bothered updating my graphics card, because I don't play games^^ A GTS450 is enough for the WIndows Desktop :ROFLMAO:

    Also I've pushed my changes. I'm not completely finished, but i wanted to push to reduce merge conflicts in case you want to change also some parts in this area.
    And any comments are welcome. :)
     

    morpheus_xx

    Retired Team Member
  • Team MediaPortal
  • March 24, 2007
    12,073
    7,459
    Home Country
    Germany Germany
    @henso and @FreakyJ , nice to see the good progress on this plugin (y).

    I have some ideas regarding the many "if / else" code blocks for constructing ffmpeg arguments. One example: https://github.com/MediaPortal/Medi...scoders/FFMpeg/FFMpegCommandline.cs#L426-L441, where there are too many checks.

    I'd suppose to reduce the lines of code and putting more configuration options into dictionaries like:
    C#:
      Dictionary<EncodingPreset, string> SWEncodingPresets = new Dictionary<EncodingPreset, string>
      {
      { EncodingPreset.Ultrafast, "-preset ultrafast" },
      { EncodingPreset.Superfast, "-preset superfast" }
      };
      Dictionary<EncodingPreset, string> IntelEncodingPresets = new Dictionary<EncodingPreset, string>
      {
      { EncodingPreset.Ultrafast, "-preset ultrafast" },
      { EncodingPreset.Superfast, "-preset superfast" }
      };
      Dictionary<EncodingPreset, string> NVidiaEncodingPresets = new Dictionary<EncodingPreset, string>
      {
      { EncodingPreset.Ultrafast, "-preset ultrafast" },
      { EncodingPreset.Superfast, "-preset superfast" }
      };

    Then you have choose the matching dict only once and use a .TryGet() to translate the presets to string args in one line. If you apply this to the other arguments as well, the number of code lines will be significantly reduced. It would also allow moving out the mappings into settings, what would allow easier extension without adding more code lines.

    I have not checked other parts, but I hope you can apply some of those refactorings :)
     

    FreakyJ

    Retired Team Member
  • Premium Supporter
  • July 25, 2010
    4,024
    1,420
    Home Country
    Germany Germany
    Sure! I will try to do this during this week :) Your input as a real developer is really appreciated!
     

    morpheus_xx

    Retired Team Member
  • Team MediaPortal
  • March 24, 2007
    12,073
    7,459
    Home Country
    Germany Germany
    To go even a step further: there could be a base class with all common code (the sw based). Then other derived classes for the 2 hw accelerated modes. :)
     

    Users who are viewing this thread

    Top Bottom