Quellcodebibliothek Statistik Leitseite products/Sources/formale Sprachen/C/VLC/src/misc/   (VLC Media Plyer ©)  Datei vom 23.9.2026 mit Größe 25 kB image not shown  

Quelle  image.c   Sprache: C

 

/*****************************************************************************
 * image.c : wrapper for image reading/writing facilities
 *****************************************************************************
 * Copyright (C) 2004-2007 VLC authors and VideoLAN
 *
 * Author: Gildas Bazin <gbazin@videolan.org>
 *
 * This program is free software; you can redistribute it and/or modify it
 * under the terms of the GNU Lesser General Public License as published by
 * the Free Software Foundation; either version 2.1 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 Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public License
 * along with this program; if not, write to the Free Software Foundation,
 * Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
 *****************************************************************************/


/**
 * \file
 * This file contains the functions to handle the image_handler_t type
 */


/*****************************************************************************
 * Preamble
 *****************************************************************************/


#ifdef HAVE_CONFIG_H
# include "config.h"
#endif

#include <errno.h>
#include <limits.h>

#include <vlc_common.h>
#include <vlc_codec.h>
#include <vlc_meta.h>
#include <vlc_filter.h>
#include <vlc_es.h>
#include <vlc_image.h>
#include <vlc_stream.h>
#include <vlc_fs.h>
#include <vlc_sout.h>
#include "../libvlc.h"
#include <vlc_modules.h>

struct decoder_owner
{
    decoder_t dec;
    es_format_t fmt_in;
    image_handler_t *p_image;
};

static inline struct decoder_owner *dec_get_owner( decoder_t *p_dec )
{
    return container_of( p_dec, struct decoder_owner, dec );
}

static picture_t *ImageRead( image_handler_t *, block_t *,
                             const es_format_t *,
                             video_format_t * );
static picture_t *ImageReadUrl( image_handler_t *, const char *,
                                video_format_t * );
static block_t *ImageWrite( image_handler_t *, picture_t *,
                            const video_format_t *,
                            vlc_fourcc_t, const video_format_t * );
static int ImageWriteUrl( image_handler_t *, picture_t *,
                          const video_format_t *,
                          vlc_fourcc_t, const video_format_t *,
                          const char * );

static picture_t *ImageConvert( image_handler_t *, picture_t *,
                                const video_format_t *, video_format_t * );

static decoder_t *CreateDecoder( image_handler_t *, const es_format_t * );
static encoder_t *CreateEncoder( vlc_object_t *, const video_format_t *,
                                 vlc_fourcc_t, const video_format_t * );
static filter_t *CreateConverter( vlc_object_t *, const es_format_t *,
                                  struct vlc_video_context *,
                                  const video_format_t * );
static void DeleteConverter( filter_t * );

vlc_fourcc_t image_Type2Fourcc( const char * );
vlc_fourcc_t image_Ext2Fourcc( const char * );
/*static const char *Fourcc2Ext( vlc_fourcc_t );*/

#undef image_HandlerCreate
/**
 * Create an image_handler_t instance
 *
 */

image_handler_t *image_HandlerCreate( vlc_object_t *p_this )
{
    image_handler_t *p_image = calloc( 1, sizeof(image_handler_t) );
    if( !p_image )
        return NULL;

    p_image->p_parent = p_this;

    p_image->pf_read = ImageRead;
    p_image->pf_read_url = ImageReadUrl;
    p_image->pf_write = ImageWrite;
    p_image->pf_write_url = ImageWriteUrl;
    p_image->pf_convert = ImageConvert;

    p_image->outfifo = picture_fifo_New();

    return p_image;
}

/**
 * Delete the image_handler_t instance
 *
 */

void image_HandlerDelete( image_handler_t *p_image )
{
    if( !p_image ) return;

    if( p_image->p_dec != NULL )
    {
        struct decoder_owner *p_owner = dec_get_owner( p_image->p_dec );
        decoder_Clean( p_image->p_dec );
        es_format_Clean( &p_owner->fmt_in );
        vlc_object_delete( p_image->p_dec );
    }
    if( p_image->p_enc )
        vlc_encoder_Destroy( p_image->p_enc );
    if( p_image->p_converter ) DeleteConverter( p_image->p_converter );

    picture_fifo_Delete( p_image->outfifo );

    free( p_image );
    p_image = NULL;
}

/**
 * Read an image
 *
 */


static void ImageQueueVideo( decoder_t *p_dec, picture_t *p_pic )
{
    struct decoder_owner *p_owner = dec_get_owner( p_dec );
    picture_fifo_Lock( p_owner->p_image->outfifo );
    picture_fifo_Push( p_owner->p_image->outfifo, p_pic );
    picture_fifo_Unlock( p_owner->p_image->outfifo );
}

static picture_t *ImageRead( image_handler_t *p_image, block_t *p_block,
                             const es_format_t *p_es_in,
                             video_format_t *p_fmt_out )
{
    picture_t *p_pic = NULL;

    if ( p_es_in->i_cat != VIDEO_ES )
    {
        block_Release(p_block);
        return NULL;
    }

    /* Check if we can reuse the current decoder */
    if( p_image->p_dec &&
        p_image->p_dec->fmt_in->i_codec != p_es_in->video.i_chroma )
    {
        struct decoder_owner *p_owner = dec_get_owner( p_image->p_dec );
        decoder_Clean( p_image->p_dec );
        es_format_Clean( &p_owner->fmt_in );
        vlc_object_delete( p_image->p_dec );
        p_image->p_dec = NULL;
    }

    /* Start a decoder */
    if( !p_image->p_dec )
    {
        p_image->p_dec = CreateDecoder( p_image, p_es_in );
        if( !p_image->p_dec )
        {
            block_Release(p_block);
            return NULL;
        }
        if( p_image->p_dec->fmt_out.i_cat != VIDEO_ES )
        {
            struct decoder_owner *p_owner = dec_get_owner( p_image->p_dec );
            decoder_Clean( p_image->p_dec );
            es_format_Clean( &p_owner->fmt_in );
            vlc_object_delete( p_image->p_dec );
            p_image->p_dec = NULL;
            block_Release(p_block);
            return NULL;
        }
    }

    p_block->i_pts = p_block->i_dts = vlc_tick_now();
    int ret = p_image->p_dec->pf_decode( p_image->p_dec, p_block );
    if( ret == VLCDEC_SUCCESS )
    {
        /* Drain */
        p_image->p_dec->pf_decode( p_image->p_dec, NULL );

        picture_fifo_Lock( p_image->outfifo );
        p_pic = picture_fifo_Pop( p_image->outfifo );

        unsigned lostcount = 0;
        picture_t *lostpic;
        while( ( lostpic = picture_fifo_Pop( p_image->outfifo ) ) != NULL )
        {
            picture_Release( lostpic );
            lostcount++;
        }
        picture_fifo_Unlock( p_image->outfifo );

        if( lostcount > 0 )
            msg_Warn( p_image->p_parent, "Image decoder output more than one "
                      "picture (%u)", lostcount );
    }

    if( p_pic == NULL )
    {
        msg_Warn( p_image->p_parent, "no image decoded" );
        return 0;
    }

    if( !p_fmt_out->i_chroma )
        p_fmt_out->i_chroma = p_image->p_dec->fmt_out.video.i_chroma;
    if( !p_fmt_out->i_width && p_fmt_out->i_height )
        p_fmt_out->i_width = (int64_t)p_image->p_dec->fmt_out.video.i_width *
                             p_image->p_dec->fmt_out.video.i_sar_num *
                             p_fmt_out->i_height /
                             p_image->p_dec->fmt_out.video.i_height /
                             p_image->p_dec->fmt_out.video.i_sar_den;

    if( !p_fmt_out->i_height && p_fmt_out->i_width )
        p_fmt_out->i_height = (int64_t)p_image->p_dec->fmt_out.video.i_height *
                              p_image->p_dec->fmt_out.video.i_sar_den *
                              p_fmt_out->i_width /
                              p_image->p_dec->fmt_out.video.i_width /
                              p_image->p_dec->fmt_out.video.i_sar_num;
    if( !p_fmt_out->i_width )
        p_fmt_out->i_width = p_image->p_dec->fmt_out.video.i_width;
    if( !p_fmt_out->i_height )
        p_fmt_out->i_height = p_image->p_dec->fmt_out.video.i_height;
    if( !p_fmt_out->i_visible_width )
        p_fmt_out->i_visible_width = p_fmt_out->i_width;
    if( !p_fmt_out->i_visible_height )
        p_fmt_out->i_visible_height = p_fmt_out->i_height;
    if( p_fmt_out->transfer == TRANSFER_FUNC_UNDEF )
        p_fmt_out->transfer = p_image->p_dec->fmt_out.video.transfer;
    if( p_fmt_out->primaries == COLOR_PRIMARIES_UNDEF )
        p_fmt_out->primaries = p_image->p_dec->fmt_out.video.primaries;
    if( p_fmt_out->space == COLOR_SPACE_UNDEF )
        p_fmt_out->space = p_image->p_dec->fmt_out.video.space;

    /* Check if we need chroma conversion or resizing */
    if( !video_format_IsSameChroma( &p_image->p_dec->fmt_out.video, p_fmt_out ) ||
        p_image->p_dec->fmt_out.video.i_width != p_fmt_out->i_width ||
        p_image->p_dec->fmt_out.video.i_height != p_fmt_out->i_height )
    {
        if( p_image->p_converter &&
            ( !video_format_IsSameChroma( &p_image->p_converter->fmt_in.video,
                                          &p_image->p_dec->fmt_out.video ) ||
              !video_format_IsSameChroma( &p_image->p_converter->fmt_out.video, p_fmt_out ) ) )
        {
            /* We need to restart a new filter */
            DeleteConverter( p_image->p_converter );
            p_image->p_converter = NULL;
        }

        /* Start a filter */
        if( !p_image->p_converter )
        {
            p_image->p_converter =
                CreateConverter( p_image->p_parent, &p_image->p_dec->fmt_out,
                                 picture_GetVideoContext(p_pic), p_fmt_out );

            if( !p_image->p_converter )
            {
                picture_Release( p_pic );
                return NULL;
            }
        }
        else
        {
            /* Filters should handle on-the-fly size changes */
            es_format_Clean( &p_image->p_converter->fmt_in );
            es_format_Copy( &p_image->p_converter->fmt_in, &p_image->p_dec->fmt_out );
            video_format_Clean( &p_image->p_converter->fmt_out.video );
            video_format_Copy( &p_image->p_converter->fmt_out.video, p_fmt_out);
        }

        p_pic = p_image->p_converter->ops->filter_video( p_image->p_converter, p_pic );
        assert(p_pic == NULL || !picture_HasChainedPics(p_pic)); // no chaining
    }
    else
    {
        video_format_Clean( p_fmt_out );
        video_format_Copy( p_fmt_out, &p_image->p_dec->fmt_out.video );
    }

    return p_pic;
}

static picture_t *ImageReadUrl( image_handler_t *p_image, const char *psz_url,
                                video_format_t *p_fmt_out )
{
    block_t *p_block;
    picture_t *p_pic;
    stream_t *p_stream = NULL;
    uint64_t i_size;

    p_stream = vlc_stream_NewURL( p_image->p_parent, psz_url );

    if( !p_stream )
    {
        msg_Dbg( p_image->p_parent, "could not open %s for reading",
                 psz_url );
        return NULL;
    }

    if( vlc_stream_GetSize( p_stream, &i_size ) || i_size > SSIZE_MAX )
    {
        msg_Dbg( p_image->p_parent, "could not read %s", psz_url );
        goto error;
    }

    p_block = vlc_stream_Block( p_stream, i_size );
    if( p_block == NULL )
        goto error;

    vlc_fourcc_t i_chroma = 0;
    char *psz_mime = stream_MimeType( p_stream );
    if( psz_mime != NULL )
    {
        i_chroma = image_Mime2Fourcc( psz_mime );
        free( psz_mime );
    }
    if( !i_chroma )
    {
       /* Try to guess format from file name */
       i_chroma = image_Ext2Fourcc( psz_url );
    }
    vlc_stream_Delete( p_stream );


    es_format_t fmtin;
    es_format_Init( &fmtin, VIDEO_ES, i_chroma );
    p_pic = ImageRead( p_image, p_block, &fmtin, p_fmt_out );

    es_format_Clean( &fmtin );

    return p_pic;
error:
    vlc_stream_Delete( p_stream );
    return NULL;
}

/**
 * Write an image
 *
 */


static block_t *ImageWrite( image_handler_t *p_image, picture_t *p_pic,
                            const video_format_t *p_fmt_in,
                            vlc_fourcc_t codec, const video_format_t *p_fmt_out )
{
    /* Check if we can reuse the current encoder */
    if( p_image->p_enc &&
        ( p_image->p_enc->fmt_out.i_codec != codec ||
          p_image->p_enc->fmt_out.video.i_width != p_fmt_out->i_width ||
          p_image->p_enc->fmt_out.video.i_height != p_fmt_out->i_height ) )
    {
        vlc_encoder_Destroy( p_image->p_enc );
        p_image->p_enc = 0;
    }

    /* Start an encoder */
    if( !p_image->p_enc )
    {
        p_image->p_enc = CreateEncoder( p_image->p_parent,
                                        p_fmt_in, codec, p_fmt_out );
        if( !p_image->p_enc ) return NULL;
    }

    /* We'll release the picture at the end or during conversion. */
    picture_Hold(p_pic);

    /* Check if we need chroma conversion or resizing */
    if( !video_format_IsSameChroma(&p_image->p_enc->fmt_in.video, p_fmt_in) ||
        p_image->p_enc->fmt_in.video.i_width != p_fmt_in->i_width ||
        p_image->p_enc->fmt_in.video.i_height != p_fmt_in->i_height )
    {

        if( p_image->p_converter &&
            ( !video_format_IsSameChroma( &p_image->p_converter->fmt_in.video, p_fmt_in ) ||
              !video_format_IsSameChroma( &p_image->p_converter->fmt_out.video,
                                          &p_image->p_enc->fmt_in.video ) ) )
        {
            /* We need to restart a new filter */
            DeleteConverter( p_image->p_converter );
            p_image->p_converter = NULL;
        }

        /* Start a filter */
        if( !p_image->p_converter )
        {
            es_format_t fmt_in;
            es_format_Init( &fmt_in, VIDEO_ES, p_fmt_in->i_chroma );
            fmt_in.video = *p_fmt_in;

            p_image->p_converter =
                CreateConverter( p_image->p_parent, &fmt_in,
                                 picture_GetVideoContext(p_pic), &p_image->p_enc->fmt_in.video );

            if( !p_image->p_converter )
            {
                picture_Release(p_pic);
                return NULL;
            }
        }
        else
        {
            /* Filters should handle on-the-fly size changes */
            es_format_Clean( &p_image->p_converter->fmt_in );
            es_format_InitFromVideo( &p_image->p_converter->fmt_in, p_fmt_in );
            es_format_Clean( &p_image->p_converter->fmt_out );
            es_format_Copy( &p_image->p_converter->fmt_out, &p_image->p_enc->fmt_in );
        }

        /* Hold the picture there to let the caller release its own picture,
         * since filters will consume the picture. */

        p_pic = p_image->p_converter->ops->filter_video( p_image->p_converter, p_pic );
        assert(p_pic == NULL || !picture_HasChainedPics(p_pic)); // no chaining
    }

    block_t *p_block = NULL;
    if (p_pic != NULL)
    {
        p_block = vlc_encoder_EncodeVideo(p_image->p_enc, p_pic);
        picture_Release(p_pic);
    }

    if( !p_block )
    {
        msg_Dbg( p_image->p_parent, "no image encoded" );
        return 0;
    }

    return p_block;
}

static int ImageWriteUrl( image_handler_t *p_image, picture_t *p_pic,
                          const video_format_t *p_fmt_in,
                          vlc_fourcc_t codec, const video_format_t *p_fmt_out,
                          const char *psz_url )
{
    block_t *p_block;
    FILE *file;
    video_format_t fmt_out = *p_fmt_out;

    if( !codec )
    {
        /* Try to guess format from file name */
        codec = image_Ext2Fourcc( psz_url );
    }

    file = vlc_fopen( psz_url, "wb" );
    if( !file )
    {
        msg_Err( p_image->p_parent, "%s: %s", psz_url, vlc_strerror_c(errno) );
        return VLC_EGENERIC;
    }

    p_block = ImageWrite( p_image, p_pic, p_fmt_in, codec, &fmt_out );

    int err = 0;
    if( p_block )
    {
        if( fwrite( p_block->p_buffer, p_block->i_buffer, 1, file ) != 1 )
            err = errno;
        block_Release( p_block );
    }

    if( fclose( file ) && !err )
        err = errno;

    if( err )
    {
       errno = err;
       msg_Err( p_image->p_parent, "%s: %s", psz_url, vlc_strerror_c(errno) );
    }

    return err ? VLC_EGENERIC : VLC_SUCCESS;
}

/**
 * Convert an image to a different format
 *
 */


static picture_t *ImageConvert( image_handler_t *p_image, picture_t *p_pic,
                                const video_format_t *p_fmt_in,
                                video_format_t *p_fmt_out )
{
    if( !p_fmt_out->i_width && !p_fmt_out->i_height &&
        p_fmt_out->i_sar_num && p_fmt_out->i_sar_den &&
        p_fmt_out->i_sar_num * p_fmt_in->i_sar_den !=
        p_fmt_out->i_sar_den * p_fmt_in->i_sar_num )
    {
        p_fmt_out->i_width =
            p_fmt_in->i_sar_num * (int64_t)p_fmt_out->i_sar_den *
            p_fmt_in->i_width / p_fmt_in->i_sar_den / p_fmt_out->i_sar_num;
        p_fmt_out->i_visible_width =
            p_fmt_in->i_sar_num * (int64_t)p_fmt_out->i_sar_den *
            p_fmt_in->i_visible_width / p_fmt_in->i_sar_den /
            p_fmt_out->i_sar_num;
    }

    if( !p_fmt_out->i_chroma ) p_fmt_out->i_chroma = p_fmt_in->i_chroma;
    if( !p_fmt_out->i_width )
        p_fmt_out->i_width = p_fmt_out->i_visible_width = p_fmt_in->i_width;
    if( !p_fmt_out->i_height )
        p_fmt_out->i_height = p_fmt_out->i_visible_height = p_fmt_in->i_height;
    if( !p_fmt_out->i_sar_num ) p_fmt_out->i_sar_num = p_fmt_in->i_sar_num;
    if( !p_fmt_out->i_sar_den ) p_fmt_out->i_sar_den = p_fmt_in->i_sar_den;

    if( p_image->p_converter &&
        ( !video_format_IsSameChroma( &p_image->p_converter->fmt_in.video, p_fmt_in ) ||
          !video_format_IsSameChroma( &p_image->p_converter->fmt_out.video, p_fmt_out ) ) )
    {
        /* We need to restart a new filter */
        DeleteConverter( p_image->p_converter );
        p_image->p_converter = NULL;
    }

    /* Start a filter */
    if( !p_image->p_converter )
    {
        es_format_t fmt_in;
        es_format_Init( &fmt_in, VIDEO_ES, p_fmt_in->i_chroma );
        fmt_in.video = *p_fmt_in;

        p_image->p_converter =
            CreateConverter( p_image->p_parent, &fmt_in,
                             picture_GetVideoContext(p_pic), p_fmt_out );

        if( !p_image->p_converter )
        {
            return NULL;
        }
    }
    else
    {
        /* Filters should handle on-the-fly size changes */
        es_format_Clean( &p_image->p_converter->fmt_in );
        es_format_InitFromVideo( &p_image->p_converter->fmt_in, p_fmt_in );
        es_format_Clean( &p_image->p_converter->fmt_out );
        es_format_InitFromVideo( &p_image->p_converter->fmt_out, p_fmt_out );
    }

    picture_Hold( p_pic );

    p_pic = p_image->p_converter->ops->filter_video( p_image->p_converter, p_pic );
    assert(p_pic == NULL || !picture_HasChainedPics(p_pic)); // no chaining
    return p_pic;
}

/**
 * Misc functions
 *
 */

static const struct
{
    vlc_fourcc_t i_codec;
    const char psz_ext[7];

} ext_table[] =
{
    { VLC_CODEC_JPEG,              "jpeg" },
    { VLC_CODEC_JPEG,              "jpg"  },
    { VLC_CODEC_JPEGLS,            "ljpg" },
    { VLC_CODEC_BPG,               "bpg" },
    { VLC_CODEC_PNG,               "png" },
    { VLC_CODEC_PGM,               "pgm" },
    { VLC_CODEC_PGMYUV,            "pgmyuv" },
    { VLC_FOURCC('p','b','m',' '), "pbm" },
    { VLC_FOURCC('p','a','m',' '), "pam" },
    { VLC_CODEC_TARGA,             "tga" },
    { VLC_CODEC_BMP,               "bmp" },
    { VLC_CODEC_FARBFELD,          "farb" },
    { VLC_CODEC_PNM,               "pnm" },
    { VLC_FOURCC('x','p','m',' '), "xpm" },
    { VLC_FOURCC('x','c','f',' '), "xcf" },
    { VLC_CODEC_PCX,               "pcx" },
    { VLC_CODEC_GIF,               "gif" },
    { VLC_CODEC_QOI,               "qoi" },
    { VLC_CODEC_SVG,               "svg" },
    { VLC_CODEC_TIFF,              "tif" },
    { VLC_CODEC_TIFF,              "tiff" },
    { VLC_CODEC_WEBP,              "webp" },
    { VLC_FOURCC('l','b','m',' '), "lbm" },
    { VLC_CODEC_PPM,               "ppm" },
};

vlc_fourcc_t image_Type2Fourcc( const char *psz_type )
{
    for( unsigned i = 0; i < ARRAY_SIZE(ext_table); i++ )
        if( !strcasecmp( ext_table[i].psz_ext, psz_type ) )
            return ext_table[i].i_codec;

    return 0;
}

vlc_fourcc_t image_Ext2Fourcc( const char *psz_name )
{
    psz_name = strrchr( psz_name, '.' );
    if( !psz_name ) return 0;
    psz_name++;

    return image_Type2Fourcc( psz_name );
}

static const struct
{
    vlc_fourcc_t i_codec;
    const char *psz_mime;
} mime_table[] =
{
    { VLC_CODEC_BMP,               "image/bmp" },
    { VLC_CODEC_BMP,               "image/x-bmp" },
    { VLC_CODEC_BMP,               "image/x-bitmap" },
    { VLC_CODEC_BMP,               "image/x-ms-bmp" },
    { VLC_CODEC_PNM,               "image/x-portable-anymap" },
    { VLC_CODEC_PNM,               "image/x-portable-bitmap" },
    { VLC_CODEC_PNM,               "image/x-portable-graymap" },
    { VLC_CODEC_PNM,               "image/x-portable-pixmap" },
    { VLC_CODEC_GIF,               "image/gif" },
    { VLC_CODEC_JPEG,              "image/jpeg" },
    { VLC_CODEC_BPG,               "image/bpg" },
    { VLC_CODEC_FARBFELD,          "image/farbfeld" },
    { VLC_CODEC_PCX,               "image/pcx" },
    { VLC_CODEC_PNG,               "image/png" },
    { VLC_CODEC_QOI,               "image/qoi" },
    { VLC_CODEC_SVG,               "image/svg+xml" },
    { VLC_CODEC_TIFF,              "image/tiff" },
    { VLC_CODEC_TARGA,             "image/x-tga" },
    { VLC_CODEC_WEBP,              "image/webp" },
    { VLC_FOURCC('x','p','m',' '), "image/x-xpixmap" },
    { 0, NULL }
};

vlc_fourcc_t image_Mime2Fourcc( const char *psz_mime )
{
    for( int i = 0; mime_table[i].i_codec; i++ )
        if( !strcmp( psz_mime, mime_table[i].psz_mime ) )
            return mime_table[i].i_codec;
    return 0;
}

static vlc_decoder_device * image_get_device( decoder_t *p_dec )
{
    VLC_UNUSED(p_dec);
    return NULL; // no hardware decoding for now
}

static decoder_t *CreateDecoder( image_handler_t *p_image, const es_format_t *fmt )
{
    decoder_t *p_dec;
    struct decoder_owner *p_owner;

    p_owner = vlc_custom_create( p_image->p_parent, sizeof( *p_owner ), "image decoder" );
    if( p_owner == NULL )
        return NULL;
    p_dec = &p_owner->dec;
    p_owner->p_image = p_image;

    decoder_Init( p_dec, &p_owner->fmt_in, fmt );

    static const struct decoder_owner_callbacks dec_cbs =
    {
        .video = {
            .get_device = image_get_device,
            .queue = ImageQueueVideo,
        },
    };
    p_dec->cbs = &dec_cbs;

    /* Find a suitable decoder module */
    p_dec->p_module = module_need_var( p_dec, "video decoder", "codec" );
    if( !p_dec->p_module )
    {
        msg_Err( p_dec, "no suitable decoder module for fourcc `%4.4s'. "
                 "VLC probably does not support this image format.",
                 (char*)&p_dec->fmt_in->i_codec );

        decoder_Clean( p_dec );
        es_format_Clean( &p_owner->fmt_in );
        vlc_object_delete( p_dec );
        p_dec = NULL;
    }

    return p_dec;
}


static encoder_t *CreateEncoder( vlc_object_t *p_this, const video_format_t *fmt_in,
                                 vlc_fourcc_t codec, const video_format_t *fmt_out )
{
    encoder_t *p_enc;

    p_enc = sout_EncoderCreate( p_this, sizeof(encoder_t) );
    if( p_enc == NULL )
        return NULL;

    p_enc->p_module = NULL;
    es_format_InitFromVideo( &p_enc->fmt_in, fmt_in );

    if( fmt_out->i_width > 0 && fmt_out->i_height > 0 )
    {
        p_enc->fmt_in.video.i_width = fmt_out->i_width;
        p_enc->fmt_in.video.i_height = fmt_out->i_height;

        if( fmt_out->i_visible_width > 0 && fmt_out->i_visible_height > 0 )
        {
            p_enc->fmt_in.video.i_visible_width = fmt_out->i_visible_width;
            p_enc->fmt_in.video.i_visible_height = fmt_out->i_visible_height;
        }
        else
        {
            p_enc->fmt_in.video.i_visible_width = fmt_out->i_width;
            p_enc->fmt_in.video.i_visible_height = fmt_out->i_height;
        }
    }

    p_enc->fmt_in.video.i_frame_rate = 25;
    p_enc->fmt_in.video.i_frame_rate_base = 1;

    es_format_InitFromVideo( &p_enc->fmt_out, fmt_out );
    p_enc->fmt_out.i_codec = codec;
    p_enc->fmt_out.video.i_chroma = 0;
    p_enc->fmt_out.video.i_width = p_enc->fmt_in.video.i_width;
    p_enc->fmt_out.video.i_height = p_enc->fmt_in.video.i_height;
    p_enc->ops = NULL;

    /* Find a suitable decoder module */
    p_enc->p_module = module_need( p_enc, "image encoder", NULL, false );
    if( !p_enc->p_module )
    {
        msg_Err( p_enc, "no suitable encoder module for fourcc `%4.4s'.\n"
                 "VLC probably does not support this image format.",
                 (char*)&p_enc->fmt_out.i_codec );

        vlc_encoder_Destroy( p_enc );
        return NULL;
    }
    assert( p_enc->ops != NULL );

    return p_enc;
}

static filter_t *CreateConverter( vlc_object_t *p_this,
                                  const es_format_t *p_fmt_in,
                                  struct vlc_video_context *p_vctx_in,
                                  const video_format_t *p_fmt_out )
{
    filter_t *p_filter;

    p_filter = vlc_custom_create( p_this, sizeof(filter_t), "filter" );

    es_format_Copy( &p_filter->fmt_in, p_fmt_in );
    es_format_Copy( &p_filter->fmt_out, p_fmt_in );
    video_format_Copy( &p_filter->fmt_out.video, p_fmt_out );

    /* whatever the input offset, write at offset 0 in the target image */
    p_filter->fmt_out.video.i_x_offset = 0;
    p_filter->fmt_out.video.i_y_offset = 0;

    p_filter->fmt_out.i_codec = p_fmt_out->i_chroma;
    p_filter->vctx_in = p_vctx_in;
    p_filter->p_module = vlc_filter_LoadModule( p_filter, "video converter", NULL, false );

    if( !p_filter->p_module )
    {
        msg_Dbg( p_filter, "no video converter found" );
        DeleteConverter( p_filter );
        return NULL;
    }
    assert( p_filter->ops != NULL );

    return p_filter;
}

static void DeleteConverter( filter_t * p_filter )
{
    vlc_filter_UnloadModule( p_filter );

    es_format_Clean( &p_filter->fmt_in );
    es_format_Clean( &p_filter->fmt_out );

    vlc_object_delete(p_filter);
}

Messung
CHZG
849510093

¤ Dauer der Verarbeitung: 0.4 Sekunden  (vorverarbeitet am  2026-11-04) ¤

*© Formatika GbR, Deutschland






Wurzel

Suchen

PVS Prover

Isabelle Prover


Cephes Mathematical Library

Vienna Development Method

Haftungshinweis

Die Informationen auf dieser Webseite wurden nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit, noch Qualität der bereit gestellten Informationen zugesichert.

Bemerkung:

Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.