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

Quelle  daala.c   Sprache: C

 

/*****************************************************************************
 * daala.c: daala codec module making use of libdaala.
 *****************************************************************************
 * Copyright (C) 2014 VLC authors and VideoLAN
 *
 * Authors: Tristan Matthews <le.businessman@gmail.com>
 *   * Based on theora.c by: 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.
 *****************************************************************************/


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

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

#include <vlc_common.h>
#include <vlc_configuration.h>
#include <vlc_plugin.h>
#include <vlc_codec.h>
#include <vlc_meta.h>
#include "../demux/xiph.h"

#include <codec.h>
#include <daaladec.h>
#ifdef ENABLE_SOUT
#include <daalaenc.h>
#endif

#include <limits.h>

/*****************************************************************************
 * decoder_sys_t : daala decoder descriptor
 *****************************************************************************/

typedef struct
{
    /* Module mode */
    bool b_packetizer;

    /*
     * Input properties
     */

    bool b_has_headers;

    /*
     * Daala properties
     */

    daala_info          di;       /* daala bitstream settings */
    daala_comment       dc;       /* daala comment information */
    daala_dec_ctx       *dcx;     /* daala decoder context */

    /*
     * Decoding properties
     */

    bool b_decoded_first_keyframe;

    /*
     * Common properties
     */

    vlc_tick_t i_pts;
} decoder_sys_t;

/*****************************************************************************
 * Local prototypes
 *****************************************************************************/

static int  OpenDecoder   ( vlc_object_t * );
static int  OpenPacketizer( vlc_object_t * );
static void CloseDecoder  ( vlc_object_t * );

static int DecodeVideo( decoder_t *p_dec, block_t *p_block );
static block_t *Packetize ( decoder_t *, block_t ** );
static int  ProcessHeaders( decoder_t * );
static void *ProcessPacket ( decoder_t *, daala_packet *, block_t * );

static picture_t *DecodePacket( decoder_t *, daala_packet * );

static void ParseDaalaComments( decoder_t * );
static void daala_CopyPicture( picture_t *, daala_image * );

#ifdef ENABLE_SOUT
static int  OpenEncoder( vlc_object_t *p_this );
static void CloseEncoder( encoder_t *p_enc );
static block_t *Encode( encoder_t *p_enc, picture_t *p_pict );

static const char *const enc_chromafmt_list[] = {
    "420", "444"
};
static const char *const enc_chromafmt_list_text[] = {
    "4:2:0", "4:4:4"
};
#endif

/*****************************************************************************
 * Module descriptor
 *****************************************************************************/

#define ENC_QUALITY_TEXT N_("Encoding quality")
#define ENC_QUALITY_LONGTEXT N_( \
  "Enforce a quality between 0 (lossless) and 511 (worst)." )
#define ENC_KEYINT_TEXT N_("Keyframe interval")
#define ENC_KEYINT_LONGTEXT N_( \
  "Enforce a keyframe interval between 1 and 1000." )

vlc_module_begin ()
    set_subcategory( SUBCAT_INPUT_VCODEC )
    set_shortname( "Daala" )
    set_description( N_("Daala video decoder") )
    set_capability( "video decoder", 100 )
    set_callbacks( OpenDecoder, CloseDecoder )
    add_shortcut( "daala" )
    add_submodule ()
    set_description( N_("Daala video packetizer") )
    set_capability( "video packetizer", 100 )
    set_callbacks( OpenPacketizer, CloseDecoder )
    add_shortcut( "daala" )

#ifdef ENABLE_SOUT
    add_submodule ()
    set_description( N_("Daala video encoder") )
    set_capability( "video encoder", 150 )
    set_callback( OpenEncoder )
    add_shortcut( "daala" )

#   define ENC_CFG_PREFIX "sout-daala-"
    add_integer_with_range( ENC_CFG_PREFIX "quality", 10, 0, 511,
                 ENC_QUALITY_TEXT, ENC_QUALITY_LONGTEXT )
    add_integer_with_range( ENC_CFG_PREFIX "keyint", 256, 1, 1000,
                 ENC_KEYINT_TEXT, ENC_KEYINT_LONGTEXT )

#   define ENC_CHROMAFMT_TEXT N_("Chroma format")
#   define ENC_CHROMAFMT_LONGTEXT N_("Picking chroma format will force a " \
                                     "conversion of the video into that format")

    add_string( ENC_CFG_PREFIX "chroma-fmt", "420", ENC_CHROMAFMT_TEXT,
                ENC_CHROMAFMT_LONGTEXT )
    change_string_list( enc_chromafmt_list, enc_chromafmt_list_text )
#endif
vlc_module_end ()

#ifdef ENABLE_SOUT
static const char *const ppsz_enc_options[] = {
    "quality", "keyint", "chroma-fmt", NULL
};
#endif

static int OpenCommon( vlc_object_t *p_this, bool b_packetizer )
{
    decoder_t *p_dec = (decoder_t*)p_this;
    decoder_sys_t *p_sys;

    if( p_dec->fmt_in->i_codec != VLC_CODEC_DAALA )
    {
        return VLC_EGENERIC;
    }

    /* Allocate the memory needed to store the decoder's structure */
    p_sys = malloc(sizeof(*p_sys));
    if( p_sys == NULL )
        return VLC_ENOMEM;

    p_dec->p_sys = p_sys;
    p_sys->b_packetizer = b_packetizer;
    p_sys->b_has_headers = false;
    p_sys->i_pts = VLC_TICK_INVALID;
    p_sys->b_decoded_first_keyframe = false;
    p_sys->dcx = NULL;

    if( b_packetizer )
    {
        p_dec->fmt_out.i_codec = VLC_CODEC_DAALA;
        p_dec->pf_packetize = Packetize;
    }
    else
    {
        p_dec->fmt_out.i_codec = VLC_CODEC_I420;
        p_dec->pf_decode = DecodeVideo;
    }

    /* Init supporting Daala structures needed in header parsing */
    daala_comment_init( &p_sys->dc );
    daala_info_init( &p_sys->di );

    return VLC_SUCCESS;
}

/*****************************************************************************
 * OpenDecoder: probe the decoder and return score
 *****************************************************************************/

static int OpenDecoder( vlc_object_t *p_this )
{
    return OpenCommon( p_this, false );
}

static int OpenPacketizer( vlc_object_t *p_this )
{
    return OpenCommon( p_this, true );
}

/****************************************************************************
 * DecodeBlock: the whole thing
 ****************************************************************************
 * This function must be fed with Daala packets.
 ****************************************************************************/

static void *DecodeBlock( decoder_t *p_dec, block_t *p_block )
{
    decoder_sys_t *p_sys = p_dec->p_sys;
    daala_packet dpacket;

    /* Block to Daala packet */
    dpacket.packet = p_block->p_buffer;
    dpacket.bytes = p_block->i_buffer;
    dpacket.granulepos = p_block->i_dts;
    dpacket.b_o_s = 0;
    dpacket.e_o_s = 0;
    dpacket.packetno = 0;

    /* Check for headers */
    if( !p_sys->b_has_headers )
    {
        if( ProcessHeaders( p_dec ) )
        {
            block_Release( p_block );
            return NULL;
        }
        p_sys->b_has_headers = true;
    }

    /* If we haven't seen a single keyframe yet, set to preroll,
     * otherwise we'll get display artifacts.  (This is impossible
     * in the general case, but can happen if e.g. we play a network stream
     * using a timed URL, such that the server doesn't start the video with a
     * keyframe). */

    if( !p_sys->b_decoded_first_keyframe )
        p_block->i_flags |= BLOCK_FLAG_PREROLL; /* Wait until we've decoded the first keyframe */

    return ProcessPacket( p_dec, &dpacket, p_block );
}

static int DecodeVideo( decoder_t *p_dec, block_t *p_block )
{
    if( p_block == NULL ) /* No Drain */
        return VLCDEC_SUCCESS;

    picture_t *p_pic = DecodeBlock( p_dec, p_block );
    if( p_pic != NULL )
        decoder_QueueVideo( p_dec, p_pic );
    return VLCDEC_SUCCESS;
}

static block_t *Packetize( decoder_t *p_dec, block_t **pp_block )
{
    if( pp_block == NULL ) /* No Drain */
        return NULL;
    block_t *p_block = *pp_block; *pp_block = NULL;
    if( p_block == NULL )
        return NULL;
    return DecodeBlock( p_dec, p_block );
}

/*****************************************************************************
 * ProcessHeaders: process Daala headers.
 *****************************************************************************/

static int ProcessHeaders( decoder_t *p_dec )
{
    int ret = VLC_SUCCESS;
    decoder_sys_t *p_sys = p_dec->p_sys;
    daala_packet dpacket;
    daala_setup_info *ds = NULL; /* daala setup information */

    unsigned pi_size[XIPH_MAX_HEADER_COUNT];
    const void *pp_data[XIPH_MAX_HEADER_COUNT];
    unsigned i_count;
    if( xiph_SplitHeaders( pi_size, pp_data, &i_count,
                           p_dec->fmt_in->i_extra, p_dec->fmt_in->p_extra) )
        return VLC_EGENERIC;
    if( i_count < 3 )
        return VLC_EGENERIC;

    dpacket.granulepos = -1;
    dpacket.e_o_s = 0;
    dpacket.packetno = 0;

    /* Take care of the initial info header */
    dpacket.b_o_s  = 1; /* yes this actually is a b_o_s packet :) */
    dpacket.bytes  = pi_size[0];
    dpacket.packet = (void *)pp_data[0];
    if( daala_decode_header_in( &p_sys->di, &p_sys->dc, &ds, &dpacket ) < 0 )
    {
        msg_Err( p_dec, "this bitstream does not contain Daala video data" );
        ret = VLC_EGENERIC;
        goto cleanup;
    }

    /* Set output properties */
    if( !p_sys->b_packetizer )
    {
        if( p_sys->di.plane_info[0].xdec == 0 && p_sys->di.plane_info[0].ydec == 0 &&
            p_sys->di.plane_info[1].xdec == 1 && p_sys->di.plane_info[1].ydec == 1 &&
            p_sys->di.plane_info[2].xdec == 1 && p_sys->di.plane_info[2].ydec == 1 )
        {
            p_dec->fmt_out.i_codec = VLC_CODEC_I420;
        }
        else if( p_sys->di.plane_info[0].xdec == 0 && p_sys->di.plane_info[0].ydec == 0 &&
                 p_sys->di.plane_info[1].xdec == 0 && p_sys->di.plane_info[1].ydec == 0 &&
                 p_sys->di.plane_info[2].xdec == 0 && p_sys->di.plane_info[2].ydec == 0 )
        {
            p_dec->fmt_out.i_codec = VLC_CODEC_I444;
        }
        else
        {
            msg_Err( p_dec, "unknown chroma in daala sample" );
        }
    }

    p_dec->fmt_out.video.i_width = p_sys->di.pic_width;
    p_dec->fmt_out.video.i_height = p_sys->di.pic_height;
    if( p_sys->di.pic_width && p_sys->di.pic_height )
    {
        p_dec->fmt_out.video.i_visible_width = p_sys->di.pic_width;
        p_dec->fmt_out.video.i_visible_height = p_sys->di.pic_height;
    }

    if( p_sys->di.pixel_aspect_denominator && p_sys->di.pixel_aspect_numerator )
    {
        p_dec->fmt_out.video.i_sar_num = p_sys->di.pixel_aspect_numerator;
        p_dec->fmt_out.video.i_sar_den = p_sys->di.pixel_aspect_denominator;
    }
    else
    {
        p_dec->fmt_out.video.i_sar_num = 1;
        p_dec->fmt_out.video.i_sar_den = 1;
    }

    if( p_sys->di.timebase_numerator > 0 && p_sys->di.timebase_denominator > 0 )
    {
        p_dec->fmt_out.video.i_frame_rate = p_sys->di.timebase_numerator;
        p_dec->fmt_out.video.i_frame_rate_base = p_sys->di.timebase_denominator;
    }

    msg_Dbg( p_dec, "%dx%d %.02f fps video, frame content ",
             p_sys->di.pic_width, p_sys->di.pic_height,
             (double)p_sys->di.timebase_numerator/p_sys->di.timebase_denominator );

    /* The next packet in order is the comments header */
    dpacket.b_o_s  = 0;
    dpacket.bytes  = pi_size[1];
    dpacket.packet = (void *)pp_data[1];

    if( daala_decode_header_in( &p_sys->di, &p_sys->dc, &ds, &dpacket ) < 0 )
    {
        msg_Err( p_dec, "Daala comment header is corrupted" );
        ret = VLC_EGENERIC;
        goto cleanup;
    }

    ParseDaalaComments( p_dec );

    /* The next packet in order is the setup header
     * We need to watch out that this packet is not missing as a
     * missing or corrupted header is fatal. */

    dpacket.b_o_s  = 0;
    dpacket.bytes  = pi_size[2];
    dpacket.packet = (void *)pp_data[2];
    if( daala_decode_header_in( &p_sys->di, &p_sys->dc, &ds, &dpacket ) < 0 )
    {
        msg_Err( p_dec, "Daala setup header is corrupted" );
        ret = VLC_EGENERIC;
        goto cleanup;
    }

    if( !p_sys->b_packetizer )
    {
        /* We have all the headers, initialize decoder */
        if ( ( p_sys->dcx = daala_decode_create( &p_sys->di, ds ) ) == NULL )
        {
            msg_Err( p_dec, "Could not allocate Daala decoder" );
            ret = VLC_EGENERIC;
            goto cleanup;
        }
    }
    else
    {
        void* p_extra = realloc( p_dec->fmt_out.p_extra,
                                 p_dec->fmt_in->i_extra );
        if( unlikely( p_extra == NULL ) )
        {
            ret = VLC_ENOMEM;
            goto cleanup;
        }
        p_dec->fmt_out.p_extra = p_extra;
        p_dec->fmt_out.i_extra = p_dec->fmt_in->i_extra;
        memcpy( p_dec->fmt_out.p_extra,
                p_dec->fmt_in->p_extra, p_dec->fmt_out.i_extra );
    }

cleanup:
    /* Clean up the decoder setup info... we're done with it */
    daala_setup_free( ds );

    return ret;
}

/*****************************************************************************
 * ProcessPacket: processes a daala packet.
 *****************************************************************************/

static void *ProcessPacket( decoder_t *p_dec, daala_packet *p_dpacket,
                            block_t *p_block )
{
    decoder_sys_t *p_sys = p_dec->p_sys;
    void *p_buf;

    if( ( p_block->i_flags&(BLOCK_FLAG_CORRUPTED) ) != 0 )
    {
        /* Don't send the the first packet after a discontinuity to
         * daala_decode, otherwise we get purple/green display artifacts
         * appearing in the video output */

        block_Release(p_block);
        return NULL;
    }

    /* Date management */
    if( p_block->i_pts != VLC_TICK_INVALID && p_block->i_pts != p_sys->i_pts )
    {
        p_sys->i_pts = p_block->i_pts;
    }

    if( p_sys->b_packetizer )
    {
        /* Date management */
        p_block->i_dts = p_block->i_pts = p_sys->i_pts;

        p_block->i_length = p_sys->i_pts - p_block->i_pts;

        p_buf = p_block;
    }
    else
    {
        p_buf = DecodePacket( p_dec, p_dpacket );
        block_Release( p_block );
    }

    /* Date management */
    p_sys->i_pts += vlc_tick_from_samples( p_sys->di.timebase_denominator,
                      p_sys->di.timebase_numerator ); /* 1 frame per packet */

    return p_buf;
}

/*****************************************************************************
 * DecodePacket: decodes a Daala packet.
 *****************************************************************************/

static picture_t *DecodePacket( decoder_t *p_dec, daala_packet *p_dpacket )
{
    decoder_sys_t *p_sys = p_dec->p_sys;
    picture_t *p_pic;
    daala_image ycbcr;

    if (daala_decode_packet_in( p_sys->dcx, p_dpacket ) < 0)
        return NULL; /* bad packet */

    if (!daala_decode_img_out( p_sys->dcx, &ycbcr ))
        return NULL;

    /* Check for keyframe */
    if( daala_packet_iskeyframe( p_dpacket ) )
        p_sys->b_decoded_first_keyframe = true;

    /* Get a new picture */
    if( decoder_UpdateVideoFormat( p_dec ) )
        return NULL;
    p_pic = decoder_NewPicture( p_dec );
    if( !p_pic ) return NULL;

    daala_CopyPicture( p_pic, &ycbcr );

    p_pic->date = p_sys->i_pts;

    return p_pic;
}

/*****************************************************************************
 * ParseDaalaComments:
 *****************************************************************************/

static void ParseDaalaComments( decoder_t *p_dec )
{
    char *psz_name, *psz_value, *psz_comment;
    /* Regarding the daala_comment structure: */

    /* The metadata is stored as a series of (tag, value) pairs, in
       length-encoded string vectors. The first occurrence of the '='
       character delimits the tag and value. A particular tag may
       occur more than once, and order is significant. The character
       set encoding for the strings is always UTF-8, but the tag names
       are limited to ASCII, and treated as case-insensitive. See the
       Theora specification, Section 6.3.3 for details. */


    /* In filling in this structure, daala_decode_header_in() will
       null-terminate the user_comment strings for safety. However,
       the bitstream format itself treats them as 8-bit clean vectors,
       possibly containing null characters, and so the length array
       should be treated as their authoritative length. */

    decoder_sys_t *p_sys = p_dec->p_sys;
    for ( int i = 0; i < p_sys->dc.comments; i++ )
    {
        int clen = p_sys->dc.comment_lengths[i];
        if ( clen <= 0 || clen >= INT_MAX ) { continue; }
        psz_comment = malloc( clen + 1 );
        if( !psz_comment )
            break;
        memcpy( (void*)psz_comment, (void*)p_sys->dc.user_comments[i], clen + 1 );
        psz_comment[clen] = '\0';

        psz_name = psz_comment;
        psz_value = strchr( psz_comment, '=' );
        if( psz_value )
        {
            *psz_value = '\0';
            psz_value++;

            if( !p_dec->p_description )
                p_dec->p_description = vlc_meta_New();
            /* TODO:  Since psz_value can contain NULLs see if there is an
             * instance where we need to preserve the full length of this string */

            if( p_dec->p_description )
                vlc_meta_SetExtra( p_dec->p_description, psz_name, psz_value );
        }
        free( psz_comment );
    }
}

/*****************************************************************************
 * CloseDecoder: daala decoder destruction
 *****************************************************************************/

static void CloseDecoder( vlc_object_t *p_this )
{
    decoder_t *p_dec = (decoder_t *)p_this;
    decoder_sys_t *p_sys = p_dec->p_sys;

    daala_info_clear(&p_sys->di);
    daala_comment_clear(&p_sys->dc);
    daala_decode_free(p_sys->dcx);
    free( p_sys );
}

/*****************************************************************************
 * daala_CopyPicture: copy a picture from daala internal buffers to a
 *                     picture_t structure.
 *****************************************************************************/

static void daala_CopyPicture( picture_t *p_pic,
                               daala_image *ycbcr )
{
    const int i_planes = __MIN(p_pic->i_planes, 3);
    for( int i_plane = 0; i_plane < i_planes; i_plane++ )
    {
        plane_t src;
        src.i_lines = __MIN(p_pic->p[i_plane].i_lines, ycbcr->height >> ycbcr->planes[i_plane].ydec);
        src.p_pixels = ycbcr->planes[i_plane].data;
        src.i_pitch = ycbcr->planes[i_plane].ystride;
        src.i_visible_pitch = src.i_pitch;
        src.i_visible_lines = src.i_lines;
        plane_CopyPixels( &p_pic->p[i_plane], &src );
    }
}

#ifdef ENABLE_SOUT
typedef struct
{
    daala_info      di;                     /* daala bitstream settings */
    daala_comment   dc;                     /* daala comment header */
    daala_enc_ctx   *dcx;                   /* daala context */
} encoder_sys_t;

static int OpenEncoder( vlc_object_t *p_this )
{
    encoder_t *p_enc = (encoder_t *)p_this;
    encoder_sys_t *p_sys;
    daala_packet header;
    int status;

    if( p_enc->fmt_out.i_codec != VLC_CODEC_DAALA &&
        !p_enc->obj.force )
    {
        return VLC_EGENERIC;
    }

    /* Allocate the memory needed to store the encoder's structure */
    p_sys = malloc( sizeof( encoder_sys_t ) );
    if( !p_sys )
        return VLC_ENOMEM;
    p_enc->p_sys = p_sys;

    p_enc->fmt_out.i_codec = VLC_CODEC_DAALA;

    config_ChainParse( p_enc, ENC_CFG_PREFIX, ppsz_enc_options, p_enc->p_cfg );

    char *psz_tmp = var_GetString( p_enc, ENC_CFG_PREFIX "chroma-fmt" );
    vlc_fourcc_t i_codec;
    if( !psz_tmp ) {
        free(p_sys);
        return VLC_ENOMEM;
    } else {
        if( !strcmp( psz_tmp, "420" ) ) {
            i_codec = VLC_CODEC_I420;
        }
        else if( !strcmp( psz_tmp, "444" ) ) {
            i_codec = VLC_CODEC_I444;
        }
        else {
            msg_Err( p_enc, "Invalid chroma format: %s", psz_tmp );
            free( psz_tmp );
            free( p_sys );
            return VLC_EGENERIC;
        }
        free( psz_tmp );
        p_enc->fmt_in.i_codec = i_codec;
        /* update bits_per_pixel */
        video_format_Setup(&p_enc->fmt_in.video, i_codec,
                p_enc->fmt_in.video.i_width,
                p_enc->fmt_in.video.i_height,
                p_enc->fmt_in.video.i_visible_width,
                p_enc->fmt_in.video.i_visible_height,
                p_enc->fmt_in.video.i_sar_num,
                p_enc->fmt_in.video.i_sar_den);
    }

    daala_info_init( &p_sys->di );

    p_sys->di.pic_width = p_enc->fmt_in.video.i_visible_width;
    p_sys->di.pic_height = p_enc->fmt_in.video.i_visible_height;

    p_sys->di.nplanes = 3;
    for (int i = 0; i < p_sys->di.nplanes; i++)
    {
        p_sys->di.plane_info[i].xdec = i > 0 && i_codec != VLC_CODEC_I444;
        p_sys->di.plane_info[i].ydec = i_codec == VLC_CODEC_I420 ?
            p_sys->di.plane_info[i].xdec : 0;
    }
    p_sys->di.frame_duration = 1;

    if( !p_enc->fmt_in.video.i_frame_rate ||
        !p_enc->fmt_in.video.i_frame_rate_base )
    {
        p_sys->di.timebase_numerator = 25;
        p_sys->di.timebase_denominator = 1;
    }
    else
    {
        p_sys->di.timebase_numerator = p_enc->fmt_in.video.i_frame_rate;
        p_sys->di.timebase_denominator = p_enc->fmt_in.video.i_frame_rate_base;
    }

    if( p_enc->fmt_in.video.i_sar_num > 0 && p_enc->fmt_in.video.i_sar_den > 0 )
    {
        unsigned i_dst_num, i_dst_den;
        vlc_ureduce( &i_dst_num, &i_dst_den,
                     p_enc->fmt_in.video.i_sar_num,
                     p_enc->fmt_in.video.i_sar_den, 0 );
        p_sys->di.pixel_aspect_numerator = i_dst_num;
        p_sys->di.pixel_aspect_denominator = i_dst_den;
    }
    else
    {
        p_sys->di.pixel_aspect_numerator = 4;
        p_sys->di.pixel_aspect_denominator = 3;
    }

    p_sys->di.keyframe_rate = var_GetInteger( p_enc, ENC_CFG_PREFIX "keyint" );

    daala_enc_ctx *dcx;
    p_sys->dcx = dcx = daala_encode_create( &p_sys->di );
    if( !dcx )
    {
        free( p_sys );
        return VLC_ENOMEM;
    }

    daala_comment_init( &p_sys->dc );

    int i_quality = var_GetInteger( p_enc, ENC_CFG_PREFIX "quality" );
    daala_encode_ctl( dcx, OD_SET_QUANT, &i_quality, sizeof(i_quality) );

    /* Create and store headers */
    while( ( status = daala_encode_flush_header( dcx, &p_sys->dc, &header ) ) )
    {
        if ( status < 0 )
        {
            CloseEncoder( p_enc );
            return VLC_EGENERIC;
        }
        if( xiph_AppendHeaders( &p_enc->fmt_out.i_extra,
                                &p_enc->fmt_out.p_extra, header.bytes,
                                header.packet ) )
        {
            p_enc->fmt_out.i_extra = 0;
            p_enc->fmt_out.p_extra = NULL;
        }
    }

    static const struct vlc_encoder_operations ops =
    {
        .close = CloseEncoder,
        .encode_video = Encode,
    };
    p_enc->ops = &ops;

    return VLC_SUCCESS;
}

static block_t *Encode( encoder_t *p_enc, picture_t *p_pict )
{
    encoder_sys_t *p_sys = p_enc->p_sys;
    daala_packet dpacket;
    block_t *p_block;
    daala_image img;

    if( !p_pict ) return NULL;

    const int i_width = p_sys->di.pic_width;
    const int i_height = p_sys->di.pic_height;

    /* Sanity check */
    if( p_pict->p[0].i_pitch < i_width ||
        p_pict->p[0].i_lines < i_height )
    {
        msg_Err( p_enc, "frame is smaller than encoding size"
                 "(%ix%i->%ix%i) -> dropping frame",
                 p_pict->p[0].i_pitch, p_pict->p[0].i_lines,
                 i_width, i_height );
        return NULL;
    }

    /* Daala is a one-frame-in, one-frame-out system. Submit a frame
     * for compression and pull out the packet. */


    img.nplanes = p_sys->di.nplanes;
    img.width = i_width;
    img.height = i_height;
    for( int i = 0; i < img.nplanes; i++ )
    {
        img.planes[i].data = p_pict->p[i].p_pixels;
        img.planes[i].xdec = p_sys->di.plane_info[i].xdec;
        img.planes[i].ydec = p_sys->di.plane_info[i].ydec;
        img.planes[i].xstride = 1;
        img.planes[i].ystride = p_pict->p[i].i_pitch;
        img.planes[i].bitdepth = 8; /*FIXME: support higher bit depths*/
    }

    if( daala_encode_img_in( p_sys->dcx, &img, 0 ) < 0 )
    {
        msg_Warn( p_enc, "failed encoding a frame" );
        return NULL;
    }

    daala_encode_packet_out( p_sys->dcx, 0, &dpacket );

    /* Daala packet to block */
    p_block = block_Alloc( dpacket.bytes );
    if( unlikely(p_block == NULL) )
        return NULL;

    memcpy( p_block->p_buffer, dpacket.packet, dpacket.bytes );
    p_block->i_dts = p_block->i_pts = p_pict->date;

    if( daala_packet_iskeyframe( &dpacket ) )
        p_block->i_flags |= BLOCK_FLAG_TYPE_I;

    return p_block;
}

static void CloseEncoder( encoder_t *p_enc )
{
    encoder_sys_t *p_sys = p_enc->p_sys;

    daala_info_clear(&p_sys->di);
    daala_comment_clear(&p_sys->dc);
    daala_encode_free(p_sys->dcx);
    free( p_sys );
}
#endif

Messung
CHZG
849610093

¤ 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.