[vlc-devel] [PATCH 04/10] converter/tospdif: handle dts-hd

Jean-Baptiste Kempf jb at videolan.org
Wed Jan 18 09:51:33 CET 2017


LGTM.

On Wed, 18 Jan 2017, at 09:20, Thomas Guillem wrote:
> ---
>  modules/audio_filter/converter/tospdif.c | 104
>  ++++++++++++++++++++++++++++++-
>  1 file changed, 103 insertions(+), 1 deletion(-)
> 
> diff --git a/modules/audio_filter/converter/tospdif.c
> b/modules/audio_filter/converter/tospdif.c
> index bcc1f7c4a0..78eae744d8 100644
> --- a/modules/audio_filter/converter/tospdif.c
> +++ b/modules/audio_filter/converter/tospdif.c
> @@ -66,6 +66,10 @@ struct filter_sys_t
>          {
>              unsigned int i_frame_count;
>          } truehd;
> +        struct
> +        {
> +            bool b_skip;
> +        } dtshd;
>      };
>  };
>  
> @@ -77,6 +81,7 @@ struct filter_sys_t
>  #define IEC61937_DTS1 0x0B
>  #define IEC61937_DTS2 0x0C
>  #define IEC61937_DTS3 0x0D
> +#define IEC61937_DTSHD 0x11
>  
>  #define SPDIF_MORE_DATA 1
>  #define SPDIF_SUCCESS VLC_SUCCESS
> @@ -107,6 +112,17 @@ static void set_16( filter_t *p_filter, void *p_buf,
> uint16_t i_val )
>          SetWLE( p_buf, i_val );
>  }
>  
> +static void write_16( filter_t *p_filter, uint16_t i_val )
> +{
> +    filter_sys_t *p_sys = p_filter->p_sys;
> +    assert( p_sys->p_out_buf != NULL );
> +
> +    assert( p_sys->p_out_buf->i_buffer - p_sys->i_out_offset
> +            >= sizeof( uint16_t ) );
> +    set_16( p_filter, &p_sys->p_out_buf->p_buffer[p_sys->i_out_offset],
> i_val );
> +    p_sys->i_out_offset += sizeof( uint16_t );
> +}
> +
>  static void write_padding( filter_t *p_filter, size_t i_size )
>  {
>      filter_sys_t *p_sys = p_filter->p_sys;
> @@ -401,6 +417,86 @@ static int write_buffer_dts( filter_t *p_filter,
> block_t *p_in_buf )
>      return SPDIF_SUCCESS;
>  }
>  
> +/* Adapted from libavformat/spdifenc.c:
> + * DTS type IV (DTS-HD) can be transmitted with various frame repetition
> + * periods; longer repetition periods allow for longer packets and
> therefore
> + * higher bitrate. Longer repetition periods mean that the constant
> bitrate of
> + * the output IEC 61937 stream is higher.
> + * The repetition period is measured in IEC 60958 frames (4 bytes).
> + */
> +static int dtshd_get_subtype( unsigned i_frame_length )
> +{
> +    switch( i_frame_length )
> +    {
> +        case 512:   return 0x0;
> +        case 1024:  return 0x1;
> +        case 2048:  return 0x2;
> +        case 4096:  return 0x3;
> +        case 8192:  return 0x4;
> +        case 16384: return 0x5;
> +        default:    return -1;
> +    }
> +}
> +
> +/* Adapted from libavformat/spdifenc.c: */
> +static int write_buffer_dtshd( filter_t *p_filter, block_t *p_in_buf )
> +{
> +    static const char p_dtshd_start_code[10] = {
> +        0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, 0xfe
> +    };
> +    static const size_t i_dtshd_start_code = sizeof( p_dtshd_start_code
> );
> +
> +    filter_sys_t *p_sys = p_filter->p_sys;
> +    vlc_dts_header_t core;
> +    if( vlc_dts_header_Parse( &core, p_in_buf->p_buffer,
> +                              p_in_buf->i_buffer ) != VLC_SUCCESS )
> +        return SPDIF_ERROR;
> +    unsigned i_period = p_filter->fmt_out.audio.i_rate
> +                      * core.i_frame_length / core.i_rate;
> +
> +    int i_subtype = dtshd_get_subtype( i_period );
> +    if( i_subtype == -1 )
> +        return SPDIF_ERROR;
> +
> +    size_t i_in_size = i_dtshd_start_code + 2 + p_in_buf->i_buffer;
> +    size_t i_out_size = i_period * 4;
> +    uint16_t i_data_type = IEC61937_DTSHD | i_subtype << 8;
> +
> +    if( p_filter->p_sys->dtshd.b_skip
> +     || i_in_size + SPDIF_HEADER_SIZE > i_out_size )
> +    {
> +        /* The bitrate is too high, pass only the core part */
> +        p_in_buf->i_buffer = core.i_frame_size;
> +        i_in_size = i_dtshd_start_code + 2 + p_in_buf->i_buffer;
> +        if( i_in_size + SPDIF_HEADER_SIZE > i_out_size )
> +            return SPDIF_ERROR;
> +
> +        /* Don't try to send substreams anymore. That way, we avoid to
> switch
> +         * back and forth between DTD and DTS-HD */
> +        p_filter->p_sys->dtshd.b_skip = true;
> +    }
> +
> +    if( write_init( p_filter, p_in_buf, i_out_size,
> +                    i_out_size /
> p_filter->fmt_out.audio.i_bytes_per_frame ) )
> +        return SPDIF_ERROR;
> +
> +    write_data( p_filter, p_dtshd_start_code, i_dtshd_start_code, true
> );
> +    write_16( p_filter, p_in_buf->i_buffer );
> +    write_buffer( p_filter, p_in_buf );
> +
> +    /* Align so that (length_code & 0xf) == 0x8. This is reportedly
> needed
> +     * with some receivers, but the exact requirement is unconfirmed. */
> +#define ALIGN(x, y) (((x) + ((y) - 1)) & ~((y) - 1))
> +    size_t i_align = ALIGN( i_in_size + 0x8, 0x10 ) - 0x8;
> +#undef ALIGN
> +    if( i_align > i_in_size && i_align - i_in_size
> +        <= p_sys->p_out_buf->i_buffer - p_sys->i_out_offset )
> +        write_padding( p_filter, i_align - i_in_size );
> +
> +    write_finalize( p_filter, i_data_type, 1 /* in bytes */ );
> +    return SPDIF_SUCCESS;
> +}
> +
>  static void Flush( filter_t *p_filter )
>  {
>      filter_sys_t *p_sys = p_filter->p_sys;
> @@ -442,7 +538,13 @@ static block_t *DoWork( filter_t *p_filter, block_t
> *p_in_buf )
>              i_ret = write_buffer_truehd( p_filter, p_in_buf );
>              break;
>          case VLC_CODEC_DTS:
> -            i_ret = write_buffer_dts( p_filter, p_in_buf );
> +            /* if the fmt_out is configured for a higher rate than 48kHz
> +             * (IEC958 rate), use the DTS-HD framing to pass the DTS
> Core and
> +             * or DTS substreams (like DTS-HD MA). */
> +            if( p_filter->fmt_out.audio.i_rate > 48000 )
> +                i_ret = write_buffer_dtshd( p_filter, p_in_buf );
> +            else
> +                i_ret = write_buffer_dts( p_filter, p_in_buf );
>              break;
>          default:
>              vlc_assert_unreachable();
> -- 
> 2.11.0
> 
> _______________________________________________
> vlc-devel mailing list
> To unsubscribe or modify your subscription options:
> https://mailman.videolan.org/listinfo/vlc-devel


-- 
Jean-Baptiste Kempf -  President
+33 672 704 734


More information about the vlc-devel mailing list