Exemplo n.º 1
0
Arquivo: h264.c Projeto: IAPark/vlc
static void ActivateSets( decoder_t *p_dec, const h264_sequence_parameter_set_t *p_sps,
                                            const h264_picture_parameter_set_t *p_pps )
{
    decoder_sys_t *p_sys = p_dec->p_sys;

    p_sys->p_active_pps = p_pps;
    p_sys->p_active_sps = p_sps;

    if( p_sps )
    {
        p_dec->fmt_out.i_profile = p_sps->i_profile;
        p_dec->fmt_out.i_level = p_sps->i_level;

        (void) h264_get_picture_size( p_sps, &p_dec->fmt_out.video.i_width,
                                      &p_dec->fmt_out.video.i_height,
                                      &p_dec->fmt_out.video.i_visible_width,
                                      &p_dec->fmt_out.video.i_visible_height );

        if( p_sps->vui.i_sar_num != 0 && p_sps->vui.i_sar_den != 0 )
        {
            p_dec->fmt_out.video.i_sar_num = p_sps->vui.i_sar_num;
            p_dec->fmt_out.video.i_sar_den = p_sps->vui.i_sar_den;
        }

        if( p_sps->vui.b_valid )
        {
            if( !p_dec->fmt_in.video.i_frame_rate_base &&
                p_sps->vui.i_num_units_in_tick > 0 && p_sps->vui.i_time_scale > 1 )
            {
                const unsigned i_rate_base = p_sps->vui.i_num_units_in_tick;
                const unsigned i_rate = p_sps->vui.i_time_scale >> 1; /* num_clock_ts == 2 */
                if( i_rate_base != p_dec->fmt_out.video.i_frame_rate_base ||
                    i_rate != p_dec->fmt_out.video.i_frame_rate )
                {
                    p_dec->fmt_out.video.i_frame_rate_base = i_rate_base;
                    p_dec->fmt_out.video.i_frame_rate = i_rate;
                    date_Change( &p_sys->dts, p_sps->vui.i_time_scale, p_sps->vui.i_num_units_in_tick );
                }
            }
            if( p_dec->fmt_in.video.primaries == COLOR_PRIMARIES_UNDEF )
                h264_get_colorimetry( p_sps, &p_dec->fmt_out.video.primaries,
                                      &p_dec->fmt_out.video.transfer,
                                      &p_dec->fmt_out.video.space,
                                      &p_dec->fmt_out.video.b_color_range_full );
        }
    }
}
Exemplo n.º 2
0
Arquivo: audio.c Projeto: MSalmo/vlc
int transcode_audio_process( sout_stream_t *p_stream,
                                    sout_stream_id_t *id,
                                    block_t *in, block_t **out )
{
    sout_stream_sys_t *p_sys = p_stream->p_sys;
    block_t *p_block, *p_audio_buf;
    *out = NULL;

    if( unlikely( in == NULL ) )
    {
        block_t *p_block;
        do {
           p_block = id->p_encoder->pf_encode_audio(id->p_encoder, NULL );
           block_ChainAppend( out, p_block );
        } while( p_block );
        return VLC_SUCCESS;
    }

    while( (p_audio_buf = id->p_decoder->pf_decode_audio( id->p_decoder,
                                                          &in )) )
    {

        if( unlikely( !id->p_encoder->p_module ) )
        {
            /* Complete destination format */
            id->p_encoder->fmt_out.i_codec = p_sys->i_acodec;
            id->p_encoder->fmt_out.audio.i_rate = p_sys->i_sample_rate > 0 ?
                p_sys->i_sample_rate : id->p_decoder->fmt_out.audio.i_rate;
            id->p_encoder->fmt_out.i_bitrate = p_sys->i_abitrate;
            id->p_encoder->fmt_out.audio.i_bitspersample =
                id->p_decoder->fmt_out.audio.i_bitspersample;
            id->p_encoder->fmt_out.audio.i_channels = p_sys->i_channels > 0 ?
                p_sys->i_channels : id->p_decoder->fmt_out.audio.i_channels;
            /* Sanity check for audio channels */
            id->p_encoder->fmt_out.audio.i_channels =
                __MIN( id->p_encoder->fmt_out.audio.i_channels,
                       id->p_decoder->fmt_out.audio.i_channels );
            id->p_encoder->fmt_out.audio.i_original_channels =
                id->p_decoder->fmt_in.audio.i_physical_channels;
            id->p_encoder->fmt_out.audio.i_physical_channels =
                pi_channels_maps[id->p_encoder->fmt_out.audio.i_channels];
            if( transcode_audio_initialize_encoder( id, p_stream ) )
            {
                msg_Err( p_stream, "cannot create audio chain" );
                return VLC_EGENERIC;
            }
            if( unlikely( transcode_audio_initialize_filters( p_stream, id, p_sys, &id->p_decoder->fmt_out.audio ) != VLC_SUCCESS ) )
                return VLC_EGENERIC;
            date_Init( &id->interpolated_pts, id->p_decoder->fmt_out.audio.i_rate, 1 );

        }
        /* Check if audio format has changed, and filters need reinit */
        if( unlikely( ( id->p_decoder->fmt_out.audio.i_rate != p_sys->fmt_audio.i_rate ) ||
                      ( id->p_decoder->fmt_out.audio.i_physical_channels != p_sys->fmt_audio.i_physical_channels ) ) )
        {
            msg_Info( p_stream, "Audio changed, trying to reinitialize filters" );
            if( id->p_af_chain != NULL )
                aout_FiltersDelete( (vlc_object_t *)NULL, id->p_af_chain );

            /* decoders don't set audio.i_format, but audio filters use it */
            id->p_decoder->fmt_out.audio.i_format = id->p_decoder->fmt_out.i_codec;
            aout_FormatPrepare( &id->p_decoder->fmt_out.audio );

            if( transcode_audio_initialize_filters( p_stream, id, p_sys, &id->p_decoder->fmt_out.audio ) != VLC_SUCCESS )
                return VLC_EGENERIC;

            /* Set interpolated_pts to run with new samplerate */
            date_Change( &id->interpolated_pts, p_sys->fmt_audio.i_rate, 1 );

        }

        if( p_sys->b_master_sync )
        {
            mtime_t i_pts = date_Get( &id->interpolated_pts );
            mtime_t i_drift = 0;

            if( likely( p_audio_buf->i_pts != VLC_TS_INVALID ) )
                i_drift = p_audio_buf->i_pts - i_pts;

            if ( unlikely(i_drift > MASTER_SYNC_MAX_DRIFT
                 || i_drift < -MASTER_SYNC_MAX_DRIFT) )
            {
                msg_Dbg( p_stream,
                    "audio drift is too high (%"PRId64"), resetting master sync",
                    i_drift );
                date_Set( &id->interpolated_pts, p_audio_buf->i_pts );
                i_pts = date_Get( &id->interpolated_pts );
                if( likely(p_audio_buf->i_pts != VLC_TS_INVALID ) )
                    i_drift = p_audio_buf->i_pts - i_pts;
            }
            p_sys->i_master_drift = i_drift;
            date_Increment( &id->interpolated_pts, p_audio_buf->i_nb_samples );
        }

        p_audio_buf->i_dts = p_audio_buf->i_pts;

        /* Run filter chain */
        p_audio_buf = aout_FiltersPlay( id->p_af_chain, p_audio_buf,
                                        INPUT_RATE_DEFAULT );
        if( !p_audio_buf )
            abort();

        p_audio_buf->i_dts = p_audio_buf->i_pts;

        p_block = id->p_encoder->pf_encode_audio( id->p_encoder, p_audio_buf );

        block_ChainAppend( out, p_block );
        block_Release( p_audio_buf );
    }

    return VLC_SUCCESS;
}
Exemplo n.º 3
0
Arquivo: dirac.c Projeto: AsamQi/vlc
/***
 * Packet (Data Unit) inspection, learns parameters from sequence
 * headers, sets up flags, drops unwanted data units, sets
 * encapsulation unit termination policy
 */
static int dirac_InspectDataUnit( decoder_t *p_dec, block_t **pp_block, block_t *p_eu )
{
    decoder_sys_t *p_sys = p_dec->p_sys;
    block_t *p_block = *pp_block;
    uint8_t u_parse_code = p_block->p_buffer[4];

    if( dirac_isEOS( u_parse_code ) )
    {
        if( p_sys->b_seen_eos )
        {
            /* remove duplicate EOS packets */
            block_Release( p_block );
            *pp_block = NULL;
            return DIRAC_DU_IN_EU;
        }
        /* p_block is an EOS packet */
        p_eu->i_flags |= BLOCK_FLAG_END_OF_SEQUENCE;
        /* for the moment, let this end an encapsulation unit */
        /* seeing an eos packet requires a flush of the packetizer
         * this is detected by the caller of this function */
        p_sys->b_seen_seq_hdr = false;
        p_sys->b_seen_eos = true;
        return DIRAC_DU_ENDS_EU;
#if 0
        /* let anything down streem know too */
        /*
        Actually, this is a bad idea:
         - It sets the discontinuity for every dirac EOS packet
           which doesnt imply a time discontinuity.
         - When the synchronizer detects a real discontinuity, it
           should copy the flags through.
        p_eu->i_flags |= BLOCK_FLAG_DISCONTINUITY;
        */
#endif
    }
    p_sys->b_seen_eos = false;

    if( dirac_isPicture( u_parse_code ) )
    {
        /* timestamps apply to pictures only */
        p_eu->i_dts = p_sys->i_eu_dts;
        p_eu->i_pts = p_sys->i_eu_pts;
        p_sys->i_eu_dts = p_sys->i_eu_pts = VLC_TS_INVALID;

        if( !p_sys->b_seen_seq_hdr )
        {
            /* can't timestamp in this case, discard later
             * so that the timestamps aren't lost */
            p_eu->i_flags |= DIRAC_DISCARD;
        }
        /* p_block is a picture -- it ends the 'encapsulation unit' */
        if( dirac_numRefs( u_parse_code ) )
        {
            /* if this picture is not an I frame, ensure that the
             * random access point flags are not set */
            p_eu->i_flags &= ~BLOCK_FLAG_TYPE_I;
        }
        dirac_block_encap_t *p_dbe = dirac_GetBlockEncap( p_block );
        if( p_dbe && p_block->i_buffer > 13+4 )
        {
            /* record the picture number to save the time gen functions
             * from having to inspect the data for it */
            p_dbe->u_picture_number = GetDWBE( p_block->p_buffer + 13 );
        }
        return DIRAC_DU_ENDS_EU;
    }

    if( dirac_isSeqHdr( u_parse_code ) )
    {
        if( !dirac_UnpackSeqHdr( &p_sys->seq_hdr, p_block ) )
        {
            /* couldn't parse the sequence header, just ignore it */
            return DIRAC_DU_IN_EU;
        }
        p_sys->b_seen_seq_hdr = true;

       /* a sequence header followed by an I frame is a random
        * access point; assume that this is the case */
        p_eu->i_flags |= BLOCK_FLAG_TYPE_I;

        es_format_t *p_es = &p_dec->fmt_out;

        p_es->video.i_width  = p_sys->seq_hdr.u_width;
        p_es->video.i_height = p_sys->seq_hdr.u_height;

        vlc_ureduce( &p_es->video.i_frame_rate, &p_es->video.i_frame_rate_base
                   , p_sys->seq_hdr.u_fps_num, p_sys->seq_hdr.u_fps_den, 0 );

        /* when field coding, dts needs to be incremented in terms of field periods */
        unsigned u_pics_per_sec = p_sys->seq_hdr.u_fps_num;
        if( p_sys->seq_hdr.u_picture_coding_mode == DIRAC_FIELD_CODING )
        {
            u_pics_per_sec *= 2;
        }
        date_Change( &p_sys->dts, u_pics_per_sec, p_sys->seq_hdr.u_fps_den );

        /* TODO: set p_sys->reorder_buf.u_size_max */
        p_sys->i_pts_offset = p_sys->reorder_buf.u_size_max
                            * 1000000
                            * p_es->video.i_frame_rate_base / p_es->video.i_frame_rate + 1;

        /* stash a copy of the seqhdr
         *  - required for ogg muxing
         *  - useful for error checking
         *  - it isn't allowed to change until an eos */
        free( p_es->p_extra );
        p_es->p_extra = calloc( 1, p_block->i_buffer + 13 );
        if( !p_es->p_extra )
        {
            p_es->i_extra = 0;
            return DIRAC_DU_IN_EU;
        }
        p_es->i_extra = p_block->i_buffer;
        memcpy( p_es->p_extra, p_block->p_buffer, p_block->i_buffer );
        /* append EOS as per Ogg guidelines */
        p_block = dirac_EmitEOS( p_dec, p_block->i_buffer );
        if( p_block )
        {
            memcpy( (uint8_t*)p_es->p_extra + p_es->i_extra, p_block->p_buffer, 13 );
            p_es->i_extra += 13;
        }

        return DIRAC_DU_IN_EU;
    }

    /* doesn't end an encapsulation unit */
    return DIRAC_DU_IN_EU;
}
Exemplo n.º 4
0
Arquivo: smf.c Projeto: CSRedRat/vlc
/**
 * Non-MIDI Meta events handler
 */
static
int HandleMeta (demux_t *p_demux, mtrk_t *tr)
{
    stream_t *s = p_demux->s;
    demux_sys_t *p_sys = p_demux->p_sys;
    uint8_t *payload;
    uint8_t type;
    int32_t length;
    int ret = 0;

    if (stream_Read (s, &type, 1) != 1)
        return -1;

    length = ReadVarInt (s);
    if (length < 0)
        return -1;

    payload = malloc (length + 1);
    if ((payload == NULL)
     || (stream_Read (s, payload, length) != length))
    {
        free (payload);
        return -1;
    }

    payload[length] = '\0';

    switch (type)
    {
        case 0x00: /* Sequence Number */
            break;

        case 0x01: /* Text (comment) */
            EnsureUTF8 ((char *)payload);
            msg_Info (p_demux, "Text      : %s", (char *)payload);
            break;

        case 0x02: /* Copyright */
            EnsureUTF8 ((char *)payload);
            msg_Info (p_demux, "Copyright : %s", (char *)payload);
            break;

        case 0x03: /* Track name */
            EnsureUTF8 ((char *)payload);
            msg_Info (p_demux, "Track name: %s", (char *)payload);
            break;

        case 0x04: /* Instrument name */
            EnsureUTF8 ((char *)payload);
            msg_Info (p_demux, "Instrument: %s", (char *)payload);
            break;

        case 0x05: /* Lyric (one syllable) */
            /*EnsureUTF8 ((char *)payload);*/
            break;

        case 0x06: /* Marker text */
            EnsureUTF8 ((char *)payload);
            msg_Info (p_demux, "Marker    : %s", (char *)payload);

        case 0x07: /* Cue point (WAVE filename) */
            EnsureUTF8 ((char *)payload);
            msg_Info (p_demux, "Cue point : %s", (char *)payload);
            break;

        case 0x08: /* Program/Patch name */
            EnsureUTF8 ((char *)payload);
            msg_Info (p_demux, "Patch name: %s", (char *)payload);
            break;

        case 0x09: /* MIDI port name */
            EnsureUTF8 ((char *)payload);
            msg_Dbg (p_demux, "MIDI port : %s", (char *)payload);
            break;

        case 0x2F: /* End of track */
            if (tr->end != stream_Tell (s))
            {
                msg_Err (p_demux, "misplaced end of track");
                ret = -1;
            }
            break;

        case 0x51: /* Tempo */
            if (length == 3)
            {
                uint32_t uspqn = (payload[0] << 16)
                               | (payload[1] << 8) | payload[2];
                unsigned tempo = 60 * 1000000 / (uspqn ? uspqn : 1);
                msg_Dbg (p_demux, "tempo: %uus/qn -> %u BPM",
                         (unsigned)uspqn, tempo);

                if (tempo < TEMPO_MIN)
                {
                    msg_Warn (p_demux, "tempo too slow -> %u BPM", TEMPO_MIN);
                    tempo = TEMPO_MIN;
                }
                else
                if (tempo > TEMPO_MAX)
                {
                    msg_Warn (p_demux, "tempo too fast -> %u BPM", TEMPO_MAX);
                    tempo = TEMPO_MAX;
                }
                date_Change (&p_sys->pts, p_sys->ppqn * tempo, 60);
            }
            else
                ret = -1;
            break;

        case 0x54: /* SMPTE offset */
            if (length == 5)
                msg_Warn (p_demux, "SMPTE offset not implemented");
            else
                ret = -1;
            break;

        case 0x58: /* Time signature */
            if (length == 4)
                ;
            else
                ret = -1;
            break;

        case 0x59: /* Key signature */
            if (length == 2)
                ;
            else
                ret = -1;
            break;

        case 0x7f: /* Proprietary event */
            msg_Dbg (p_demux, "ignored proprietary SMF Meta Event (%d bytes)",
                     length);
            break;

        default:
            msg_Warn (p_demux, "unknown SMF Meta Event type 0x%02X (%d bytes)",
                      type, length);
    }

    free (payload);
    return ret;
}
Exemplo n.º 5
0
Arquivo: h264.c Projeto: IAPark/vlc
/*****************************************************************************
 * Open: probe the packetizer and return score
 * When opening after demux, the packetizer is only loaded AFTER the decoder
 * That means that what you set in fmt_out is ignored by the decoder in this special case
 *****************************************************************************/
static int Open( vlc_object_t *p_this )
{
    decoder_t     *p_dec = (decoder_t*)p_this;
    decoder_sys_t *p_sys;
    int i;

    const bool b_avc = (p_dec->fmt_in.i_original_fourcc == VLC_FOURCC( 'a', 'v', 'c', '1' ));

    if( p_dec->fmt_in.i_codec != VLC_CODEC_H264 )
        return VLC_EGENERIC;
    if( b_avc && p_dec->fmt_in.i_extra < 7 )
        return VLC_EGENERIC;

    /* Allocate the memory needed to store the decoder's structure */
    if( ( p_dec->p_sys = p_sys = malloc( sizeof(decoder_sys_t) ) ) == NULL )
    {
        return VLC_ENOMEM;
    }

    p_sys->p_ccs = cc_storage_new();
    if( unlikely(!p_sys->p_ccs) )
    {
        free( p_dec->p_sys );
        return VLC_ENOMEM;
    }

    packetizer_Init( &p_sys->packetizer,
                     p_h264_startcode, sizeof(p_h264_startcode), startcode_FindAnnexB,
                     p_h264_startcode, 1, 5,
                     PacketizeReset, PacketizeParse, PacketizeValidate, p_dec );

    p_sys->b_slice = false;
    p_sys->p_frame = NULL;
    p_sys->pp_frame_last = &p_sys->p_frame;
    p_sys->p_sei = NULL;
    p_sys->pp_sei_last = &p_sys->p_sei;
    p_sys->b_new_sps = false;
    p_sys->b_new_pps = false;

    for( i = 0; i <= H264_SPS_ID_MAX; i++ )
    {
        p_sys->sps[i].p_sps = NULL;
        p_sys->sps[i].p_block = NULL;
    }
    p_sys->p_active_sps = NULL;
    for( i = 0; i <= H264_PPS_ID_MAX; i++ )
    {
        p_sys->pps[i].p_pps = NULL;
        p_sys->pps[i].p_block = NULL;
    }
    p_sys->p_active_pps = NULL;
    p_sys->i_recovery_frame_cnt = UINT_MAX;

    h264_slice_init( &p_sys->slice );

    p_sys->i_next_block_flags = 0;
    p_sys->b_recovered = false;
    p_sys->i_recoveryfnum = UINT_MAX;
    p_sys->i_frame_dts = VLC_TS_INVALID;
    p_sys->i_frame_pts = VLC_TS_INVALID;
    p_sys->i_dpb_output_delay = 0;

    /* POC */
    h264_poc_context_init( &p_sys->pocctx );
    p_sys->prevdatedpoc.pts = VLC_TS_INVALID;

    date_Init( &p_sys->dts, 30000 * 2, 1001 );
    date_Set( &p_sys->dts, VLC_TS_INVALID );

    /* Setup properties */
    es_format_Copy( &p_dec->fmt_out, &p_dec->fmt_in );
    p_dec->fmt_out.i_codec = VLC_CODEC_H264;
    p_dec->fmt_out.b_packetized = true;

    if( p_dec->fmt_in.video.i_frame_rate_base &&
        p_dec->fmt_in.video.i_frame_rate &&
        p_dec->fmt_in.video.i_frame_rate <= UINT_MAX / 2 )
    {
        date_Change( &p_sys->dts, p_dec->fmt_in.video.i_frame_rate * 2,
                                  p_dec->fmt_in.video.i_frame_rate_base );
    }

    if( b_avc )
    {
        /* This type of stream is produced by mp4 and matroska
         * when we want to store it in another streamformat, you need to convert
         * The fmt_in.p_extra should ALWAYS contain the avcC
         * The fmt_out.p_extra should contain all the SPS and PPS with 4 byte startcodes */
        if( h264_isavcC( p_dec->fmt_in.p_extra, p_dec->fmt_in.i_extra ) )
        {
            free( p_dec->fmt_out.p_extra );
            size_t i_size;
            p_dec->fmt_out.p_extra = h264_avcC_to_AnnexB_NAL( p_dec->fmt_in.p_extra,
                                                              p_dec->fmt_in.i_extra,
                                                             &i_size,
                                                             &p_sys->i_avcC_length_size );
            p_dec->fmt_out.i_extra = i_size;
            p_sys->b_recovered = !!p_dec->fmt_out.i_extra;

            if(!p_dec->fmt_out.p_extra)
            {
                msg_Err( p_dec, "Invalid AVC extradata");
                Close( p_this );
                return VLC_EGENERIC;
            }
        }
        else
        {
            msg_Err( p_dec, "Invalid or missing AVC extradata");
            Close( p_this );
            return VLC_EGENERIC;
        }

        /* Set callback */
        p_dec->pf_packetize = PacketizeAVC1;
    }
    else
    {
        /* This type of stream contains data with 3 of 4 byte startcodes
         * The fmt_in.p_extra MAY contain SPS/PPS with 4 byte startcodes
         * The fmt_out.p_extra should be the same */

        /* Set callback */
        p_dec->pf_packetize = Packetize;
    }

    /* */
    if( p_dec->fmt_out.i_extra > 0 )
    {
        packetizer_Header( &p_sys->packetizer,
                           p_dec->fmt_out.p_extra, p_dec->fmt_out.i_extra );
    }

    if( b_avc )
    {
        /* FIXME: that's not correct for every AVC */
        if( !p_sys->b_new_pps || !p_sys->b_new_sps )
        {
            msg_Err( p_dec, "Invalid or missing SPS %d or PPS %d in AVC extradata",
                     p_sys->b_new_sps, p_sys->b_new_pps );
            Close( p_this );
            return VLC_EGENERIC;
        }

        msg_Dbg( p_dec, "Packetizer fed with AVC, nal length size=%d",
                         p_sys->i_avcC_length_size );
    }

    /* CC are the same for H264/AVC in T35 sections (ETSI TS 101 154)  */
    p_dec->pf_get_cc = GetCc;
    p_dec->pf_flush = PacketizeFlush;

    return VLC_SUCCESS;
}