Project

General

Profile

Add new field to webui

Added by Stefan Dietzel 6 months ago

Hi,

at the moment I am trying to extend a little bit the VAAPI transcoding in TVHeadend.
The techical stuff about trancoding is no problem but I am a little bit struggling how to add a new field to the UI mask of "Codec profiles".

It is nessecary to add a few fields to make the quality of encoding more accurate (buffer size for example).

Can someone give me a hint how to add input fields to an existing mask and which src files are relevant for this?

Thx in advance.


Replies (29)

RE: Add new field to webui - Added by Stefan Dietzel 6 months ago

Thanks for this info.

My problem at the moment is that I do not find the file where the form fields are defined.

The only part I found was in file codec.js but there are only some values from the existing form read:

function genericCBRvsVBR(form) {
    function updateBitrate(cbr_f, vbr_f) {
        if (vbr_f.getValue() > 0) {
            cbr_f.setValue(0);
            cbr_f.setReadOnly(true);
        }
        else {
            cbr_f.setReadOnly(false);
        }
    }

    var cbr_field = form.findField('bit_rate');
    var vbr_field = form.findField('qp') || form.findField('crf') || form.findField('qscale');
    vbr_field.spinner.editable = false;
    updateBitrate(cbr_field, vbr_field);

    vbr_field.on('spin', function(spinner) {
        updateBitrate(cbr_field, spinner.field);
    });
}

I don't find the file or part where the fields are defined because there is no file where the Ext.create is called with the items area.
What I need to do is to add to this function something like var buffsize = form.findField('buff_size'); but this will only work if this form field exists.

Regards
Stefan

RE: Add new field to webui - Added by Dave Pickles 6 months ago

I am definitely not an expert here but it seems to me that the form is created from the output of api/codec/list and api/codec_profile/list (function tvheadend.codec.tab() in src/webui/static/app/codec.js). The API functions supplying this data are in src/api/api_codec.c, and I believe that they get their input from the class definitions. In your case codec_profile_vaapi_class{} in src/transcoding/codec/codecs/libs/vaapi.c might be the place to add extra fields.

I don't use transcoding so I can't experiment further. Good luck!

RE: Add new field to webui - Added by Stefan Dietzel 6 months ago

Thx this helped really much. It works and now I can do the rest.

RE: Add new field to webui - Added by Stefan Dietzel 5 months ago

Patch has been submitted with pull request # 1447.
Now vaapi transcoding can be configured mire precise.

Thx for the tip with the webui. It worked perfectly.

RE: Add new field to webui - Added by Kiril St. 5 months ago

Hello Stefan, do you have time to try adding "-vf" option in hevc_vaapi? Or maybe someone have idea where to add this option???
For exampe in spawn profile i have:
-vf 'format=nv12,hwupload,deinterlace_vaapi=rate=field

Any ideas are welcome!

The main problem is in this thread:

https://tvheadend.org/boards/5/topics/39632

RE: Add new field to webui - Added by Stefan Dietzel 5 months ago

Normally you don't need to set this vf parameters manually. Setting the transcoding options in TVH does in fact nothing else then create this parameters.

You can check under "Profile Settings" the option "Hardware acceleration" and under "Advanced Settings" you can choose "Pixel Format".

RE: Add new field to webui - Added by Stefan Dietzel 5 months ago

You can try the following change of the vaapi.c
I don't know if vf is really a libva parameter so please test it and it would be great that you post your expirience in this thread.
With this hack there should be an option for VF available under profile settings.

Don't add the quotation marks to this field. In your case the field should contain only format=nv12,hwupload,deinterlace_vaapi=rate=field

/*
 *  tvheadend - Codec Profiles
 *
 *  Copyright (C) 2016 Tvheadend
 *
 *  This program is free software: you can redistribute it and/or modify
 *  it under the terms of the GNU General Public License as published by
 *  the Free Software Foundation, either version 3 of the License, or
 *  (at your option) any later version.
 *
 *  This program is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *  GNU General Public License for more details.
 *
 *  You should have received a copy of the GNU General Public License
 *  along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */

#include "transcoding/codec/internals.h" 
#include <fcntl.h>
#include <sys/ioctl.h>

#define AV_DICT_SET_QP(d, v, a) \
    AV_DICT_SET_INT((d), "qp", (v) ? (v) : (a), AV_DICT_DONT_OVERWRITE)

/* vaapi ==================================================================== */

typedef struct {
    TVHVideoCodecProfile;
    int qp;
    int quality;
    double buff_factor;
    int rc_mode;
    int tier;
    char *advanced_options_vf;
} tvh_codec_profile_vaapi_t;

#if defined(__linux__)
#include <linux/types.h>
#include <asm/ioctl.h>
#else
#include <sys/ioccom.h>
#include <sys/types.h>
typedef size_t   __kernel_size_t;
#endif

typedef struct drm_version {
   int version_major;        /**< Major version */
   int version_minor;        /**< Minor version */
   int version_patchlevel;   /**< Patch level */
   __kernel_size_t name_len; /**< Length of name buffer */
   char *name;               /**< Name of driver */
   __kernel_size_t date_len; /**< Length of date buffer */
   char *date;               /**< User-space buffer to hold date */
   __kernel_size_t desc_len; /**< Length of desc buffer */
   char *desc;               /**< User-space buffer to hold desc */
} drm_version_t;

#define DRM_IOCTL_VERSION _IOWR('d', 0x00, struct drm_version)

static int
probe_vaapi_device(const char *device, char *name, size_t namelen)
{
    drm_version_t dv;
    char dname[128];
    int fd;

    if ((fd = open(device, O_RDWR)) < 0)
        return -1;
    memset(&dv, 0, sizeof(dv));
    memset(dname, 0, sizeof(dname));
    dv.name = dname;
    dv.name_len = sizeof(dname)-1;
    if (ioctl(fd, DRM_IOCTL_VERSION, &dv) < 0) {
        close(fd);
        return -1;
    }
    snprintf(name, namelen, "%s v%d.%d.%d (%s)",
             dv.name, dv.version_major, dv.version_minor,
             dv.version_patchlevel, device);
    close(fd);
    return 0;
}

static htsmsg_t *
tvh_codec_profile_vaapi_device_list(void *obj, const char *lang)
{
    static const char *renderD_fmt = "/dev/dri/renderD%d";
    static const char *card_fmt = "/dev/dri/card%d";
    htsmsg_t *result = htsmsg_create_list();
    char device[PATH_MAX];
    char name[128];
    int i, dev_num;

    for (i = 0; i < 32; i++) {
        dev_num = i + 128;
        snprintf(device, sizeof(device), renderD_fmt, dev_num);
        if (probe_vaapi_device(device, name, sizeof(name)) == 0)
            htsmsg_add_msg(result, NULL, htsmsg_create_key_val(device, name));
    }
    for (i = 0; i < 32; i++) {
        dev_num = i + 128;
        snprintf(device, sizeof(device), card_fmt, dev_num);
        if (probe_vaapi_device(device, name, sizeof(name)) == 0)
            htsmsg_add_msg(result, NULL, htsmsg_create_key_val(device, name));
    }
    return result;
}

static int
tvh_codec_profile_vaapi_open(tvh_codec_profile_vaapi_t *self,
                             AVDictionary **opts)
{
    // pix_fmt
    AV_DICT_SET_PIX_FMT(opts, self->pix_fmt, AV_PIX_FMT_VAAPI);
    return 0;
}

static const codec_profile_class_t codec_profile_vaapi_class = {
    {
        .ic_super      = (idclass_t *)&codec_profile_video_class,
        .ic_class      = "codec_profile_vaapi",
        .ic_caption    = N_("vaapi"),
        .ic_properties = (const property_t[]){
            {
                .type     = PT_STR,
                .id       = "device",
                .name     = N_("Device name"),
                .desc     = N_("Device name (e.g. /dev/dri/renderD129)."),
                .group    = 3,
                .off      = offsetof(tvh_codec_profile_vaapi_t, device),
                .list     = tvh_codec_profile_vaapi_device_list,
            },
            {
                .type     = PT_DBL,
                .id       = "bit_rate",
                .name     = N_("Bitrate (kb/s) (0=auto)"),
                .desc     = N_("Target bitrate."),
                .group    = 3,
                .get_opts = codec_profile_class_get_opts,
                .off      = offsetof(TVHCodecProfile, bit_rate),
                .def.d    = 0,
            },
            {
                .type     = PT_DBL,
                .id       = "buff_factor",
                .name     = N_("Buffer factor"),
                .desc     = N_("Size of transcoding buffer (buffer=bitrate*1000*factor). Good factor is 3."),
                .group    = 3,
                .get_opts = codec_profile_class_get_opts,
                .off      = offsetof(tvh_codec_profile_vaapi_t, buff_factor),
                .def.d    = 3,
            },
            {
                .type     = PT_INT,
                .id       = "rc_mode",
                .name     = N_("Rate control mode"),
                .desc     = N_("Set rate control mode (from 0 to 6).[0=auto 1=CQP 2=CBR 3=VBR 4=ICQ 5=QVBR 6=AVBR]"),
                .group    = 3,
                .get_opts = codec_profile_class_get_opts,
                .off      = offsetof(tvh_codec_profile_vaapi_t, rc_mode),
                .intextra = INTEXTRA_RANGE(0, 6, 0),
                .def.d    = 0,
            },
            {
                .type     = PT_INT,
                .id       = "qp",
                .name     = N_("Constant QP (0=auto)"),
                .group    = 3,
                .desc     = N_("Fixed QP of P frames [0-52]."),
                .get_opts = codec_profile_class_get_opts,
                .off      = offsetof(tvh_codec_profile_vaapi_t, qp),
                .intextra = INTEXTRA_RANGE(0, 52, 1),
                .def.i    = 0,
            },
            {
                .type     = PT_STR,
                .id       = "advanced_options_vf",
                .name     = N_("Options VF"),
                .desc     = N_("Advanced parameters for VF"),
                .group    = 3,
                .off      = offsetof(tvh_codec_profile_vaapi_t, advanced_options_vf),
            },
            {}
        }
    },
    .open = (codec_profile_open_meth)tvh_codec_profile_vaapi_open,
};

/* h264_vaapi =============================================================== */

static const AVProfile vaapi_h264_profiles[] = {
    { FF_PROFILE_H264_CONSTRAINED_BASELINE, "Constrained Baseline" },
    { FF_PROFILE_H264_MAIN,                 "Main" },
    { FF_PROFILE_H264_HIGH,                 "High" },
    { FF_PROFILE_UNKNOWN },
};

static int
tvh_codec_profile_vaapi_h264_open(tvh_codec_profile_vaapi_t *self,
                                  AVDictionary **opts)
{
    // bit_rate or qp
    if (self->bit_rate) {
        if (self->buff_factor <= 0) {
            self->buff_factor = 3;
        }
        AV_DICT_SET_BIT_RATE(opts, self->bit_rate);
        AV_DICT_SET_INT(opts, "maxrate", (self->bit_rate) * 1000, AV_DICT_DONT_OVERWRITE);
        AV_DICT_SET_INT(opts, "bufsize", ((self->bit_rate) * 1000) * self->buff_factor, AV_DICT_DONT_OVERWRITE);
        AV_DICT_SET(opts, "force_key_frames", "expr:gte(t,n_forced*3)", AV_DICT_DONT_OVERWRITE);
        AV_DICT_SET_INT(opts, "rc_mode", self->rc_mode, AV_DICT_DONT_OVERWRITE);
        if (sizeof(self->advanced_options_vf)>0) {
            AV_DICT_SET(opts, "vf", self->advanced_options_vf, AV_DICT_DONT_OVERWRITE);
        }
    }
    else {
        AV_DICT_SET_QP(opts, self->qp, 20);
    }
    AV_DICT_SET_INT(opts, "quality", self->quality, 0);
    return 0;
}

static const codec_profile_class_t codec_profile_vaapi_h264_class = {
    {
        .ic_super      = (idclass_t *)&codec_profile_vaapi_class,
        .ic_class      = "codec_profile_vaapi_h264",
        .ic_caption    = N_("vaapi_h264"),
        .ic_properties = (const property_t[]){
            {
                .type     = PT_INT,
                .id       = "quality",
                .name     = N_("Quality (0=auto)"),
                .desc     = N_("Set encode quality (trades off against speed, " 
                               "higher is faster) [0-8]."),
                .group    = 5,
                .opts     = PO_EXPERT,
                .get_opts = codec_profile_class_get_opts,
                .off      = offsetof(tvh_codec_profile_vaapi_t, quality),
                .intextra = INTEXTRA_RANGE(0, 8, 1),
                .def.i    = 0,
            },
            {}
        }
    },
    .open = (codec_profile_open_meth)tvh_codec_profile_vaapi_h264_open,
};

TVHVideoCodec tvh_codec_vaapi_h264 = {
    .name     = "h264_vaapi",
    .size     = sizeof(tvh_codec_profile_vaapi_t),
    .idclass  = &codec_profile_vaapi_h264_class,
    .profiles = vaapi_h264_profiles,
};

/* hevc_vaapi =============================================================== */

static const AVProfile vaapi_hevc_profiles[] = {
    { FF_PROFILE_HEVC_MAIN, "Main" },
    { FF_PROFILE_HEVC_MAIN_10, "Main 10" },
    { FF_PROFILE_HEVC_REXT, "Rext" },
    { FF_PROFILE_UNKNOWN },
};

static int
tvh_codec_profile_vaapi_hevc_open(tvh_codec_profile_vaapi_t *self,
                                  AVDictionary **opts)
{
    // bit_rate or qp
    if (self->bit_rate) {
        AV_DICT_SET_BIT_RATE(opts, self->bit_rate);
        if (self->buff_factor <= 0) {
            self->buff_factor = 3;
        }
        AV_DICT_SET_INT(opts, "maxrate", (self->bit_rate) * 1000, AV_DICT_DONT_OVERWRITE);
        AV_DICT_SET_INT(opts, "bufsize", ((self->bit_rate) * 1000) * self->buff_factor, AV_DICT_DONT_OVERWRITE);
        AV_DICT_SET(opts, "force_key_frames", "expr:gte(t,n_forced*3)", AV_DICT_DONT_OVERWRITE);
        AV_DICT_SET_INT(opts, "rc_mode", self->rc_mode, AV_DICT_DONT_OVERWRITE);
        AV_DICT_SET_INT(opts, "tier", self->tier, AV_DICT_DONT_OVERWRITE);
        if (sizeof(self->advanced_options_vf)>0) {
            AV_DICT_SET(opts, "vf", self->advanced_options_vf, AV_DICT_DONT_OVERWRITE);
        }
    }
    else {
        AV_DICT_SET_QP(opts, self->qp, 25);
    }
    return 0;
}

static const codec_profile_class_t codec_profile_vaapi_hevc_class = {
    {
        .ic_super      = (idclass_t *)&codec_profile_vaapi_class,
        .ic_class      = "codec_profile_vaapi_hevc",
        .ic_caption    = N_("vaapi_hevc"),
        .ic_properties = (const property_t[]){
            {
                .type     = PT_INT,
                .id       = "tier",
                .name     = N_("Tier"),
                .desc     = N_("Set tier (general_tier_flag) [0=main 1=high]"),
                .group    = 5,
                .opts     = PO_EXPERT,
                .get_opts = codec_profile_class_get_opts,
                .off      = offsetof(tvh_codec_profile_vaapi_t, tier),
                .intextra = INTEXTRA_RANGE(0, 1, 0),
                .def.i    = 0,
            },
            {}
        }
    },
    .open = (codec_profile_open_meth)tvh_codec_profile_vaapi_hevc_open,
};

TVHVideoCodec tvh_codec_vaapi_hevc = {
    .name     = "hevc_vaapi",
    .size     = sizeof(tvh_codec_profile_vaapi_t),
    .idclass  = &codec_profile_vaapi_hevc_class,
    .profiles = vaapi_hevc_profiles,
    .profile_init = tvh_codec_profile_video_init,
    .profile_destroy = tvh_codec_profile_video_destroy,
};

/* vp8_vaapi =============================================================== */

static const AVProfile vaapi_vp8_profiles[] = {
    { FF_PROFILE_UNKNOWN },
};

static int
tvh_codec_profile_vaapi_vp8_open(tvh_codec_profile_vaapi_t *self,
                                  AVDictionary **opts)
{
    // bit_rate or qp
    if (self->bit_rate) {
        AV_DICT_SET_BIT_RATE(opts, self->bit_rate);
    }
    else {
        AV_DICT_SET_QP(opts, self->qp, 25);
    }
    // force zero here, until encoder is fixed
    AV_DICT_SET_INT(opts, "bf", 0, 0);
    return 0;
}

static const codec_profile_class_t codec_profile_vaapi_vp8_class = {
    {
        .ic_super      = (idclass_t *)&codec_profile_vaapi_class,
        .ic_class      = "codec_profile_vaapi_vp8",
        .ic_caption    = N_("vaapi_vp8")
    },
    .open = (codec_profile_open_meth)tvh_codec_profile_vaapi_vp8_open,
};

TVHVideoCodec tvh_codec_vaapi_vp8 = {
    .name     = "vp8_vaapi",
    .size     = sizeof(tvh_codec_profile_vaapi_t),
    .idclass  = &codec_profile_vaapi_vp8_class,
    .profiles = vaapi_vp8_profiles,
    .profile_init = tvh_codec_profile_video_init,
    .profile_destroy = tvh_codec_profile_video_destroy,
};

/* vp9_vaapi =============================================================== */

static const AVProfile vaapi_vp9_profiles[] = {
    { FF_PROFILE_UNKNOWN },
};

static int
tvh_codec_profile_vaapi_vp9_open(tvh_codec_profile_vaapi_t *self,
                                  AVDictionary **opts)
{
    // bit_rate or qp
    if (self->bit_rate) {
        AV_DICT_SET_BIT_RATE(opts, self->bit_rate);
    }
    else {
        AV_DICT_SET_QP(opts, self->qp, 25);
    }
    // force zero here, until encoder is fixed
    AV_DICT_SET_INT(opts, "bf", 0, 0);
    return 0;
}

static const codec_profile_class_t codec_profile_vaapi_vp9_class = {
    {
        .ic_super      = (idclass_t *)&codec_profile_vaapi_class,
        .ic_class      = "codec_profile_vaapi_vp9",
        .ic_caption    = N_("vaapi_vp9")
    },
    .open = (codec_profile_open_meth)tvh_codec_profile_vaapi_vp9_open,
};

TVHVideoCodec tvh_codec_vaapi_vp9 = {
    .name     = "vp9_vaapi",
    .size     = sizeof(tvh_codec_profile_vaapi_t),
    .idclass  = &codec_profile_vaapi_vp9_class,
    .profiles = vaapi_vp9_profiles,
    .profile_init = tvh_codec_profile_video_init,
    .profile_destroy = tvh_codec_profile_video_destroy,
};

RE: Add new field to webui - Added by Kiril St. 5 months ago

The problem is somewhere else. Still no picture with hevc_vaapi profile. My goal is to try understand why tvheadend encoding not work with AMD GPU and mesa driver! I dont have NVIDIA or INTEL cpu to test! Spawn profile works fine:

/usr/bin/ffmpeg -vaapi_device /dev/dri/renderD128 -i pipe:0 -vf 'format=nv12,hwupload,deinterlace_vaapi=rate=field,scale_vaapi=w=1920:h=1080' -c:v hevc_vaapi -b:v 2200k -maxrate 2200k -bufsize 2M -c:s copy -c:a copy -f mpegts pipe:1

RE: Add new field to webui - Added by Stefan Dietzel 5 months ago

Hi,

maybe it has something to do with the integrated ffmpeg in TVH (i guess this version is older than the system ffmpeg you are calling in spawn).
I always disable static ffmpeg and use the ffmpeg from my distribution.
Can you try and compile it without static ffmpeg?

You will not need all but those are the parameters I use for compilation (it's the package autobuild but you can just grep the parameters you need to disable static ffmpeg):

AUTOBUILD_CONFIGURE_EXTRA="--enable-libav --disable-hdhomerun_client --disable-hdhomerun_static --disable-ffmpeg_static --disable-libffmpeg_static --enable-libx264 --enable-libx265 --enable-vaapi --enable-libfdkaac --disable-libx264_static --disable-libx265_static --disable-libfdkaac_static --disable-libvorbis_static --disable-libtheora_static --disable-libvpx_static --disable-libopus_static --enable-libav" ./Autobuild.sh -t debian

RE: Add new field to webui - Added by Jay O 5 months ago

I will be able to test this also (your vaapi.c file from above), and compare it with a spawn profile.

To help: do spawn profiles work with Kodi HTSP plugin, or only with VLC? I have not been able to get spawn profiles working in Kodi last time I tried (the HTSP plugin reports the streaming profile is not available).

RE: Add new field to webui - Added by Kiril St. 5 months ago

Jay O wrote:

I will be able to test this also (your vaapi.c file from above), and compare it with a spawn profile.

To help: do spawn profiles work with Kodi HTSP plugin, or only with VLC? I have not been able to get spawn profiles working in Kodi last time I tried (the HTSP plugin reports the streaming profile is not available).

Spawn works! Just install latest kodi and tvheadend addon, add both http and htsp ports, enable option in addon "use http for streaming" and channels are open with spawn profile!

RE: Add new field to webui - Added by Stefan Dietzel 5 months ago

Spawn's don't work with HTSP messages. They only work with HTTP/VLC.
If you have a spawn profile and want to use it in Kodi you have to use IPTV plugin (and M3U from TVH) instead of HTSP plugin.

Thats the reason why I added functionality to vaapi.c because this works on both HTPS and VLC.

My question was related to the newly requested -VF parameter part.
I don't know if parameters set to VF via libva are really used (because in official avconv for example those parameter is parsed and mapped directly to corresponding functions).

I am very sure the general problem of Kiri St. belongs to internal compiled ffmpeg version and they should be gone when using a newer version (non-static).

My question more or less is if this "Options VF" works and makes sence of if it's better to remove it before creating a pull request for the project.

RE: Add new field to webui - Added by Jay O 5 months ago

Kiril St. wrote:

Jay O wrote:

I will be able to test this also (your vaapi.c file from above), and compare it with a spawn profile.

To help: do spawn profiles work with Kodi HTSP plugin, or only with VLC? I have not been able to get spawn profiles working in Kodi last time I tried (the HTSP plugin reports the streaming profile is not available).

Spawn works! Just install latest kodi and tvheadend addon, add both http and htsp ports, enable option in addon "use http for streaming" and channels are open with spawn profile!

Thanks, I had missed the "Use HTTP for streaming option".

I'll be building Stefan's modified vaapi later today.

RE: Add new field to webui - Added by Kiril St. 5 months ago

Stefan Dietzel wrote:

Spawn's don't work with HTSP messages. They only work with HTTP/VLC.
If you have a spawn profile and want to use it in Kodi you have to use IPTV plugin (and M3U from TVH) instead of HTSP plugin.

Thats the reason why I added functionality to vaapi.c because this works on both HTPS and VLC.

My question was related to the newly requested -VF parameter part.
I don't know if parameters set to VF via libva are really used (because in official avconv for example those parameter is parsed and mapped directly to corresponding functions).

I am very sure the general problem of Kiri St. belongs to internal compiled ffmpeg version and they should be gone when using a newer version (non-static).

My question more or less is if this "Options VF" works and makes sence of if it's better to remove it before creating a pull request for the project.

Stefan, thanks once again for trying to help! Ignore this -vf parameter. It does not change anything! I will continue to investigate and report if anything is found! Report github pull request without this change!

RE: Add new field to webui - Added by Jay O 5 months ago

Stefan Dietzel wrote:

Spawn's don't work with HTSP messages. They only work with HTTP/VLC.
If you have a spawn profile and want to use it in Kodi you have to use IPTV plugin (and M3U from TVH) instead of HTSP plugin.

Thats the reason why I added functionality to vaapi.c because this works on both HTPS and VLC.

My question was related to the newly requested -VF parameter part.
I don't know if parameters set to VF via libva are really used (because in official avconv for example those parameter is parsed and mapped directly to corresponding functions).

I am very sure the general problem of Kiri St. belongs to internal compiled ffmpeg version and they should be gone when using a newer version (non-static).

My question more or less is if this "Options VF" works and makes sence of if it's better to remove it before creating a pull request for the project.

Hi Stefan,

Your modified vaapi builds OK here and I see the "Options VF" field. I'm trying to find a video filter to apply here which would be clear for me to see on the output. I tried "scale=512:384" so that I could see the SD quality instead of HD, but I'm not sure if the "Height (pixels) (0=no scaling)" being set to 0 is somehow over-writing this. The colour space conversions and deinterlace type ones won't be clear to see if it's working or not.

I'm trying to find a basic video filter that would show it working. I tried rotate=180/PI*180 (https://ffmpeg.org/ffmpeg-filters.html#rotate ) to flip the video, but it didn't work. I didn't see any related errors in the debug log.

It could be very useful to have "Options VF" as an "expert" field to give people control for all kinds of filters in TVH, if it works.

RE: Add new field to webui - Added by saen acro 5 months ago

If some can modify build-in FFMpeg as this one
https://github.com/markus-perl/ffmpeg-build-script
to include AMF not only VAAPI for AMD

RE: Add new field to webui - Added by Stefan Dietzel 5 months ago

Their seems to exist some problems with AMD vaapi: https://gist.github.com/Brainiarc7/95c9338a737aa36d9bb2931bed379219

Note that with AMD hardware, we generally disable B-Frame support as newer SKUs such as the RX 460/470/480 and their rebrands (Polaris-based) do not support B-Frames in H.264 encoding.

This means I cannot remove this b frame fix and need to make it selectable if it should be applied.

RE: Add new field to webui - Added by Stefan Dietzel 5 months ago

I added an ignore b-frame option to vaapi and also updated VP8 and VP9 encoding.

Tomorrow I will create a pull request for this change. It would be good if someone can test the attached vaapi.c
Maybe this b-frame option also helps for AMD.

VP8 and VP9 now also reacts on options for "Buffer factor" and "Ignore B-Frames" and got the "force_key_frames" expression to increase picture quality.

vaapi.c (14.5 KB) vaapi.c

RE: Add new field to webui - Added by Jay O 5 months ago

Stefan Dietzel wrote:

I added an ignore b-frame option to vaapi and also updated VP8 and VP9 encoding.

Tomorrow I will create a pull request for this change. It would be good if someone can test the attached vaapi.c
Maybe this b-frame option also helps for AMD.

VP8 and VP9 now also reacts on options for "Buffer factor" and "Ignore B-Frames" and got the "force_key_frames" expression to increase picture quality.

Will test over the next few days. Building and testing on Intel Atom, where VAAPI is essential.

RE: Add new field to webui - Added by Jay O 5 months ago

I've been testing with H264 on an Intel Atom SBC, there seems to be a memory leak issue with VAAPI.

When I start a channel on the client, I see an extra 100MB or so of RAM used on the TVH server. This does not get released when I stop playback. When I start another channel, another 100MB of RAM is used up on top of the original uncleared 100MB. It builds every time a new channel is played until all system RAM (700MB is all I have + 1GB swap) is used up.

Is there a .profile_destroy = tvh_codec_profile_video_destroy, missing in the h264 section below (from your code above)? It's there for the other codecs.

TVHVideoCodec tvh_codec_vaapi_h264 = {
    .name     = "h264_vaapi",
    .size     = sizeof(tvh_codec_profile_vaapi_t),
    .idclass  = &codec_profile_vaapi_h264_class,
    .profiles = vaapi_h264_profiles,
};

RE: Add new field to webui - Added by Kiril St. 5 months ago

Apply fix from this thread: https://tvheadend.org/boards/5/topics/43530?r=44328#message-44328 in /src/profile.c
For now I dont have any other solution!

RE: Add new field to webui - Added by Stefan Dietzel 5 months ago

Hi,

I added the destroy to h264.
Please check this again and thank you for testing.

vaapi.c (14.7 KB) vaapi.c

RE: Add new field to webui - Added by Jay O 5 months ago

Hi Stefan,

I made a new build with the h264 destroy, but this memleak issue remains.

At the weekend I'll be able to test it on another Intel machine.

Kiril, I didn't try that patch you link in the other thread, that seems to be about NVENC, not Intel? Does it affect both?

RE: Add new field to webui - Added by Kiril St. 5 months ago

Jay O wrote:

Hi Stefan,

I made a new build with the h264 destroy, but this memleak issue remains.

At the weekend I'll be able to test it on another Intel machine.

Kiril, I didn't try that patch you link in the other thread, that seems to be about NVENC, not Intel? Does it affect both?

Yes, affect both vaapi and nvenc!

(1-25/29)