Пример #1
0
static int OpenAudioDev( demux_t *p_demux, const char *psz_device )
{
    demux_sys_t *p_sys = p_demux->p_sys;
    if( OpenAudioDevAlsa( p_demux, psz_device ) != VLC_SUCCESS )
        return VLC_EGENERIC;

    msg_Dbg( p_demux, "opened adev=`%s' %s %dHz",
             psz_device, p_sys->b_stereo ? "stereo" : "mono",
             p_sys->i_sample_rate );

    es_format_t fmt;
    es_format_Init( &fmt, AUDIO_ES, VLC_FOURCC('a','r','a','w') );

    fmt.audio.i_channels = p_sys->b_stereo ? 2 : 1;
    fmt.audio.i_rate = p_sys->i_sample_rate;
    fmt.audio.i_bitspersample = 16;
    fmt.audio.i_blockalign = fmt.audio.i_channels * fmt.audio.i_bitspersample / 8;
    fmt.i_bitrate = fmt.audio.i_channels * fmt.audio.i_rate * fmt.audio.i_bitspersample;

    msg_Dbg( p_demux, "new audio es %d channels %dHz",
             fmt.audio.i_channels, fmt.audio.i_rate );

    p_sys->p_es = es_out_Add( p_demux->out, &fmt );

    return VLC_SUCCESS;
}
Пример #2
0
static int Open (vlc_object_t *obj)
{
    demux_t *demux = (demux_t *)obj;
    demux_sys_t *sys = vlc_malloc(obj, sizeof (*sys));

    if (unlikely(sys == NULL))
        return VLC_ENOMEM;

    es_format_t fmt;
    es_format_Init (&fmt, SPU_ES, VLC_CODEC_ITU_T140);
    sys->es = es_out_Add (demux->out, &fmt);

    unsigned num, den;
    if (var_InheritURational (demux, &num, &den, "timecode-fps")
     || !num || !den)
    {
        msg_Err (demux, "invalid frame rate");
        return VLC_EGENERIC;
    }

    date_Init (&sys->date, num, den);
    date_Set (&sys->date, VLC_TS_0);
    sys->next_time = VLC_TS_INVALID;

    demux->p_sys = sys;
    demux->pf_demux   = Demux;
    demux->pf_control = Control;
    return VLC_SUCCESS;
}
Пример #3
0
    virtual HRESULT STDMETHODCALLTYPE VideoInputFormatChanged(BMDVideoInputFormatChangedEvents events, IDeckLinkDisplayMode *mode, BMDDetectedVideoInputFormatFlags)
    {
        demux_sys_t *sys = demux_->p_sys;

        if( !(events & bmdVideoInputDisplayModeChanged ))
            return S_OK;

        const char *mode_name;
        if (mode->GetName(&mode_name) != S_OK)
            mode_name = "unknown";

        msg_Dbg(demux_, "Video input format changed to %s", mode_name);
        if (!sys->autodetect) {
            msg_Err(demux_, "Video format detection disabled");
            return S_OK;
        }

        es_out_Del(demux_->out, sys->video_es);
        es_format_t video_fmt = GetModeSettings(demux_, mode);
        sys->video_es = es_out_Add(demux_->out, &video_fmt);

        BMDPixelFormat fmt = sys->tenbits ? bmdFormat10BitYUV : bmdFormat8BitYUV;
        sys->input->PauseStreams();
        sys->input->EnableVideoInput( mode->GetDisplayMode(), fmt, bmdVideoInputEnableFormatDetection );
        sys->input->FlushStreams();
        sys->input->StartStreams();

        return S_OK;
    }
Пример #4
0
/*****************************************************************************
 * Open: check file and initializes structures
 *****************************************************************************/
static int Open( vlc_object_t * p_this )
{
    demux_t     *p_demux = (demux_t*)p_this;
    demux_sys_t *p_sys;

    /* Identify cdg file by extension, as there is no simple way to
     * detect it */
    if( !demux_IsPathExtension( p_demux, ".cdg" ) && !demux_IsForced( p_demux, "cdg" ) )
        return VLC_EGENERIC;

    /* CDG file size has to be multiple of CDG_FRAME_SIZE (it works even
     * if size is unknown ie 0) */
//    if( (stream_Size( p_demux->s ) % CDG_FRAME_SIZE) != 0 )
//    {
//        msg_Err( p_demux, "Reject CDG file based on its size" );
//        return VLC_EGENERIC;
//    }

    p_demux->pf_demux   = Demux;
    p_demux->pf_control = Control;
    p_demux->p_sys      = p_sys = malloc( sizeof( demux_sys_t ) );

    /* */
    es_format_Init( &p_sys->fmt, VIDEO_ES, VLC_CODEC_CDG );
    p_sys->fmt.video.i_width  = 300-2*6;
    p_sys->fmt.video.i_height = 216-2*12 ;

    p_sys->p_es = es_out_Add( p_demux->out, &p_sys->fmt );

    /* There is CDG_FRAME_RATE frames per second */
    date_Init( &p_sys->pts, CDG_FRAME_RATE, 1 );
    date_Set( &p_sys->pts, 1 );

    return VLC_SUCCESS;
}
Пример #5
0
/*****************************************************************************
 * Demux: reads and demuxes data packets
 *****************************************************************************
 * Returns -1 in case of error, 0 in case of EOF, 1 otherwise
 *****************************************************************************/
static int Demux( demux_t *p_demux)
{
    demux_sys_t *p_sys = p_demux->p_sys;
    block_t *p_block_in, *p_block_out;

    if( p_sys->i_state == DIRAC_DEMUX_DISCONT )
    {
        p_sys->i_state++;
        p_block_in = block_Alloc( 128 );
        if( p_block_in )
        {
            p_block_in->i_flags = BLOCK_FLAG_DISCONTINUITY | BLOCK_FLAG_CORRUPTED;
        }
    }
    else
    {
        p_block_in = stream_Block( p_demux->s, DIRAC_PACKET_SIZE );
        if( !p_block_in )
        {
            return 0;
        }
        if ( p_sys->i_state == DIRAC_DEMUX_FIRST)
        {
            p_sys->i_state++;
            /* by default, timestamps are invalid.
             * Except when we need an anchor point */
            p_block_in->i_dts = VLC_TS_0;
        }
    }

    while( (p_block_out = p_sys->p_packetizer->pf_packetize( p_sys->p_packetizer, &p_block_in )) )
    {
        while( p_block_out )
        {
            block_t *p_next = p_block_out->p_next;
            p_block_out->p_next = NULL;

            if( p_sys->p_es == NULL )
                p_sys->p_es = es_out_Add( p_demux->out, &p_sys->p_packetizer->fmt_out);

            p_block_out->i_dts += p_sys->i_dtsoffset;
            p_sys->i_dts = p_block_out->i_dts;

            /* track low watermark for pts_offset -- can be used to show
             * when it is too large */
            mtime_t i_delay = p_block_out->i_pts - p_block_out->i_dts;
            if( p_sys->i_pts_offset_lowtide > i_delay )
            {
                p_sys->i_pts_offset_lowtide = i_delay;
            }

            es_out_Control( p_demux->out, ES_OUT_SET_PCR, p_block_out->i_dts );
            es_out_Send( p_demux->out, p_sys->p_es, p_block_out );

            p_block_out = p_next;
        }
    }
    return 1;
}
Пример #6
0
/*****************************************************************************
 * Open: initializes demux structures
 *****************************************************************************/
static int Open( vlc_object_t * p_this )
{
    demux_t     *p_demux = (demux_t*)p_this;
    demux_sys_t *p_sys;
    bool   b_forced = false;

    const uint8_t *p_peek;

    es_format_t  fmt;

    if( vlc_stream_Peek( p_demux->s, &p_peek, 4 ) < 4 )
    {
        msg_Dbg( p_demux, "cannot peek" );
        return VLC_EGENERIC;
    }

    if( p_demux->obj.force )
        b_forced = true;

    if( p_peek[0] != 0x00 || p_peek[1] != 0x00 || p_peek[2] != 0x01 )
    {
        if( !b_forced ) return VLC_EGENERIC;

        msg_Err( p_demux, "this doesn't look like an MPEG ES stream, continuing" );
    }

    if( p_peek[3] > 0xb9 )
    {
        if( !b_forced ) return VLC_EGENERIC;
        msg_Err( p_demux, "this seems to be a system stream (PS plug-in ?), but continuing" );
    }

    p_demux->pf_demux  = Demux;
    p_demux->pf_control= Control;
    p_demux->p_sys     = p_sys = malloc( sizeof( demux_sys_t ) );
    p_sys->b_start     = true;
    p_sys->p_es        = NULL;

    /* Load the mpegvideo packetizer */
    es_format_Init( &fmt, VIDEO_ES, VLC_CODEC_MPGV );
    p_sys->p_packetizer = demux_PacketizerNew( p_demux, &fmt, "mpeg video" );
    if( !p_sys->p_packetizer )
    {
        free( p_sys );
        return VLC_EGENERIC;
    }

    /* create the output */
    p_sys->p_es = es_out_Add( p_demux->out, &fmt );
    if( p_sys->p_es == NULL )
    {
        Close( p_this );
        return VLC_EGENERIC;
    }

    return VLC_SUCCESS;
}
Пример #7
0
vlc_v4l2_vbi_t *OpenVBI (demux_t *demux, const char *psz_device)
{
    vlc_v4l2_vbi_t *vbi = malloc (sizeof (*vbi));
    if (unlikely(vbi == NULL))
        return NULL;

    int rawfd = vlc_open (psz_device, O_RDWR);
    if (rawfd == -1)
    {
        msg_Err (demux, "cannot open device '%s': %m", psz_device);
        goto err;
    }

    //Can put more in here. See osd.c in zvbi package.
    unsigned int services = VBI_SLICED_CAPTION_525;
    char *errstr = NULL;

    vbi->cap = vbi_capture_v4l2k_new (psz_device, rawfd,
                                      /* buffers */ 5,
                                      &services,
                                      /* strict */ 1,
                                      &errstr,
                                      /* verbose */ 1);
    if (vbi->cap == NULL)
    {
        msg_Err (demux, "cannot capture VBI data: %s", errstr);
        free (errstr);
        goto err;
    }

    for (unsigned i = 0; i < VBI_NUM_CC_STREAMS; i++)
    {
        es_format_t fmt;

        es_format_Init (&fmt, SPU_ES, VLC_FOURCC('c', 'c', '1' + i, ' '));
        if (asprintf (&fmt.psz_description, "Closed captions %d", i + 1) >= 0)
        {
            msg_Dbg (demux, "new spu es %4.4s", (char *)&fmt.i_codec);
            vbi->es[i] = es_out_Add (demux->out, &fmt);
        }
    }

    /* Do a single read and throw away the results so that ZVBI calls
       the STREAMON ioctl() */
    GrabVBI(demux, vbi);

    return vbi;
err:
    free (vbi);
    return NULL;
}
Пример #8
0
/*****************************************************************************
 * Demux: reads and demuxes data packets
 *****************************************************************************
 * Returns -1 in case of error, 0 in case of EOF, 1 otherwise
 *****************************************************************************/
static int Demux( demux_t *p_demux)
{
    demux_sys_t *p_sys = p_demux->p_sys;
    block_t *p_block_in, *p_block_out;

    if( ( p_block_in = stream_Block( p_demux->s, VC1_PACKET_SIZE ) ) == NULL )
        return 0;

    /*  */
    p_block_in->i_dts = VLC_TS_0;
    p_block_in->i_pts = VLC_TS_0;

    while( (p_block_out = p_sys->p_packetizer->pf_packetize( p_sys->p_packetizer, &p_block_in )) )
    {
        while( p_block_out )
        {
            block_t *p_next = p_block_out->p_next;

            p_block_out->p_next = NULL;

            if( p_sys->p_es == NULL )
            {
                p_sys->p_packetizer->fmt_out.b_packetized = true;
                p_sys->p_es = es_out_Add( p_demux->out, &p_sys->p_packetizer->fmt_out);
            }

            es_out_Control( p_demux->out, ES_OUT_SET_PCR, VLC_TS_0 + p_sys->i_dts );
            p_block_out->i_dts = VLC_TS_0 + p_sys->i_dts;
            p_block_out->i_pts = VLC_TS_0 + p_sys->i_dts;

            es_out_Send( p_demux->out, p_sys->p_es, p_block_out );

            p_block_out = p_next;

            if( p_sys->p_packetizer->fmt_out.video.i_frame_rate > 0 &&
                p_sys->p_packetizer->fmt_out.video.i_frame_rate_base > 0 )
                p_sys->i_dts += INT64_C(1000000) *
                    p_sys->p_packetizer->fmt_out.video.i_frame_rate_base /
                    p_sys->p_packetizer->fmt_out.video.i_frame_rate;
            else if( p_sys->f_fps > 0.001 )
                p_sys->i_dts += (int64_t)((double)1000000.0 / p_sys->f_fps);
            else
                p_sys->i_dts += INT64_C(1000000) / 25;
        }
    }
    return 1;
}
Пример #9
0
Файл: rdp.c Проект: mstorsjo/vlc
static void desktopResizeHandler( rdpContext *p_context )
{
    vlcrdp_context_t * p_vlccontext = (vlcrdp_context_t *) p_context;
    demux_sys_t *p_sys = p_vlccontext->p_demux->p_sys;
    rdpGdi *p_gdi = p_context->gdi;

    if ( p_sys->es )
    {
        es_out_Del( p_vlccontext->p_demux->out, p_sys->es );
        p_sys->es = NULL;
    }

    /* Now init and fill es format */
    vlc_fourcc_t i_chroma;
    switch( p_gdi->bytesPerPixel )
    {
        default:
        case 16:
            i_chroma = VLC_CODEC_RGB16;
            break;
        case 24:
            i_chroma = VLC_CODEC_RGB24;
            break;
        case 32:
            i_chroma = VLC_CODEC_RGB32;
            break;
    }
    es_format_t fmt;
    es_format_Init( &fmt, VIDEO_ES, i_chroma );

    fmt.video.i_chroma = i_chroma;
    fmt.video.i_visible_width =
    fmt.video.i_width = p_gdi->width;
    fmt.video.i_visible_height =
    fmt.video.i_height = p_gdi->height;
    fmt.video.i_frame_rate_base = 1000;
    fmt.video.i_frame_rate = 1000 * p_sys->f_fps;
    p_sys->i_framebuffersize = p_gdi->width * p_gdi->height * p_gdi->bytesPerPixel;

    if ( p_sys->p_block )
        p_sys->p_block = block_Realloc( p_sys->p_block, 0, p_sys->i_framebuffersize );
    else
        p_sys->p_block = block_Alloc( p_sys->i_framebuffersize );

    p_sys->es = es_out_Add( p_vlccontext->p_demux->out, &fmt );
}
Пример #10
0
static void output_mode_cb(void *data, struct wl_output *output,
                           uint32_t flags, int32_t width, int32_t height,
                           int32_t refresh)
{
    demux_t *demux = data;
    demux_sys_t *sys = demux->p_sys;

    msg_Dbg(demux, "output mode: 0x%08"PRIX32" %"PRId32"x%"PRId32
            " %"PRId32"mHz%s", flags, width, height, refresh,
            (flags & WL_OUTPUT_MODE_CURRENT) ? " (current)" : "");

    if (!(flags & WL_OUTPUT_MODE_CURRENT))
        return;
    if (width <= sys->x || height <= sys->y)
        return;

    if (sys->es != NULL)
        es_out_Del(demux->out, sys->es);

    es_format_t fmt;

    es_format_Init(&fmt, VIDEO_ES, VLC_CODEC_RGB32);
    fmt.video.i_chroma = VLC_CODEC_RGB32;
    fmt.video.i_bits_per_pixel = 32;
    fmt.video.i_sar_num = fmt.video.i_sar_den = 1;
    fmt.video.i_frame_rate = lroundf(1000.f * sys->rate);
    fmt.video.i_frame_rate_base = 1000;
    fmt.video.i_width = width;

    if (sys->w != 0 && width > sys->w + sys->x)
        fmt.video.i_visible_width = sys->w;
    else
        fmt.video.i_visible_width = width - sys->x;

    if (sys->h != 0 && height > sys->h + sys->y)
        fmt.video.i_visible_height = sys->h;
    else
        fmt.video.i_visible_height = height - sys->y;

    fmt.video.i_height = fmt.video.i_visible_height;

    sys->es = es_out_Add(demux->out, &fmt);
    sys->width = width;
    sys->height = height;
    (void) output;
}
Пример #11
0
/*****************************************************************************
 * Demux: reads and demuxes data packets
 *****************************************************************************
 * Returns -1 in case of error, 0 in case of EOF, 1 otherwise
 *****************************************************************************/
static int Demux( demux_t *p_demux )
{
    demux_sys_t *p_sys = p_demux->p_sys;
    block_t     *p_block_in, *p_block_out;

    if( !( p_block_in = stream_Block( p_demux->s, FLAC_PACKET_SIZE ) ) )
        return 0;

    p_block_in->i_pts = p_block_in->i_dts = p_sys->b_start ? VLC_TS_0 : VLC_TS_INVALID;
    p_sys->b_start = false;

    while( (p_block_out = p_sys->p_packetizer->pf_packetize(
                p_sys->p_packetizer, &p_block_in )) )
    {
        while( p_block_out )
        {
            block_t *p_next = p_block_out->p_next;

            p_block_out->p_next = NULL;

            if( p_sys->p_es == NULL )
            {
                p_sys->p_packetizer->fmt_out.b_packetized = true;
                p_sys->p_packetizer->fmt_out.audio_replay_gain = p_sys->replay_gain;
                p_sys->p_es = es_out_Add( p_demux->out, &p_sys->p_packetizer->fmt_out);
            }

            p_sys->i_pts = p_block_out->i_dts - VLC_TS_0;

            /* Correct timestamp */
            p_block_out->i_pts += p_sys->i_time_offset;
            p_block_out->i_dts += p_sys->i_time_offset;

            /* set PCR */
            es_out_Control( p_demux->out, ES_OUT_SET_PCR, p_block_out->i_dts );

            es_out_Send( p_demux->out, p_sys->p_es, p_block_out );

            p_block_out = p_next;
        }
    }
    return 1;
}
Пример #12
0
/*****************************************************************************
 * Demux: reads and demuxes data packets
 *****************************************************************************
 * Returns -1 in case of error, 0 in case of EOF, 1 otherwise
 *****************************************************************************/
static int Demux( demux_t *p_demux)
{
    demux_sys_t *p_sys = p_demux->p_sys;
    block_t *p_block_in, *p_block_out;

    if( ( p_block_in = stream_Block( p_demux->s, H264_PACKET_SIZE ) ) == NULL )
    {
        return 0;
    }

    /* m4v demuxer doesn't set pts/dts at all */
    p_block_in->i_dts = 1;
    p_block_in->i_pts = 1;

    while( (p_block_out = p_sys->p_packetizer->pf_packetize( p_sys->p_packetizer, &p_block_in )) )
    {
        while( p_block_out )
        {
            block_t *p_next = p_block_out->p_next;

            p_block_out->p_next = NULL;

            if( p_sys->p_es == NULL )
            {
                p_sys->p_packetizer->fmt_out.b_packetized = VLC_TRUE;
                p_sys->p_es = es_out_Add( p_demux->out, &p_sys->p_packetizer->fmt_out);
            }

            es_out_Control( p_demux->out, ES_OUT_SET_PCR, p_sys->i_dts );
            p_block_out->i_dts = p_sys->i_dts;
            p_block_out->i_pts = p_sys->i_dts;

            es_out_Send( p_demux->out, p_sys->p_es, p_block_out );

            p_block_out = p_next;

            p_sys->i_dts += (int64_t)((double)1000000.0 / p_sys->f_fps);
        }
    }
    return 1;
}
Пример #13
0
/*****************************************************************************
 * Demux: reads and demuxes data packets
 *****************************************************************************
 * Returns -1 in case of error, 0 in case of EOF, 1 otherwise
 *****************************************************************************/
static int Demux( demux_t *p_demux )
{
    demux_sys_t *p_sys = p_demux->p_sys;
    block_t     *p_block_in, *p_block_out;

    bool b_eof = !( p_block_in = stream_Block( p_demux->s, FLAC_PACKET_SIZE ) );

    if ( p_block_in )
    {
        p_block_in->i_pts = p_block_in->i_dts = p_sys->b_start ? VLC_TS_0 : VLC_TS_INVALID;
        p_sys->b_start = false;
    }

    while( (p_block_out = p_sys->p_packetizer->pf_packetize(
                p_sys->p_packetizer, (p_block_in) ? &p_block_in : NULL )) )
    {
        while( p_block_out )
        {
            block_t *p_next = p_block_out->p_next;

            p_block_out->p_next = NULL;

            if( p_sys->p_es == NULL )
            {
                p_sys->p_packetizer->fmt_out.b_packetized = true;
                p_sys->p_es = es_out_Add( p_demux->out, &p_sys->p_packetizer->fmt_out);
            }

            p_sys->i_pts = p_block_out->i_dts;

            /* set PCR */
            es_out_Control( p_demux->out, ES_OUT_SET_PCR, p_block_out->i_dts );

            es_out_Send( p_demux->out, p_sys->p_es, p_block_out );

            p_block_out = p_next;
        }
    }
    return !b_eof;
}
Пример #14
0
/*****************************************************************************
 * Demux: reads and demuxes data packets
 *****************************************************************************
 * Returns -1 in case of error, 0 in case of EOF, 1 otherwise
 *****************************************************************************/
static int Demux( demux_t *p_demux)
{
    demux_sys_t *p_sys = p_demux->p_sys;
    block_t *p_block_in, *p_block_out;

    if( ( p_block_in = stream_Block( p_demux->s, M4A_PACKET_SIZE ) ) == NULL )
    {
        return 0;
    }

    p_block_in->i_pts = p_block_in->i_dts = p_sys->b_start ? 1 : 0;
    p_sys->b_start = VLC_FALSE;

    while( (p_block_out = p_sys->p_packetizer->pf_packetize(
                                          p_sys->p_packetizer, &p_block_in )) )
    {
        while( p_block_out )
        {
            block_t *p_next = p_block_out->p_next;

            if( p_sys->p_es == NULL )
            {
                p_sys->p_packetizer->fmt_out.b_packetized = VLC_TRUE;
                p_sys->p_es = es_out_Add( p_demux->out,
                                          &p_sys->p_packetizer->fmt_out);
            }

            es_out_Control( p_demux->out, ES_OUT_SET_PCR, p_block_out->i_dts );

            p_block_out->p_next = NULL;
            es_out_Send( p_demux->out, p_sys->p_es, p_block_out );

            p_block_out = p_next;
        }
    }
    return 1;
}
Пример #15
0
int OpenDemux( vlc_object_t* p_this )
{
    demux_t     *p_demux = (demux_t*)p_this;
    demux_sys_t *p_sys;

    const uint8_t *p_peek;
    ssize_t i_peek = vlc_stream_Peek( p_demux->s, &p_peek, 2048 );
    if( unlikely( i_peek <= 32 ) )
        return VLC_EGENERIC;

    const char *psz_xml = (const char *) p_peek;
    size_t i_xml  = i_peek;

    /* Try to probe without xml module/loading the full document */
    char *psz_alloc = NULL;
    switch( GetQWBE(p_peek) )
    {
        /* See RFC 3023 Part 4 */
        case UINT64_C(0xFFFE3C003F007800): /* UTF16 BOM<? */
        case UINT64_C(0xFFFE3C003F007400): /* UTF16 BOM<t */
        case UINT64_C(0xFEFF003C003F0078): /* UTF16 BOM<? */
        case UINT64_C(0xFEFF003C003F0074): /* UTF16 BOM<t */
            psz_alloc = FromCharset( "UTF-16", p_peek, i_peek );
            break;
        case UINT64_C(0x3C003F0078006D00): /* UTF16-LE <?xm */
        case UINT64_C(0x3C003F0074007400): /* UTF16-LE <tt */
            psz_alloc = FromCharset( "UTF-16LE", p_peek, i_peek );
            break;
        case UINT64_C(0x003C003F0078006D): /* UTF16-BE <?xm */
        case UINT64_C(0x003C003F00740074): /* UTF16-BE <tt */
            psz_alloc = FromCharset( "UTF-16BE", p_peek, i_peek );
            break;
        case UINT64_C(0xEFBBBF3C3F786D6C): /* UTF8 BOM<?xml */
        case UINT64_C(0x3C3F786D6C207665): /* UTF8 <?xml ve */
        case UINT64_C(0xEFBBBF3C74742078): /* UTF8 BOM<tt x*/
            break;
        default:
            if(GetDWBE(p_peek) != UINT32_C(0x3C747420)) /* tt node without xml document marker */
                return VLC_EGENERIC;
    }

    if( psz_alloc )
    {
        psz_xml = psz_alloc;
        i_xml = strlen( psz_alloc );
    }

    /* Simplified probing. Valid TTML must have a namespace declaration */
    const char *psz_tt = strnstr( psz_xml, "tt ", i_xml );
    if( !psz_tt || psz_tt == psz_xml ||
        (psz_tt[-1] != ':' && psz_tt[-1] != '<') )
    {
        free( psz_alloc );
        return VLC_EGENERIC;
    }
    else
    {
        const char * const rgsz[] =
        {
            "=\"http://www.w3.org/ns/ttml\"",
            "=\"http://www.w3.org/2004/11/ttaf1\"",
            "=\"http://www.w3.org/2006/04/ttaf1\"",
            "=\"http://www.w3.org/2006/10/ttaf1\"",
        };
        const char *psz_ns = NULL;
        for( size_t i=0; i<ARRAY_SIZE(rgsz) && !psz_ns; i++ )
        {
            psz_ns = strnstr( psz_xml, rgsz[i],
                              i_xml - (psz_tt - psz_xml) );
        }
        free( psz_alloc );
        if( !psz_ns )
            return VLC_EGENERIC;
    }

    p_demux->p_sys = p_sys = calloc( 1, sizeof( *p_sys ) );
    if( unlikely( p_sys == NULL ) )
        return VLC_ENOMEM;

    p_sys->b_first_time = true;
    p_sys->temporal_extent.i_type = TT_TIMINGS_PARALLEL;
    tt_time_Init( &p_sys->temporal_extent.begin );
    tt_time_Init( &p_sys->temporal_extent.end );
    tt_time_Init( &p_sys->temporal_extent.dur );
    p_sys->temporal_extent.begin.base = 0;

    p_sys->p_xml = xml_Create( p_demux );
    if( !p_sys->p_xml )
        goto error;

    p_sys->p_reader = xml_ReaderCreate( p_sys->p_xml, p_demux->s );
    if( !p_sys->p_reader )
        goto error;

#ifndef TTML_DEMUX_DEBUG
    p_sys->p_reader->obj.flags |= OBJECT_FLAGS_QUIET;
#endif

    if( ReadTTML( p_demux ) != VLC_SUCCESS )
        goto error;

    tt_timings_Resolve( (tt_basenode_t *) p_sys->p_rootnode, &p_sys->temporal_extent,
                        &p_sys->times.p_array, &p_sys->times.i_count );

#ifdef TTML_DEMUX_DEBUG
    {
        struct vlc_memstream stream;

        if( vlc_memstream_open( &stream ) )
            goto error;

        tt_time_t t;
        tt_time_Init( &t );
        tt_node_ToText( &stream, (tt_basenode_t*)p_sys->p_rootnode, &t /* invalid */ );

        vlc_memstream_putc( &stream, '\0' );

        if( vlc_memstream_close( &stream ) == VLC_SUCCESS )
        {
            msg_Dbg( p_demux, "%s", stream.ptr );
            free( stream.ptr );
        }
    }
#endif

    p_demux->pf_demux = Demux;
    p_demux->pf_control = Control;

    es_format_t fmt;
    es_format_Init( &fmt, SPU_ES, VLC_CODEC_TTML );
    p_sys->p_es = es_out_Add( p_demux->out, &fmt );
    if( !p_sys->p_es )
        goto error;

    es_format_Clean( &fmt );

    return VLC_SUCCESS;

error:
    CloseDemux( p_demux );

    return VLC_EGENERIC;
}
Пример #16
0
/*****************************************************************************
 * Open: initializes demux structures
 *****************************************************************************/
static int Open( vlc_object_t * p_this )
{
    demux_t     *p_demux = (demux_t*)p_this;
    demux_sys_t *p_sys;
    const uint8_t *p_peek;
    es_format_t fmt;

    if( stream_Peek( p_demux->s, &p_peek, 5 ) < 5 ) return VLC_EGENERIC;

    if( p_peek[0] != 0x00 || p_peek[1] != 0x00 ||
        p_peek[2] != 0x00 || p_peek[3] != 0x01 ||
        (p_peek[4]&0xFE) != 0x40 ) /* VPS & forbidden zero bit*/
    {
        if( !p_demux->b_force )
        {
            msg_Warn( p_demux, "hevc module discarded (no startcode)" );
            return VLC_EGENERIC;
        }

        msg_Err( p_demux, "this doesn't look like a HEVC ES stream, "
                 "continuing anyway" );
    }

    p_demux->p_sys     = p_sys = malloc( sizeof( demux_sys_t ) );

    if( !p_demux->p_sys )
        return VLC_ENOMEM;

    p_sys->p_es        = NULL;
    p_sys->i_dts       = VLC_TS_0;
    p_sys->f_force_fps = var_CreateGetFloat( p_demux, "hevc-force-fps" );
    if( p_sys->f_force_fps != 0.0f )
    {
        p_sys->f_fps = ( p_sys->f_force_fps < 0.001f )? 0.001f:
            p_sys->f_force_fps;
        msg_Dbg( p_demux, "using %.2f fps", (double) p_sys->f_fps );
    }
    else
        p_sys->f_fps = 0.0f;

    /* Load the hevc packetizer */
    es_format_Init( &fmt, VIDEO_ES, VLC_CODEC_HEVC );
    p_sys->p_packetizer = demux_PacketizerNew( p_demux, &fmt, "hevc" );
    if( !p_sys->p_packetizer )
    {
        free( p_sys );
        return VLC_EGENERIC;
    }

    p_sys->p_packetizer->fmt_out.b_packetized = true;
    p_sys->p_es = es_out_Add( p_demux->out, &p_sys->p_packetizer->fmt_out);

    if( !p_sys->p_es )
    {
        demux_PacketizerDestroy( p_sys->p_packetizer );
        free( p_sys );
        return VLC_ENOMEM;
    }
    p_demux->pf_demux  = Demux;
    p_demux->pf_control= Control;

    return VLC_SUCCESS;
}
Пример #17
0
/*****************************************************************************
 * Open: initializes ES structures
 *****************************************************************************/
static int Open( vlc_object_t * p_this )
{
    demux_t     *p_demux = (demux_t*)p_this;
    demux_sys_t *p_sys;
    byte_t      *p_peek;
    int         i_peek = 0;
    vlc_bool_t  b_big_endian = 0; /* Arbitrary initialisation */

    /* Check if we are dealing with a WAV file */
    if( stream_Peek( p_demux->s, &p_peek, 12 ) == 12 &&
        !memcmp( p_peek, "RIFF", 4 ) && !memcmp( p_peek + 8, "WAVE", 4 ) )
    {
        int i_size;

        /* Skip the wave header */
        i_peek = 12 + 8;
        while( stream_Peek( p_demux->s, &p_peek, i_peek ) == i_peek &&
               memcmp( p_peek + i_peek - 8, "data", 4 ) )
        {
            i_peek += GetDWLE( p_peek + i_peek - 4 ) + 8;
        }

        /* TODO: should check wave format and sample_rate */

        /* Some A52 wav files don't begin with a sync code so we do a more
         * extensive search */
        i_size = stream_Peek( p_demux->s, &p_peek, i_peek + A52_PACKET_SIZE * 2);
        i_size -= (PCM_FRAME_SIZE + A52_MAX_HEADER_SIZE);

        while( i_peek < i_size )
        {
            if( CheckSync( p_peek + i_peek, &b_big_endian ) != VLC_SUCCESS )
                /* The data is stored in 16 bits words */
                i_peek += 2;
            else
            {
                /* Check following sync code */
                if( CheckSync( p_peek + i_peek + PCM_FRAME_SIZE,
                               &b_big_endian ) != VLC_SUCCESS )
                {
                    i_peek += 2;
                    continue;
                }

                break;
            }
        }
    }

    /* Have a peep at the show. */
    if( stream_Peek( p_demux->s, &p_peek, i_peek + A52_MAX_HEADER_SIZE * 2 ) <
        i_peek + A52_MAX_HEADER_SIZE * 2 )
    {
        /* Stream too short */
        msg_Warn( p_demux, "cannot peek()" );
        return VLC_EGENERIC;
    }

    if( CheckSync( p_peek + i_peek, &b_big_endian ) != VLC_SUCCESS )
    {
        if( strncmp( p_demux->psz_demux, "a52", 3 ) )
        {
            return VLC_EGENERIC;
        }

        /* User forced */
        msg_Err( p_demux, "this doesn't look like a A52 audio stream, "
                 "continuing anyway" );
    }

    /* Fill p_demux fields */
    p_demux->pf_demux = Demux;
    p_demux->pf_control = Control;
    p_demux->p_sys = p_sys = malloc( sizeof( demux_sys_t ) );
    p_sys->b_start = VLC_TRUE;
    p_sys->i_mux_rate = 0;
    p_sys->b_big_endian = b_big_endian;

    /*
     * Load the A52 packetizer
     */
    p_sys->p_packetizer = vlc_object_create( p_demux, VLC_OBJECT_DECODER );
    p_sys->p_packetizer->pf_decode_audio = 0;
    p_sys->p_packetizer->pf_decode_video = 0;
    p_sys->p_packetizer->pf_decode_sub = 0;
    p_sys->p_packetizer->pf_packetize = 0;

    /* Initialization of decoder structure */
    es_format_Init( &p_sys->p_packetizer->fmt_in, AUDIO_ES,
                    VLC_FOURCC( 'a', '5', '2', ' ' ) );

    p_sys->p_packetizer->p_module =
        module_Need( p_sys->p_packetizer, "packetizer", NULL, 0 );
    if( !p_sys->p_packetizer->p_module )
    {
        msg_Err( p_demux, "cannot find A52 packetizer" );
        return VLC_EGENERIC;
    }

    /* Create one program */
    p_sys->p_es = es_out_Add( p_demux->out, &p_sys->p_packetizer->fmt_in );

    return VLC_SUCCESS;
}
Пример #18
0
Файл: rtp.c Проект: Geal/vlc
void *codec_init (demux_t *demux, es_format_t *fmt)
{
    if (fmt->i_cat == AUDIO_ES)
        aout_FormatPrepare (&fmt->audio);
    return es_out_Add (demux->out, fmt);
}
Пример #19
0
/*****************************************************************************
 * Open: check file and initializes structures
 *****************************************************************************/
static int Open( vlc_object_t * p_this )
{
    demux_t     *p_demux = (demux_t*)p_this;
    int         i_size;
    bool        b_matched = false;

    if( IsMxpeg( p_demux->s ) && !p_demux->b_force )
        // let avformat handle this case
        return VLC_EGENERIC;

    demux_sys_t *p_sys = (demux_sys_t *)malloc( sizeof( demux_sys_t ) );			// sunqueen modify
    if( unlikely(p_sys == NULL) )
        return VLC_ENOMEM;

    p_demux->pf_control = Control;
    p_demux->p_sys      = p_sys;
    p_sys->p_es         = NULL;
    p_sys->i_time       = VLC_TS_0;
    p_sys->i_level      = 0;

    p_sys->psz_separator = NULL;
    p_sys->i_frame_size_estimate = 15 * 1024;

    char *content_type = stream_ContentType( p_demux->s );
    if ( content_type )
    {
        //FIXME: this is not fully match to RFC
        char* boundary = strstr( content_type, "boundary=" );
        if( boundary )
        {
	    boundary += strlen( "boundary=" );
	    size_t len = strlen( boundary );
	    if( len > 2 && boundary[0] == '"'
	        && boundary[len-1] == '"' )
	    {
	        boundary[len-1] = '\0';
	        boundary++;
	    }
            p_sys->psz_separator = strdup( boundary );
            if( !p_sys->psz_separator )
            {
                free( content_type );
                goto error;
            }
        }
        free( content_type );
    }

    b_matched = CheckMimeHeader( p_demux, &i_size);
    if( b_matched )
    {
        p_demux->pf_demux = MimeDemux;
        stream_Read( p_demux->s, NULL, i_size );
    }
    else if( i_size == 0 )
    {
        /* 0xffd8 identify a JPEG SOI */
        if( p_sys->p_peek[0] == 0xFF && p_sys->p_peek[1] == 0xD8 )
        {
            msg_Dbg( p_demux, "JPEG SOI marker detected" );
            p_demux->pf_demux = MjpgDemux;
            p_sys->i_level++;
        }
        else
        {
            goto error;
        }
    }
    else
    {
        goto error;
    }

    /* Frame rate */
    float f_fps = var_InheritFloat( p_demux, "mjpeg-fps" );

    p_sys->i_still_end = 0;
    if( demux_IsPathExtension( p_demux, ".jpeg" ) ||
        demux_IsPathExtension( p_demux, ".jpg" ) )
    {
        /* Plain JPEG file = single still picture */
        p_sys->b_still = true;
        if( f_fps == 0.f )
            /* Defaults to 1fps */
            f_fps = 1.f;
    }
    else
        p_sys->b_still = false;
    p_sys->i_frame_length = f_fps ? (CLOCK_FREQ / f_fps) : 0;

    es_format_Init( &p_sys->fmt, VIDEO_ES, 0 );
    p_sys->fmt.i_codec = VLC_CODEC_MJPG;

    p_sys->p_es = es_out_Add( p_demux->out, &p_sys->fmt );
    return VLC_SUCCESS;

error:
    free( p_sys->psz_separator );
    free( p_sys );
    return VLC_EGENERIC;
}
Пример #20
0
Файл: stl.c Проект: BossKing/vlc
static int Open(vlc_object_t *object)
{
    demux_t *demux = (demux_t*)object;

    const uint8_t *peek;
    if (vlc_stream_Peek(demux->s, &peek, 11) != 11)
        return VLC_EGENERIC;

    bool is_stl_25 = !memcmp(&peek[3], "STL25.01", 8);
    bool is_stl_30 = !memcmp(&peek[3], "STL30.01", 8);
    if (!is_stl_25 && !is_stl_30)
        return VLC_EGENERIC;
    const double fps = is_stl_25 ? 25 : 30;

    uint8_t header[1024];
    if (vlc_stream_Read(demux->s, header, sizeof(header)) != sizeof(header)) {
        msg_Err(demux, "Incomplete EBU STL header");
        return VLC_EGENERIC;
    }
    const int cct = ParseInteger(&header[12], 2);
    const mtime_t program_start = ParseTextTimeCode(&header[256], fps);
    const int tti_count = ParseInteger(&header[238], 5);
    msg_Dbg(demux, "Detected EBU STL : CCT=%d TTI=%d start=%8.8s %"PRId64, cct, tti_count, &header[256], program_start);

    demux_sys_t *sys = xmalloc(sizeof(*sys));
    sys->next_date = 0;
    sys->current   = 0;
    sys->count     = 0;
    sys->index     = xcalloc(tti_count, sizeof(*sys->index));


    bool comment = false;
    stl_entry_t *s = &sys->index[0];
    s->count = 0;

    for (int i = 0; i < tti_count; i++) {
        uint8_t tti[16];
        if (vlc_stream_Read(demux->s, tti, 16) != 16 ||
            vlc_stream_Read(demux->s, NULL, 112) != 112) {
            msg_Warn(demux, "Incomplete EBU STL file");
            break;
        }
        const int ebn = tti[3];
        if (ebn >= 0xf0 && ebn <= 0xfd)
            continue;
        if (ebn == 0xfe)
            continue;

        if (s->count <= 0) {
            comment  = tti[15] != 0;
            s->start = ParseTimeCode(&tti[5], fps) - program_start;
            s->stop  = ParseTimeCode(&tti[9], fps) - program_start;
            s->index = i;
        }
        s->count++;
        if (ebn == 0xff && !comment)
            s = &sys->index[++sys->count];
        if (ebn == 0xff && sys->count < tti_count)
            s->count = 0;
    }
    if (sys->count > 0)
        vlc_stream_Seek(demux->s, 1024 + 128LL * sys->index[0].index);

    es_format_t fmt;
    es_format_Init(&fmt, SPU_ES, VLC_CODEC_EBU_STL);
    fmt.i_extra = sizeof(header);
    fmt.p_extra = header;

    sys->es = es_out_Add(demux->out, &fmt);

    fmt.i_extra = 0;
    fmt.p_extra = NULL;
    es_format_Clean(&fmt);

    demux->p_sys      = sys;
    demux->pf_demux   = Demux;
    demux->pf_control = Control;
    return VLC_SUCCESS;
}
Пример #21
0
/*****************************************************************************
 * Open: initializes demux structures
 *****************************************************************************/
static int Open( vlc_object_t * p_this )
{
    demux_t     *p_demux = (demux_t*)p_this;
    demux_sys_t *p_sys;
    vlc_bool_t   b_forced = VLC_FALSE;

    uint8_t     *p_peek;

    es_format_t  fmt;

    if( stream_Peek( p_demux->s, &p_peek, 4 ) < 4 )
    {
        msg_Err( p_demux, "cannot peek" );
        return VLC_EGENERIC;
    }

    if( !strncmp( p_demux->psz_demux, "mpgv", 4 ) )
    {
        b_forced = VLC_TRUE;
    }

    if( p_peek[0] != 0x00 || p_peek[1] != 0x00 || p_peek[2] != 0x01 )
    {
        if( !b_forced )
        {
            msg_Warn( p_demux, "ES module discarded (no startcode)" );
            return VLC_EGENERIC;
        }

        msg_Err( p_demux, "this doesn't look like an MPEG ES stream, continuing" );
    }

    if( p_peek[3] > 0xb9 )
    {
        if( !b_forced )
        {
            msg_Warn( p_demux, "ES module discarded (system startcode)" );
            return VLC_EGENERIC;
        }
        msg_Err( p_demux, "this seems to be a system stream (PS plug-in ?), but continuing" );
    }

    p_demux->pf_demux  = Demux;
    p_demux->pf_control= Control;
    p_demux->p_sys     = p_sys = malloc( sizeof( demux_sys_t ) );
    p_sys->b_start     = VLC_TRUE;
    p_sys->p_es        = NULL;

    /*
     * Load the mpegvideo packetizer
     */
    p_sys->p_packetizer = vlc_object_create( p_demux, VLC_OBJECT_PACKETIZER );
    p_sys->p_packetizer->pf_decode_audio = NULL;
    p_sys->p_packetizer->pf_decode_video = NULL;
    p_sys->p_packetizer->pf_decode_sub = NULL;
    p_sys->p_packetizer->pf_packetize = NULL;
    es_format_Init( &p_sys->p_packetizer->fmt_in, VIDEO_ES,
                    VLC_FOURCC( 'm', 'p', 'g', 'v' ) );
    es_format_Init( &p_sys->p_packetizer->fmt_out, UNKNOWN_ES, 0 );
    p_sys->p_packetizer->p_module =
        module_Need( p_sys->p_packetizer, "packetizer", NULL, 0 );

    if( p_sys->p_packetizer->p_module == NULL)
    {
        vlc_object_destroy( p_sys->p_packetizer );
        msg_Err( p_demux, "cannot find mpgv packetizer" );
        free( p_sys );
        return VLC_EGENERIC;
    }

    /*
     * create the output
     */
    es_format_Init( &fmt, VIDEO_ES, VLC_FOURCC( 'm', 'p', 'g', 'v' ) );
    p_sys->p_es = es_out_Add( p_demux->out, &fmt );

    return VLC_SUCCESS;
}
Пример #22
0
Файл: vnc.c Проект: mstorsjo/vlc
static rfbBool mallocFrameBufferHandler( rfbClient* p_client )
{
    vlc_fourcc_t i_chroma;
    demux_t *p_demux = (demux_t *) rfbClientGetClientData( p_client, DemuxThread );
    demux_sys_t *p_sys = p_demux->p_sys;

    if ( p_sys->es ) /* Source has changed resolution */
    {
        es_out_Del( p_demux->out, p_sys->es );
        p_sys->es = NULL;
    }

    int i_width = p_client->width;
    int i_height = p_client->height;
    int i_depth = p_client->format.bitsPerPixel;

    switch( i_depth )
    {
        case 8:
            i_chroma = VLC_CODEC_RGB8;
            break;
        default:
        case 16:
            i_chroma = VLC_CODEC_RGB16;
            break;
        case 24:
            i_chroma = VLC_CODEC_RGB24;
            break;
        case 32:
            i_chroma = VLC_CODEC_RGB32;
            break;
    }

    switch( i_chroma )
    {
        case VLC_CODEC_RGB16:
            p_client->format.redShift   = 11;
            p_client->format.greenShift =  5;
            p_client->format.blueShift  =  0;
            p_client->format.redMax     = 0x1f;
            p_client->format.greenMax   = 0x3f;
            p_client->format.blueMax    = 0x1f;
            break;
        case VLC_CODEC_RGB24:
        case VLC_CODEC_RGB32:
            p_client->format.redShift   = 16;
            p_client->format.greenShift =  8;
            p_client->format.blueShift  =  0;
            p_client->format.redMax     = 0xff;
            p_client->format.greenMax   = 0xff;
            p_client->format.blueMax    = 0xff;
            break;
    }

    /* Set up framebuffer */
    p_sys->i_framebuffersize = i_width * i_height * i_depth / 8;

    /* Reuse unsent block */
    if ( p_sys->p_block )
        p_sys->p_block = block_Realloc( p_sys->p_block, 0, p_sys->i_framebuffersize );
    else
        p_sys->p_block = block_Alloc( p_sys->i_framebuffersize );

    if ( p_sys->p_block )
        p_sys->p_block->i_buffer = p_sys->i_framebuffersize;
    else
        return FALSE;

    /* Push our VNC config */
    SetFormatAndEncodings( p_client );

    /* Now init and fill es format */
    es_format_t fmt;
    es_format_Init( &fmt, VIDEO_ES, i_chroma );

    /* Fill input format */
    fmt.video.i_chroma = i_chroma;
    fmt.video.i_visible_width =
            fmt.video.i_width = i_width;

    fmt.video.i_visible_height =
            fmt.video.i_height = i_height;

    fmt.video.i_frame_rate_base = 1000;
    fmt.video.i_frame_rate = 1000 * p_sys->f_fps;

    fmt.video.i_bits_per_pixel = i_depth;
    fmt.video.i_rmask = p_client->format.redMax << p_client->format.redShift;
    fmt.video.i_gmask = p_client->format.greenMax << p_client->format.greenShift;
    fmt.video.i_bmask = p_client->format.blueMax << p_client->format.blueShift;

    fmt.video.i_sar_num = fmt.video.i_sar_den = 1;

    /* declare the new es */
    p_sys->es = es_out_Add( p_demux->out, &fmt );

    return TRUE;
}
Пример #23
0
static int Open(vlc_object_t *object)
{
    demux_t *demux = (demux_t*)object;

    /* Detect the image type */
    const image_format_t *img;

    const uint8_t *peek;
    int peek_size = 0;
    for (int i = 0; ; i++) {
        img = &formats[i];
        if (!img->codec)
            return VLC_EGENERIC;

        if (img->detect) {
            if (img->detect(demux->s))
                break;
        } else {
            if (peek_size < img->marker_size)
                peek_size = stream_Peek(demux->s, &peek, img->marker_size);
            if (peek_size >= img->marker_size &&
                !memcmp(peek, img->marker, img->marker_size))
                break;
        }
    }
    msg_Dbg(demux, "Detected image: %s",
            vlc_fourcc_GetDescription(VIDEO_ES, img->codec));

    if( img->codec == VLC_CODEC_MXPEG )
    {
        return VLC_EGENERIC; //let avformat demux this file
    }

    /* Load and if selected decode */
    es_format_t fmt;
    es_format_Init(&fmt, VIDEO_ES, img->codec);
    fmt.video.i_chroma = fmt.i_codec;

    block_t *data = Load(demux);
    if (data && var_InheritBool(demux, "image-decode")) {
        char *string = var_InheritString(demux, "image-chroma");
        vlc_fourcc_t chroma = vlc_fourcc_GetCodecFromString(VIDEO_ES, string);
        free(string);

        data = Decode(demux, &fmt.video, chroma, data);
        fmt.i_codec = fmt.video.i_chroma;
    }
    fmt.i_id    = var_InheritInteger(demux, "image-id");
    fmt.i_group = var_InheritInteger(demux, "image-group");
    if (var_InheritURational(demux,
                             &fmt.video.i_frame_rate,
                             &fmt.video.i_frame_rate_base,
                             "image-fps") ||
        fmt.video.i_frame_rate <= 0 || fmt.video.i_frame_rate_base <= 0) {
        msg_Err(demux, "Invalid frame rate, using 10/1 instead");
        fmt.video.i_frame_rate      = 10;
        fmt.video.i_frame_rate_base = 1;
    }

    /* If loadind failed, we still continue to avoid mis-detection
     * by other demuxers. */
    if (!data)
        msg_Err(demux, "Failed to load the image");

    /* */
    demux_sys_t *sys = malloc(sizeof(*sys));
    if (!sys) {
        if (data)
            block_Release(data);
        es_format_Clean(&fmt);
        return VLC_ENOMEM;
    }

    sys->data        = data;
    sys->es          = es_out_Add(demux->out, &fmt);
    sys->duration    = CLOCK_FREQ * var_InheritFloat(demux, "image-duration");
    sys->is_realtime = var_InheritBool(demux, "image-realtime");
    sys->pts_origin  = sys->is_realtime ? mdate() : 0;
    sys->pts_next    = VLC_TS_INVALID;
    date_Init(&sys->pts, fmt.video.i_frame_rate, fmt.video.i_frame_rate_base);
    date_Set(&sys->pts, 0);

    es_format_Clean(&fmt);

    demux->pf_demux   = Demux;
    demux->pf_control = Control;
    demux->p_sys      = sys;
    return VLC_SUCCESS;
}
Пример #24
0
Файл: ps.c Проект: mstorsjo/vlc
/*****************************************************************************
 * Demux:
 *****************************************************************************/
static int Demux( demux_t *p_demux )
{
    demux_sys_t *p_sys = p_demux->p_sys;
    int i_ret, i_mux_rate;
    block_t *p_pkt;

    i_ret = ps_pkt_resynch( p_demux->s, p_sys->format, p_sys->b_have_pack );
    if( i_ret < 0 )
    {
        return VLC_DEMUXER_EOF;
    }
    else if( i_ret == 0 )
    {
        if( !p_sys->b_lost_sync )
        {
            msg_Warn( p_demux, "garbage at input from %"PRIu64", trying to resync...",
                                vlc_stream_Tell(p_demux->s) );
            NotifyDiscontinuity( p_sys->tk, p_demux->out );
        }

        p_sys->b_lost_sync = true;
        return VLC_DEMUXER_SUCCESS;
    }

    if( p_sys->b_lost_sync ) msg_Warn( p_demux, "found sync code" );
    p_sys->b_lost_sync = false;

    if( p_sys->i_length == VLC_TICK_INVALID && p_sys->b_seekable )
    {
        if( !FindLength( p_demux ) )
            return VLC_DEMUXER_EGENERIC;
    }

    if( ( p_pkt = ps_pkt_read( p_demux->s ) ) == NULL )
    {
        return VLC_DEMUXER_EOF;
    }

    if( p_pkt->i_buffer < 4 )
    {
        block_Release( p_pkt );
        return VLC_DEMUXER_EGENERIC;
    }

    const uint8_t i_stream_id = p_pkt->p_buffer[3];
    switch( i_stream_id )
    {
    case PS_STREAM_ID_END_STREAM:
        block_Release( p_pkt );
        break;

    case PS_STREAM_ID_PACK_HEADER:
        if( !ps_pkt_parse_pack( p_pkt, &p_sys->i_pack_scr, &i_mux_rate ) )
        {
            if( p_sys->i_first_scr == VLC_TICK_INVALID )
                p_sys->i_first_scr = p_sys->i_pack_scr;
            CheckPCR( p_sys, p_demux->out, p_sys->i_pack_scr );
            p_sys->i_scr = p_sys->i_pack_scr;
            p_sys->i_lastpack_byte = vlc_stream_Tell( p_demux->s );
            if( !p_sys->b_have_pack ) p_sys->b_have_pack = true;
            /* done later on to work around bad vcd/svcd streams */
            /* es_out_SetPCR( p_demux->out, p_sys->i_scr ); */
            if( i_mux_rate > 0 ) p_sys->i_mux_rate = i_mux_rate;
        }
        block_Release( p_pkt );
        break;

    case PS_STREAM_ID_SYSTEM_HEADER:
        if( !ps_pkt_parse_system( p_pkt, &p_sys->psm, p_sys->tk ) )
        {
            int i;
            for( i = 0; i < PS_TK_COUNT; i++ )
            {
                ps_track_t *tk = &p_sys->tk[i];

                if( !tk->b_configured && tk->fmt.i_cat != UNKNOWN_ES )
                {
                    if( tk->b_seen )
                        tk->es = es_out_Add( p_demux->out, &tk->fmt );
                     /* else create when seeing packet */
                    tk->b_configured = true;
                }
            }
        }
        block_Release( p_pkt );
        break;

    case PS_STREAM_ID_MAP:
        if( p_sys->psm.i_version == 0xFFFF )
            msg_Dbg( p_demux, "contains a PSM");

        ps_psm_fill( &p_sys->psm, p_pkt, p_sys->tk, p_demux->out );
        block_Release( p_pkt );
        break;

    default:
        /* Reject non video/audio nor PES */
        if( i_stream_id < 0xC0 || i_stream_id > 0xEF )
        {
            block_Release( p_pkt );
            break;
        }
        /* fallthrough */
    case PS_STREAM_ID_PRIVATE_STREAM1:
    case PS_STREAM_ID_EXTENDED:
        {
            int i_id = ps_pkt_id( p_pkt );
            /* Small heuristic to improve MLP detection from AOB */
            if( i_id == 0xa001 &&
                p_sys->i_aob_mlp_count < 500 )
            {
                p_sys->i_aob_mlp_count++;
            }
            else if( i_id == 0xbda1 &&
                     p_sys->i_aob_mlp_count > 0 )
            {
                p_sys->i_aob_mlp_count--;
                i_id = 0xa001;
            }

            bool b_new = false;
            ps_track_t *tk = &p_sys->tk[ps_id_to_tk(i_id)];

            if( !tk->b_configured )
            {
                if( !ps_track_fill( tk, &p_sys->psm, i_id, p_pkt, false ) )
                {
                    /* No PSM and no probing yet */
                    if( p_sys->format == PSMF_PS )
                    {
                        if( tk->fmt.i_cat == VIDEO_ES )
                            tk->fmt.i_codec = VLC_CODEC_H264;
#if 0
                        if( i_stream_id == PS_STREAM_ID_PRIVATE_STREAM1 )
                        {
                            es_format_Change( &tk->fmt, AUDIO_ES, VLC_CODEC_ATRAC3P );
                            tk->fmt.audio.i_blockalign = 376;
                            tk->fmt.audio.i_channels = 2;
                            tk->fmt.audio.i_rate = 44100;
                        }
#endif
                    }

                    tk->es = es_out_Add( p_demux->out, &tk->fmt );
                    b_new = true;
                    tk->b_configured = true;
                }
                else
                {
                    msg_Dbg( p_demux, "es id=0x%x format unknown", i_id );
                }
            }

            /* Late creation from system header */
            if( !tk->b_seen && tk->b_configured && !tk->es && tk->fmt.i_cat != UNKNOWN_ES )
                tk->es = es_out_Add( p_demux->out, &tk->fmt );

            tk->b_seen = true;

            /* The popular VCD/SVCD subtitling WinSubMux does not
             * renumber the SCRs when merging subtitles into the PES */
            if( tk->b_seen && !p_sys->b_bad_scr &&
                ( tk->fmt.i_codec == VLC_CODEC_OGT ||
                  tk->fmt.i_codec == VLC_CODEC_CVD ) )
            {
                p_sys->b_bad_scr = true;
                p_sys->i_first_scr = VLC_TICK_INVALID;
            }

            if( p_sys->i_pack_scr != VLC_TICK_INVALID && !p_sys->b_bad_scr )
            {
                if( (tk->fmt.i_cat == AUDIO_ES || tk->fmt.i_cat == VIDEO_ES) &&
                    tk->i_first_pts != VLC_TICK_INVALID && tk->i_first_pts - p_sys->i_pack_scr > VLC_TICK_FROM_SEC(2))
                {
                    msg_Warn( p_demux, "Incorrect SCR timing offset by of %"PRId64 "ms, disabling",
                                       MS_FROM_VLC_TICK(tk->i_first_pts - p_sys->i_pack_scr) );
                    p_sys->b_bad_scr = true; /* Disable Offset SCR */
                    p_sys->i_first_scr = VLC_TICK_INVALID;
                }
                else
                    es_out_SetPCR( p_demux->out, p_sys->i_pack_scr );
            }

            if( tk->b_configured && tk->es &&
                !ps_pkt_parse_pes( VLC_OBJECT(p_demux), p_pkt, tk->i_skip ) )
            {
                if( tk->fmt.i_cat == AUDIO_ES || tk->fmt.i_cat == VIDEO_ES )
                {
                    if( !p_sys->b_bad_scr && p_sys->i_pack_scr != VLC_TICK_INVALID && p_pkt->i_pts != VLC_TICK_INVALID &&
                        p_sys->i_pack_scr > p_pkt->i_pts + VLC_TICK_FROM_MS(250) )
                    {
                        msg_Warn( p_demux, "Incorrect SCR timing in advance of %" PRId64 "ms, disabling",
                                           MS_FROM_VLC_TICK(p_sys->i_pack_scr - p_pkt->i_pts) );
                        p_sys->b_bad_scr = true;
                        p_sys->i_first_scr = VLC_TICK_INVALID;
                    }

                    if( (p_sys->b_bad_scr || !p_sys->b_have_pack) && !p_sys->i_scr_track_id )
                    {
                        p_sys->i_scr_track_id = tk->i_id;
                    }
                }

                if( ((!b_new && !p_sys->b_have_pack) || p_sys->b_bad_scr) &&
                    p_sys->i_scr_track_id == tk->i_id &&
                    p_pkt->i_pts != VLC_TICK_INVALID )
                {
                    /* A hack to sync the A/V on PES files. */
                    msg_Dbg( p_demux, "force SCR: %"PRId64, p_pkt->i_pts );
                    CheckPCR( p_sys, p_demux->out, p_pkt->i_pts );
                    p_sys->i_scr = p_pkt->i_pts;
                    if( p_sys->i_first_scr == VLC_TICK_INVALID )
                        p_sys->i_first_scr = p_sys->i_scr;
                    es_out_SetPCR( p_demux->out, p_pkt->i_pts );
                }

                if( tk->fmt.i_codec == VLC_CODEC_TELETEXT &&
                    p_pkt->i_pts == VLC_TICK_INVALID && p_sys->i_scr != VLC_TICK_INVALID )
                {
                    /* Teletext may have missing PTS (ETSI EN 300 472 Annexe A)
                     * In this case use the last SCR + 40ms */
                    p_pkt->i_pts = p_sys->i_scr + VLC_TICK_FROM_MS(40);
                }

                if( p_pkt->i_pts > p_sys->i_current_pts )
                {
                    p_sys->i_current_pts = p_pkt->i_pts;
                }

                if( tk->i_next_block_flags )
                {
                    p_pkt->i_flags = tk->i_next_block_flags;
                    tk->i_next_block_flags = 0;
                }
#if 0
                if( tk->fmt.i_codec == VLC_CODEC_ATRAC3P )
                {
                    p_pkt->p_buffer += 14;
                    p_pkt->i_buffer -= 14;
                }
#endif
                es_out_Send( p_demux->out, tk->es, p_pkt );
            }
            else
            {
                block_Release( p_pkt );
            }

            p_sys->i_pack_scr = VLC_TICK_INVALID;
        }
        break;
    }

    demux_UpdateTitleFromStream( p_demux );
    return VLC_DEMUXER_SUCCESS;
}
Пример #25
0
/*****************************************************************************
 * Open: initializes raw DV demux structures
 *****************************************************************************/
static int Open( vlc_object_t * p_this )
{
    demux_t     *p_demux = (demux_t*)p_this;
    demux_sys_t *p_sys;
    int i_width=-1, i_height=-1;
    unsigned u_fps_num, u_fps_den;
    vlc_fourcc_t i_chroma = 0;
    unsigned int i_sar_num;
    unsigned int i_sar_den;
    const struct preset_t *p_preset = NULL;
    const uint8_t *p_peek;
    bool b_y4m = false;

    if( stream_Peek( p_demux->s, &p_peek, 9 ) == 9 )
    {
        /* http://wiki.multimedia.cx/index.php?title=YUV4MPEG2 */
        if( !strncmp( (char *)p_peek, "YUV4MPEG2", 9 ) )
        {
            b_y4m = true;
            goto valid;
        }
    }

    if( !p_demux->b_force )
    {
        /* guess preset based on file extension */
        if( !p_demux->psz_file )
            return VLC_EGENERIC;

        const char *psz_ext = strrchr( p_demux->psz_file, '.' );
        if( !psz_ext )
            return VLC_EGENERIC;
        psz_ext++;

        for( unsigned i = 0; p_presets[i].psz_ext ; i++ )
        {
            if( !strcasecmp( psz_ext, p_presets[i].psz_ext ) )
            {
                p_preset = &p_presets[i];
                goto valid;
            }
        }
        return VLC_EGENERIC;
    }
valid:
    p_demux->p_sys      = p_sys = malloc( sizeof( demux_sys_t ) );
    if( !p_sys )
        return VLC_ENOMEM;

    p_sys->b_y4m = b_y4m;

    /* guess the parameters based on the preset */
    if( p_preset )
    {
        i_width = p_preset->i_width;
        i_height = p_preset->i_height;
        u_fps_num = p_preset->u_fps_num;
        u_fps_den = p_preset->u_fps_den;
        i_sar_num = p_preset->u_ar_num * p_preset->i_height;
        i_sar_den = p_preset->u_ar_den * p_preset->i_width;
        i_chroma = p_preset->i_chroma;
    }

    /* override presets if yuv4mpeg2 */
    if( b_y4m )
    {
        /* The string should start with "YUV4MPEG2" */
        char *psz = stream_ReadLine( p_demux->s );
        char *psz_buf;
        int a = 1;
        int b = 1;

        if( unlikely(psz == NULL) )
            goto error;

        /* NB, it is not possible to handle interlaced here, since the
         * interlaced picture flags are in picture_t not block_t */

#define READ_FRAC( key, num, den ) do { \
        psz_buf = strstr( psz+9, key );\
        if( psz_buf )\
        {\
            char *end = strchr( psz_buf+1, ' ' );\
            char *sep;\
            if( end ) *end = '\0';\
            sep = strchr( psz_buf+1, ':' );\
            if( sep )\
            {\
                *sep = '\0';\
                den = atoi( sep+1 );\
            }\
            else\
            {\
                den = 1;\
            }\
            num = atoi( psz_buf+2 );\
            if( sep ) *sep = ':';\
            if( end ) *end = ' ';\
        } } while(0)
        READ_FRAC( " W", i_width, a );
        READ_FRAC( " H", i_height, a );
        READ_FRAC( " F", u_fps_num, u_fps_den );
        READ_FRAC( " A", a, b );
#undef READ_FRAC
        if( b != 0 )
        {
            i_sar_num = a;
            i_sar_den = b;
        }

        psz_buf = strstr( psz+9, " C" );
        if( psz_buf )
        {
            static const struct { const char *psz_name; vlc_fourcc_t i_fcc; } formats[] =
            {
                { "420jpeg",    VLC_CODEC_I420 },
                { "420paldv",   VLC_CODEC_I420 },
                { "420",        VLC_CODEC_I420 },
                { "422",        VLC_CODEC_I422 },
                { "444",        VLC_CODEC_I444 },
                { "mono",       VLC_CODEC_GREY },
                { NULL, 0 }
            };
            bool b_found = false;
            char *psz_end = strchr( psz_buf+1, ' ' );
            if( psz_end )
                *psz_end = '\0';
            psz_buf += 2;

            for( int i = 0; formats[i].psz_name != NULL; i++ )
            {
                if( !strncmp( psz_buf, formats[i].psz_name, strlen(formats[i].psz_name) ) )
                {
                    i_chroma = formats[i].i_fcc;
                    b_found = true;
                    break;
                }
            }
            if( !b_found )
                msg_Warn( p_demux, "Unknown YUV4MPEG2 chroma type \"%s\"", psz_buf );
            if( psz_end )
                *psz_end = ' ';
        }

        free( psz );
    }

    /* allow the user to override anything guessed from the input */
    int i_tmp;
    i_tmp = var_CreateGetInteger( p_demux, "rawvid-width" );
    if( i_tmp ) i_width = i_tmp;

    i_tmp = var_CreateGetInteger( p_demux, "rawvid-height" );
    if( i_tmp ) i_height = i_tmp;

    char *psz_tmp;
    psz_tmp = var_CreateGetNonEmptyString( p_demux, "rawvid-chroma" );
    if( psz_tmp )
    {
        if( strlen( psz_tmp ) != 4 )
        {
            msg_Err( p_demux, "Invalid fourcc format/chroma specification %s"
                     " expecting four characters eg, UYVY", psz_tmp );
            free( psz_tmp );
            goto error;
        }
        memcpy( &i_chroma, psz_tmp, 4 );
        msg_Dbg( p_demux, "Forcing chroma to 0x%.8x (%4.4s)", i_chroma, (char*)&i_chroma );
        free( psz_tmp );
    }

    if( var_InheritURational( p_demux, &u_fps_num, &u_fps_den, "rawvid-fps" ) )
    {
        u_fps_num = 0;
        u_fps_den = 1;
    }

    if( var_InheritURational( p_demux, &i_sar_num, &i_sar_den,
                              "rawvid-aspect-ratio" ) )
        i_sar_num = i_sar_den = 1;

    /* moan about anything wrong */
    if( i_width <= 0 || i_height <= 0 )
    {
        msg_Err( p_demux, "width and height must be strictly positive." );
        goto error;
    }

    if( !u_fps_num || !u_fps_den )
    {
        msg_Err( p_demux, "invalid or no framerate specified." );
        goto error;
    }

    if( i_chroma == 0 )
    {
        msg_Err( p_demux, "invalid or no chroma specified." );
        goto error;
    }

    /* fixup anything missing with sensible assumptions */
    if( i_sar_num <= 0 || i_sar_den <= 0 )
    {
        /* assume 1:1 sar */
        i_sar_num = 1;
        i_sar_den = 1;
    }

    es_format_Init( &p_sys->fmt_video, VIDEO_ES, i_chroma );
    video_format_Setup( &p_sys->fmt_video.video, i_chroma,
                        i_width, i_height, i_width, i_height,
                        i_sar_num, i_sar_den );

    vlc_ureduce( &p_sys->fmt_video.video.i_frame_rate,
                 &p_sys->fmt_video.video.i_frame_rate_base,
                 u_fps_num, u_fps_den, 0);
    date_Init( &p_sys->pcr, p_sys->fmt_video.video.i_frame_rate,
               p_sys->fmt_video.video.i_frame_rate_base );
    date_Set( &p_sys->pcr, 0 );

    if( !p_sys->fmt_video.video.i_bits_per_pixel )
    {
        msg_Err( p_demux, "Unsupported chroma 0x%.8x (%4.4s)", i_chroma,
                 (char*)&i_chroma );
        goto error;
    }
    p_sys->frame_size = i_width * i_height
                        * p_sys->fmt_video.video.i_bits_per_pixel / 8;
    p_sys->p_es_video = es_out_Add( p_demux->out, &p_sys->fmt_video );

    p_demux->pf_demux   = Demux;
    p_demux->pf_control = Control;
    return VLC_SUCCESS;

error:
    stream_Seek( p_demux->s, 0 ); // Workaround, but y4m uses stream_ReadLines
    free( p_sys );
    return VLC_EGENERIC;
}
Пример #26
0
static int Open (vlc_object_t *obj)
{
    demux_t *demux = (demux_t *)obj;
    demux_sys_t *sys = vlc_obj_malloc(obj, sizeof (*sys));
    if (unlikely(sys == NULL))
        return VLC_ENOMEM;

    /* Open the device */
    const char *device = demux->psz_location;
    if (device == NULL || !device[0])
        device = "default";

    const int mode = SND_PCM_NONBLOCK
                 /*| SND_PCM_NO_AUTO_RESAMPLE*/
                   | SND_PCM_NO_AUTO_CHANNELS
                 /*| SND_PCM_NO_AUTO_FORMAT*/;
    snd_pcm_t *pcm;
    int val = snd_pcm_open (&pcm, device, SND_PCM_STREAM_CAPTURE, mode);
    if (val != 0)
    {
        msg_Err (demux, "cannot open ALSA device \"%s\": %s", device,
                 snd_strerror (val));
        return VLC_EGENERIC;
    }
    sys->pcm = pcm;
    msg_Dbg (demux, "using ALSA device: %s", device);
    DumpDevice (VLC_OBJECT(demux), pcm);

    /* Negotiate capture parameters */
    snd_pcm_hw_params_t *hw;
    es_format_t fmt;
    unsigned param;
    int dir;

    snd_pcm_hw_params_alloca (&hw);
    snd_pcm_hw_params_any (pcm, hw);
    Dump (demux, "initial hardware setup:\n", snd_pcm_hw_params_dump, hw);

    val = snd_pcm_hw_params_set_rate_resample (pcm, hw, 0);
    if (val)
    {
        msg_Err (demux, "cannot disable resampling: %s", snd_strerror (val));
        goto error;
    }

    val = snd_pcm_hw_params_set_access (pcm, hw,
                                        SND_PCM_ACCESS_RW_INTERLEAVED);
    if (val)
    {
        msg_Err (demux, "cannot set access mode: %s", snd_strerror (val));
        goto error;
    }

    snd_pcm_format_t format = SND_PCM_FORMAT_UNKNOWN;
    for (size_t i = 0; i < sizeof (choices) / sizeof (choices[0]); i++)
        if (snd_pcm_hw_params_test_format (pcm, hw, choices[i]) == 0)
        {
            val = snd_pcm_hw_params_set_format (pcm, hw, choices[i]);
            if (val)
            {
                msg_Err (demux, "cannot set sample format: %s",
                         snd_strerror (val));
                goto error;
            }
            format = choices[i];
            break;
        }

    if (format == SND_PCM_FORMAT_UNKNOWN)
    {
        msg_Err (demux, "no supported sample format");
        goto error;
    }

    assert ((size_t)format < (sizeof (formats) / sizeof (formats[0])));
    es_format_Init (&fmt, AUDIO_ES, formats[format]);
    fmt.audio.i_format = fmt.i_codec;

    param = 1 + var_InheritBool (demux, "alsa-stereo");
    val = snd_pcm_hw_params_set_channels_max (pcm, hw, &param);
    if (val)
    {
        msg_Err (demux, "cannot restrict channels count: %s",
                 snd_strerror (val));
        goto error;
    }
    val = snd_pcm_hw_params_set_channels_last (pcm, hw, &param);
    if (val)
    {
        msg_Err (demux, "cannot set channels count: %s", snd_strerror (val));
        goto error;
    }
    assert (param > 0);
    assert (param < (sizeof (channel_maps) / sizeof (channel_maps[0])));
    fmt.audio.i_channels = param;
    fmt.audio.i_physical_channels = channel_maps[param - 1];

    param = var_InheritInteger (demux, "alsa-samplerate");
    val = snd_pcm_hw_params_set_rate_max (pcm, hw, &param, NULL);
    if (val)
    {
        msg_Err (demux, "cannot restrict rate to %u Hz or less: %s", 192000,
                 snd_strerror (val));
        goto error;
    }
    val = snd_pcm_hw_params_set_rate_last (pcm, hw, &param, &dir);
    if (val)
    {
        msg_Err (demux, "cannot set sample rate: %s", snd_strerror (val));
        goto error;
    }
    if (dir)
        msg_Warn (demux, "sample rate is not integral");
    fmt.audio.i_rate = param;
    sys->rate = param;

    sys->start = mdate ();
    sys->caching = INT64_C(1000) * var_InheritInteger (demux, "live-caching");
    param = sys->caching;
    val = snd_pcm_hw_params_set_buffer_time_near (pcm, hw, &param, NULL);
    if (val)
    {
        msg_Err (demux, "cannot set buffer duration: %s", snd_strerror (val));
        goto error;
    }

    param /= 4;
    val = snd_pcm_hw_params_set_period_time_near (pcm, hw, &param, NULL);
    if (val)
    {
        msg_Err (demux, "cannot set period: %s", snd_strerror (val));
        goto error;
    }

    val = snd_pcm_hw_params_get_period_size (hw, &sys->period_size, &dir);
    if (val)
    {
        msg_Err (demux, "cannot get period size: %s", snd_strerror (val));
        goto error;
    }
    if (dir > 0)
        sys->period_size++;

    /* Commit hardware parameters */
    val = snd_pcm_hw_params (pcm, hw);
    if (val)
    {
        msg_Err (demux, "cannot commit hardware parameters: %s",
                 snd_strerror (val));
        goto error;
    }
    Dump (demux, "final HW setup:\n", snd_pcm_hw_params_dump, hw);

    /* Kick recording */
    aout_FormatPrepare (&fmt.audio);
    sys->es = es_out_Add (demux->out, &fmt);
    demux->p_sys = sys;

    if (vlc_clone (&sys->thread, Thread, demux, VLC_THREAD_PRIORITY_INPUT))
    {
        es_out_Del (demux->out, sys->es);
        goto error;
    }

    demux->pf_demux = NULL;
    demux->pf_control = Control;
    return VLC_SUCCESS;
error:
    snd_pcm_close (pcm);
    return VLC_EGENERIC;
}
Пример #27
0
/*****************************************************************************
 * Open: check file and initializes structures
 *****************************************************************************/
static int Open( vlc_object_t * p_this )
{
    demux_t     *p_demux = (demux_t*)p_this;
    demux_sys_t *p_sys;
    int         i_size;
    bool        b_matched = false;
    float       f_fps;

    p_sys = malloc( sizeof( demux_sys_t ) );
    if( unlikely(p_sys == NULL) )
        return VLC_ENOMEM;

    p_demux->pf_control = Control;
    p_demux->p_sys      = p_sys;
    p_sys->p_es         = NULL;
    p_sys->i_time       = 0;
    p_sys->i_level      = 0;

    p_sys->psz_separator = NULL;
    p_sys->i_frame_size_estimate = 15 * 1024;

    b_matched = CheckMimeHeader( p_demux, &i_size);
    if( b_matched )
    {
        p_demux->pf_demux = MimeDemux;
        stream_Read( p_demux->s, NULL, i_size );
    }
    else if( 0 == i_size )
    {
        /* 0xffd8 identify a JPEG SOI */
        if( p_sys->p_peek[0] == 0xFF && p_sys->p_peek[1] == 0xD8 )
        {
            msg_Dbg( p_demux, "JPEG SOI marker detected" );
            p_demux->pf_demux = MjpgDemux;
            p_sys->i_level++;
        }
        else
        {
            goto error;
        }
    }
    else
    {
        goto error;
    }


    f_fps = var_CreateGetFloat( p_demux, "mjpeg-fps" );
    p_sys->i_frame_length = 0;

    /* Check for jpeg file extension */
    p_sys->b_still = false;
    p_sys->i_still_end = 0;
    if( demux_IsPathExtension( p_demux, ".jpeg" ) ||
        demux_IsPathExtension( p_demux, ".jpg" ) )
    {
        p_sys->b_still = true;
        if( f_fps )
        {
            p_sys->i_still_length = 1000000.0 / f_fps;
        }
        else
        {
            /* Defaults to 1fps */
            p_sys->i_still_length = 1000000;
        }
    }
    else if ( f_fps )
    {
        p_sys->i_frame_length = 1000000.0 / f_fps;
    }

    es_format_Init( &p_sys->fmt, VIDEO_ES, 0 );
    p_sys->fmt.i_codec = VLC_CODEC_MJPG;

    p_sys->p_es = es_out_Add( p_demux->out, &p_sys->fmt );
    return VLC_SUCCESS;

error:
    free( p_sys );
    return VLC_EGENERIC;
}
Пример #28
0
int avformat_OpenDemux( vlc_object_t *p_this )
{
    demux_t       *p_demux = (demux_t*)p_this;
    demux_sys_t   *p_sys;
    AVInputFormat *fmt = NULL;
    vlc_tick_t    i_start_time = VLC_TICK_INVALID;
    bool          b_can_seek;
    const char    *psz_url;
    int           error;

    if( p_demux->psz_filepath )
        psz_url = p_demux->psz_filepath;
    else
        psz_url = p_demux->psz_url;

    if( avformat_ProbeDemux( p_this, &fmt, psz_url ) != VLC_SUCCESS )
        return VLC_EGENERIC;

    vlc_stream_Control( p_demux->s, STREAM_CAN_SEEK, &b_can_seek );

    /* Fill p_demux fields */
    p_demux->pf_demux = Demux;
    p_demux->pf_control = Control;
    p_demux->p_sys = p_sys = malloc( sizeof( demux_sys_t ) );
    if( !p_sys )
        return VLC_ENOMEM;

    p_sys->ic = 0;
    p_sys->fmt = fmt;
    p_sys->tracks = NULL;
    p_sys->i_ssa_order = 0;
    TAB_INIT( p_sys->i_attachments, p_sys->attachments);
    p_sys->p_title = NULL;
    p_sys->i_seekpoint = 0;
    p_sys->i_update = 0;

    /* Create I/O wrapper */
    unsigned char * p_io_buffer = av_malloc( AVFORMAT_IOBUFFER_SIZE );
    if( !p_io_buffer )
    {
        avformat_CloseDemux( p_this );
        return VLC_ENOMEM;
    }

    p_sys->ic = avformat_alloc_context();
    if( !p_sys->ic )
    {
        av_free( p_io_buffer );
        avformat_CloseDemux( p_this );
        return VLC_ENOMEM;
    }

    AVIOContext *pb = p_sys->ic->pb = avio_alloc_context( p_io_buffer,
        AVFORMAT_IOBUFFER_SIZE, 0, p_demux, IORead, NULL, IOSeek );
    if( !pb )
    {
        av_free( p_io_buffer );
        avformat_CloseDemux( p_this );
        return VLC_ENOMEM;
    }

    p_sys->ic->pb->seekable = b_can_seek ? AVIO_SEEKABLE_NORMAL : 0;
    error = avformat_open_input(&p_sys->ic, psz_url, p_sys->fmt, NULL);

    if( error < 0 )
    {
        msg_Err( p_demux, "Could not open %s: %s", psz_url,
                 vlc_strerror_c(AVUNERROR(error)) );
        av_free( pb->buffer );
        av_free( pb );
        p_sys->ic = NULL;
        avformat_CloseDemux( p_this );
        return VLC_EGENERIC;
    }

    char *psz_opts = var_InheritString( p_demux, "avformat-options" );
    unsigned nb_streams = p_sys->ic->nb_streams;

    AVDictionary *options[nb_streams ? nb_streams : 1];
    options[0] = NULL;
    for (unsigned i = 1; i < nb_streams; i++)
        options[i] = NULL;
    if (psz_opts) {
        vlc_av_get_options(psz_opts, &options[0]);
        for (unsigned i = 1; i < nb_streams; i++) {
            av_dict_copy(&options[i], options[0], 0);
        }
        free(psz_opts);
    }
    vlc_avcodec_lock(); /* avformat calls avcodec behind our back!!! */
    error = avformat_find_stream_info( p_sys->ic, options );
    vlc_avcodec_unlock();
    AVDictionaryEntry *t = NULL;
    while ((t = av_dict_get(options[0], "", t, AV_DICT_IGNORE_SUFFIX))) {
        msg_Err( p_demux, "Unknown option \"%s\"", t->key );
    }
    av_dict_free(&options[0]);
    for (unsigned i = 1; i < nb_streams; i++) {
        av_dict_free(&options[i]);
    }

    nb_streams = p_sys->ic->nb_streams; /* it may have changed */
    if( !nb_streams )
    {
        msg_Err( p_demux, "No streams found");
        avformat_CloseDemux( p_this );
        return VLC_EGENERIC;
    }
    p_sys->tracks = calloc( nb_streams, sizeof(*p_sys->tracks) );
    if( !p_sys->tracks )
    {
        avformat_CloseDemux( p_this );
        return VLC_ENOMEM;
    }
    p_sys->i_tracks = nb_streams;

    if( error < 0 )
    {
        msg_Warn( p_demux, "Could not find stream info: %s",
                  vlc_strerror_c(AVUNERROR(error)) );
    }

    for( unsigned i = 0; i < nb_streams; i++ )
    {
        struct avformat_track_s *p_track = &p_sys->tracks[i];
        AVStream *s = p_sys->ic->streams[i];
        const AVCodecParameters *cp = s->codecpar;
        es_format_t es_fmt;
        const char *psz_type = "unknown";

        /* Do not use the cover art as a stream */
        if( s->disposition == AV_DISPOSITION_ATTACHED_PIC )
            continue;

        vlc_fourcc_t fcc = GetVlcFourcc( cp->codec_id );
        switch( cp->codec_type )
        {
        case AVMEDIA_TYPE_AUDIO:
            es_format_Init( &es_fmt, AUDIO_ES, fcc );
            es_fmt.i_original_fourcc = CodecTagToFourcc( cp->codec_tag );
            es_fmt.i_bitrate = cp->bit_rate;
            es_fmt.audio.i_channels = cp->channels;
            es_fmt.audio.i_rate = cp->sample_rate;
            es_fmt.audio.i_bitspersample = cp->bits_per_coded_sample;
            es_fmt.audio.i_blockalign = cp->block_align;
            psz_type = "audio";

            if(cp->codec_id == AV_CODEC_ID_AAC_LATM)
            {
                es_fmt.i_original_fourcc = VLC_FOURCC('L','A','T','M');
                es_fmt.b_packetized = false;
            }
            else if(cp->codec_id == AV_CODEC_ID_AAC && p_sys->fmt->long_name &&
                    strstr(p_sys->fmt->long_name, "raw ADTS AAC"))
            {
                es_fmt.i_original_fourcc = VLC_FOURCC('A','D','T','S');
                es_fmt.b_packetized = false;
            }
            break;

        case AVMEDIA_TYPE_VIDEO:
            es_format_Init( &es_fmt, VIDEO_ES, fcc );
            es_fmt.i_original_fourcc = CodecTagToFourcc( cp->codec_tag );

            es_fmt.video.i_bits_per_pixel = cp->bits_per_coded_sample;
            /* Special case for raw video data */
            if( cp->codec_id == AV_CODEC_ID_RAWVIDEO )
            {
                msg_Dbg( p_demux, "raw video, pixel format: %i", cp->format );
                if( GetVlcChroma( &es_fmt.video, cp->format ) != VLC_SUCCESS)
                {
                    msg_Err( p_demux, "was unable to find a FourCC match for raw video" );
                }
                else
                    es_fmt.i_codec = es_fmt.video.i_chroma;
            }
            /* We need this for the h264 packetizer */
            else if( cp->codec_id == AV_CODEC_ID_H264 && ( p_sys->fmt == av_find_input_format("flv") ||
                p_sys->fmt == av_find_input_format("matroska") || p_sys->fmt == av_find_input_format("mp4") ) )
                es_fmt.i_original_fourcc = VLC_FOURCC( 'a', 'v', 'c', '1' );

            es_fmt.video.i_width = cp->width;
            es_fmt.video.i_height = cp->height;
            es_fmt.video.i_visible_width = es_fmt.video.i_width;
            es_fmt.video.i_visible_height = es_fmt.video.i_height;

            get_rotation(&es_fmt, s);

# warning FIXME: implement palette transmission
            psz_type = "video";

            AVRational rate;
#if (LIBAVUTIL_VERSION_MICRO < 100) /* libav */
# if (LIBAVFORMAT_VERSION_INT >= AV_VERSION_INT(55, 20, 0))
            rate.num = s->time_base.num;
            rate.den = s->time_base.den;
# else
            rate.num = s->codec->time_base.num;
            rate.den = s->codec->time_base.den;
# endif
            rate.den *= __MAX( s->codec->ticks_per_frame, 1 );
#else /* ffmpeg */
            rate = av_guess_frame_rate( p_sys->ic, s, NULL );
#endif
            if( rate.den && rate.num )
            {
                es_fmt.video.i_frame_rate = rate.num;
                es_fmt.video.i_frame_rate_base = rate.den;
            }

            AVRational ar;
#if (LIBAVUTIL_VERSION_MICRO < 100) /* libav */
            ar.num = s->sample_aspect_ratio.num;
            ar.den = s->sample_aspect_ratio.den;
#else
            ar = av_guess_sample_aspect_ratio( p_sys->ic, s, NULL );
#endif
            if( ar.num && ar.den )
            {
                es_fmt.video.i_sar_den = ar.den;
                es_fmt.video.i_sar_num = ar.num;
            }
            break;

        case AVMEDIA_TYPE_SUBTITLE:
            es_format_Init( &es_fmt, SPU_ES, fcc );
            es_fmt.i_original_fourcc = CodecTagToFourcc( cp->codec_tag );
            if( strncmp( p_sys->ic->iformat->name, "matroska", 8 ) == 0 &&
                cp->codec_id == AV_CODEC_ID_DVD_SUBTITLE &&
                cp->extradata != NULL &&
                cp->extradata_size > 0 )
            {
                char *psz_start;
                char *psz_buf = malloc( cp->extradata_size + 1);
                if( psz_buf != NULL )
                {
                    memcpy( psz_buf, cp->extradata , cp->extradata_size );
                    psz_buf[cp->extradata_size] = '\0';

                    psz_start = strstr( psz_buf, "size:" );
                    if( psz_start &&
                        vobsub_size_parse( psz_start,
                                           &es_fmt.subs.spu.i_original_frame_width,
                                           &es_fmt.subs.spu.i_original_frame_height ) == VLC_SUCCESS )
                    {
                        msg_Dbg( p_demux, "original frame size: %dx%d",
                                 es_fmt.subs.spu.i_original_frame_width,
                                 es_fmt.subs.spu.i_original_frame_height );
                    }
                    else
                    {
                        msg_Warn( p_demux, "reading original frame size failed" );
                    }

                    psz_start = strstr( psz_buf, "palette:" );
                    if( psz_start &&
                        vobsub_palette_parse( psz_start, &es_fmt.subs.spu.palette[1] ) == VLC_SUCCESS )
                    {
                        es_fmt.subs.spu.palette[0] = SPU_PALETTE_DEFINED;
                        msg_Dbg( p_demux, "vobsub palette read" );
                    }
                    else
                    {
                        msg_Warn( p_demux, "reading original palette failed" );
                    }
                    free( psz_buf );
                }
            }
            else if( cp->codec_id == AV_CODEC_ID_DVB_SUBTITLE &&
                     cp->extradata_size > 3 )
            {
                es_fmt.subs.dvb.i_id = GetWBE( cp->extradata ) |
                                      (GetWBE( cp->extradata + 2 ) << 16);
            }
            else if( cp->codec_id == AV_CODEC_ID_MOV_TEXT )
            {
                if( cp->extradata_size && (es_fmt.p_extra = malloc(cp->extradata_size)) )
                {
                    memcpy( es_fmt.p_extra, cp->extradata, cp->extradata_size );
                    es_fmt.i_extra = cp->extradata_size;
                }
            }
            psz_type = "subtitle";
            break;

        default:
            es_format_Init( &es_fmt, UNKNOWN_ES, 0 );
            es_fmt.i_original_fourcc = CodecTagToFourcc( cp->codec_tag );
#ifdef HAVE_AVUTIL_CODEC_ATTACHMENT
            if( cp->codec_type == AVMEDIA_TYPE_ATTACHMENT )
            {
                input_attachment_t *p_attachment;

                psz_type = "attachment";
                if( cp->codec_id == AV_CODEC_ID_TTF )
                {
                    AVDictionaryEntry *filename = av_dict_get( s->metadata, "filename", NULL, 0 );
                    if( filename && filename->value )
                    {
                        p_attachment = vlc_input_attachment_New(
                                filename->value, "application/x-truetype-font",
                                NULL, cp->extradata, (int)cp->extradata_size );
                        if( p_attachment )
                            TAB_APPEND( p_sys->i_attachments, p_sys->attachments,
                                        p_attachment );
                    }
                }
                else msg_Warn( p_demux, "unsupported attachment type (%u) in avformat demux", cp->codec_id );
            }
            else
#endif
            {
                if( cp->codec_type == AVMEDIA_TYPE_DATA )
                    psz_type = "data";

                msg_Warn( p_demux, "unsupported track type (%u:%u) in avformat demux", cp->codec_type, cp->codec_id );
            }
            break;
        }

        AVDictionaryEntry *language = av_dict_get( s->metadata, "language", NULL, 0 );
        if ( language && language->value )
            es_fmt.psz_language = strdup( language->value );

        if( s->disposition & AV_DISPOSITION_DEFAULT )
            es_fmt.i_priority = ES_PRIORITY_SELECTABLE_MIN + 1000;

#ifdef HAVE_AVUTIL_CODEC_ATTACHMENT
        if( cp->codec_type != AVMEDIA_TYPE_ATTACHMENT )
#endif
        if( cp->codec_type != AVMEDIA_TYPE_DATA )
        {
            const bool    b_ogg = !strcmp( p_sys->fmt->name, "ogg" );
            const uint8_t *p_extra = cp->extradata;
            unsigned      i_extra  = cp->extradata_size;

            if( cp->codec_id == AV_CODEC_ID_THEORA && b_ogg )
            {
                unsigned pi_size[3];
                const void *pp_data[3];
                unsigned i_count;
                for( i_count = 0; i_count < 3; i_count++ )
                {
                    if( i_extra < 2 )
                        break;
                    pi_size[i_count] = GetWBE( p_extra );
                    pp_data[i_count] = &p_extra[2];
                    if( i_extra < pi_size[i_count] + 2 )
                        break;

                    p_extra += 2 + pi_size[i_count];
                    i_extra -= 2 + pi_size[i_count];
                }
                if( i_count > 0 && xiph_PackHeaders( &es_fmt.i_extra, &es_fmt.p_extra,
                                                     pi_size, pp_data, i_count ) )
                {
                    es_fmt.i_extra = 0;
                    es_fmt.p_extra = NULL;
                }
            }
            else if( cp->codec_id == AV_CODEC_ID_SPEEX && b_ogg )
            {
                const uint8_t p_dummy_comment[] = {
                    0, 0, 0, 0,
                    0, 0, 0, 0,
                };
                unsigned pi_size[2];
                const void *pp_data[2];

                pi_size[0] = i_extra;
                pp_data[0] = p_extra;

                pi_size[1] = sizeof(p_dummy_comment);
                pp_data[1] = p_dummy_comment;

                if( pi_size[0] > 0 && xiph_PackHeaders( &es_fmt.i_extra, &es_fmt.p_extra,
                                                        pi_size, pp_data, 2 ) )
                {
                    es_fmt.i_extra = 0;
                    es_fmt.p_extra = NULL;
                }
            }
            else if( cp->codec_id == AV_CODEC_ID_OPUS )
            {
                const uint8_t p_dummy_comment[] = {
                    'O', 'p', 'u', 's',
                    'T', 'a', 'g', 's',
                    0, 0, 0, 0, /* Vendor String length */
                                /* Vendor String */
                    0, 0, 0, 0, /* User Comment List Length */

                };
                unsigned pi_size[2];
                const void *pp_data[2];

                pi_size[0] = i_extra;
                pp_data[0] = p_extra;

                pi_size[1] = sizeof(p_dummy_comment);
                pp_data[1] = p_dummy_comment;

                if( pi_size[0] > 0 && xiph_PackHeaders( &es_fmt.i_extra, &es_fmt.p_extra,
                                                        pi_size, pp_data, 2 ) )
                {
                    es_fmt.i_extra = 0;
                    es_fmt.p_extra = NULL;
                }
            }
            else if( cp->extradata_size > 0 && !es_fmt.i_extra )
            {
                es_fmt.p_extra = malloc( i_extra );
                if( es_fmt.p_extra )
                {
                    es_fmt.i_extra = i_extra;
                    memcpy( es_fmt.p_extra, p_extra, i_extra );
                }
            }

            p_track->p_es = es_out_Add( p_demux->out, &es_fmt );
            if( p_track->p_es && (s->disposition & AV_DISPOSITION_DEFAULT) )
                es_out_Control( p_demux->out, ES_OUT_SET_ES_DEFAULT, p_track->p_es );

            msg_Dbg( p_demux, "adding es: %s codec = %4.4s (%d)",
                     psz_type, (char*)&fcc, cp->codec_id  );
        }
        es_format_Clean( &es_fmt );
    }

    if( p_sys->ic->start_time != (int64_t)AV_NOPTS_VALUE )
        i_start_time = FROM_AV_TS(p_sys->ic->start_time);

    msg_Dbg( p_demux, "AVFormat(%s %s) supported stream", AVPROVIDER(LIBAVFORMAT), LIBAVFORMAT_IDENT );
    msg_Dbg( p_demux, "    - format = %s (%s)",
             p_sys->fmt->name, p_sys->fmt->long_name );
    msg_Dbg( p_demux, "    - start time = %"PRId64, i_start_time );
    msg_Dbg( p_demux, "    - duration = %"PRId64,
             ( p_sys->ic->duration != (int64_t)AV_NOPTS_VALUE ) ?
             FROM_AV_TS(p_sys->ic->duration) : -1 );

    if( p_sys->ic->nb_chapters > 0 )
    {
        p_sys->p_title = vlc_input_title_New();
        p_sys->p_title->i_length = FROM_AV_TS(p_sys->ic->duration);
    }

    for( unsigned i = 0; i < p_sys->ic->nb_chapters; i++ )
    {
        seekpoint_t *s = vlc_seekpoint_New();

        AVDictionaryEntry *title = av_dict_get( p_sys->ic->metadata, "title", NULL, 0);
        if( title && title->value )
        {
            s->psz_name = strdup( title->value );
            EnsureUTF8( s->psz_name );
            msg_Dbg( p_demux, "    - chapter %d: %s", i, s->psz_name );
        }
        s->i_time_offset = vlc_tick_from_samples( p_sys->ic->chapters[i]->start *
            p_sys->ic->chapters[i]->time_base.num,
            p_sys->ic->chapters[i]->time_base.den ) -
            (i_start_time != VLC_TICK_INVALID ? i_start_time : 0 );
        TAB_APPEND( p_sys->p_title->i_seekpoint, p_sys->p_title->seekpoint, s );
    }

    ResetTime( p_demux, 0 );
    return VLC_SUCCESS;
}
Пример #29
0
/*****************************************************************************
 * Open: initializes ES structures
 *****************************************************************************/
static int Open( vlc_object_t * p_this )
{
    demux_t     *p_demux = (demux_t*)p_this;
    demux_sys_t *p_sys;
    const uint8_t *p_peek;
    es_format_t fmt;

    /* Have a peep at the show. */
    if( vlc_stream_Peek( p_demux->s, &p_peek, 4 ) < 4 ) return VLC_EGENERIC;

    if( p_peek[0]!='f' || p_peek[1]!='L' || p_peek[2]!='a' || p_peek[3]!='C' )
    {
        if( !p_demux->obj.force
         && !demux_IsContentType( p_demux, "audio/flac" ) )
            return VLC_EGENERIC;

        /* User forced */
        msg_Err( p_demux, "this doesn't look like a flac stream, "
                 "continuing anyway" );
    }

    p_sys = malloc( sizeof( demux_sys_t ) );
    if( unlikely(p_sys == NULL) )
        return VLC_ENOMEM;

    p_demux->pf_demux   = Demux;
    p_demux->pf_control = Control;
    p_demux->p_sys      = p_sys;
    p_sys->b_start = true;
    p_sys->i_next_block_flags = 0;
    p_sys->p_packetizer = NULL;
    p_sys->p_meta = NULL;
    p_sys->i_length = 0;
    p_sys->i_pts = VLC_TS_INVALID;
    p_sys->p_es = NULL;
    p_sys->p_current_block = NULL;
    TAB_INIT( p_sys->i_seekpoint, p_sys->seekpoint );
    TAB_INIT( p_sys->i_attachments, p_sys->attachments);
    TAB_INIT( p_sys->i_title_seekpoints, p_sys->pp_title_seekpoints );
    p_sys->i_cover_idx = 0;
    p_sys->i_cover_score = 0;

    es_format_Init( &fmt, AUDIO_ES, VLC_CODEC_FLAC );

    /* We need to read and store the STREAMINFO metadata into fmt extra */
    if( ParseHeaders( p_demux, &fmt ) )
        goto error;

    /* Load the FLAC packetizer */
    p_sys->p_packetizer = demux_PacketizerNew( p_demux, &fmt, "flac" );
    if( !p_sys->p_packetizer )
        goto error;

    if( p_sys->i_cover_idx < p_sys->i_attachments )
    {
        char psz_url[128];
        if( !p_sys->p_meta )
            p_sys->p_meta = vlc_meta_New();
        snprintf( psz_url, sizeof(psz_url), "attachment://%s",
                  p_sys->attachments[p_sys->i_cover_idx]->psz_name );
        vlc_meta_Set( p_sys->p_meta, vlc_meta_ArtworkURL, psz_url );
    }

    p_sys->p_es = es_out_Add( p_demux->out, &p_sys->p_packetizer->fmt_in );
    if( !p_sys->p_es )
        goto error;

    return VLC_SUCCESS;
error:
    Close( p_this );
    return VLC_EGENERIC;
}
Пример #30
0
/*****************************************************************************
 * Open: check file and initializes structures
 *****************************************************************************/
static int Open( vlc_object_t *p_this )
{
    demux_t     *p_demux = (demux_t*)p_this;
    demux_sys_t *p_sys;

    uint8_t      hdr[20];
    const uint8_t *p_peek;
    int          i_cat;
    int          i_samples, i_modulo;

    if( stream_Peek( p_demux->s , &p_peek, 4 ) < 4 )
        return VLC_EGENERIC;

    if( memcmp( p_peek, ".snd", 4 ) )
        return VLC_EGENERIC;

    /* skip signature */
    stream_Read( p_demux->s, NULL, 4 );   /* cannot fail */

    /* read header */
    if( stream_Read( p_demux->s, hdr, 20 ) < 20 )
    {
        msg_Err( p_demux, "cannot read" );
        return VLC_EGENERIC;
    }

    if( GetDWBE( &hdr[0]  ) < 24 )
    {
        msg_Err( p_demux, "invalid file" );
        return VLC_EGENERIC;
    }

    DEMUX_INIT_COMMON();
    p_sys = p_demux->p_sys;
    p_sys->i_time = 0;
    p_sys->i_header_size = GetDWBE( &hdr[0] );

    /* skip extra header data */
    if( p_sys->i_header_size > 24 )
    {
        stream_Read( p_demux->s, NULL, p_sys->i_header_size - 24 );
    }

    /* init fmt */
    es_format_Init( &p_sys->fmt, AUDIO_ES, 0 );
    p_sys->fmt.audio.i_rate     = GetDWBE( &hdr[12] );
    p_sys->fmt.audio.i_channels = GetDWBE( &hdr[16] );

#if 0
    p_sys->au.i_header_size   = GetDWBE( &p_sys->au.i_header_size );
    p_sys->au.i_data_size     = GetDWBE( &p_sys->au.i_data_size );
    p_sys->au.i_encoding      = GetDWBE( &p_sys->au.i_encoding );
    p_sys->au.i_sample_rate   = GetDWBE( &p_sys->au.i_sample_rate );
    p_sys->au.i_channels      = GetDWBE( &p_sys->au.i_channels );
#endif
    switch( GetDWBE( &hdr[8] ) )
    {
    case AU_ALAW_8:        /* 8-bit ISDN A-law */
        p_sys->fmt.i_codec               = VLC_CODEC_ALAW;
        p_sys->fmt.audio.i_bitspersample = 8;
        p_sys->fmt.audio.i_blockalign    = 1 * p_sys->fmt.audio.i_channels;
        i_cat                    = AU_CAT_PCM;
        break;

    case AU_MULAW_8:       /* 8-bit ISDN u-law */
        p_sys->fmt.i_codec               = VLC_CODEC_MULAW;
        p_sys->fmt.audio.i_bitspersample = 8;
        p_sys->fmt.audio.i_blockalign    = 1 * p_sys->fmt.audio.i_channels;
        i_cat                    = AU_CAT_PCM;
        break;

    case AU_LINEAR_8:      /* 8-bit linear PCM */
        p_sys->fmt.i_codec               = VLC_FOURCC( 't','w','o','s' );
        p_sys->fmt.audio.i_bitspersample = 8;
        p_sys->fmt.audio.i_blockalign    = 1 * p_sys->fmt.audio.i_channels;
        i_cat                    = AU_CAT_PCM;
        break;

    case AU_LINEAR_16:     /* 16-bit linear PCM */
        p_sys->fmt.i_codec               = VLC_FOURCC( 't','w','o','s' );
        p_sys->fmt.audio.i_bitspersample = 16;
        p_sys->fmt.audio.i_blockalign    = 2 * p_sys->fmt.audio.i_channels;
        i_cat                    = AU_CAT_PCM;
        break;

    case AU_LINEAR_24:     /* 24-bit linear PCM */
        p_sys->fmt.i_codec               = VLC_FOURCC( 't','w','o','s' );
        p_sys->fmt.audio.i_bitspersample = 24;
        p_sys->fmt.audio.i_blockalign    = 3 * p_sys->fmt.audio.i_channels;
        i_cat                    = AU_CAT_PCM;
        break;

    case AU_LINEAR_32:     /* 32-bit linear PCM */
        p_sys->fmt.i_codec               = VLC_FOURCC( 't','w','o','s' );
        p_sys->fmt.audio.i_bitspersample = 32;
        p_sys->fmt.audio.i_blockalign    = 4 * p_sys->fmt.audio.i_channels;
        i_cat                    = AU_CAT_PCM;
        break;

    case AU_FLOAT:         /* 32-bit IEEE floating point */
        p_sys->fmt.i_codec               = VLC_FOURCC( 'a', 'u', 0, AU_FLOAT );
        p_sys->fmt.audio.i_bitspersample = 32;
        p_sys->fmt.audio.i_blockalign    = 4 * p_sys->fmt.audio.i_channels;
        i_cat                    = AU_CAT_PCM;
        break;

    case AU_DOUBLE:        /* 64-bit IEEE floating point */
        p_sys->fmt.i_codec               = VLC_FOURCC( 'a', 'u', 0, AU_DOUBLE );
        p_sys->fmt.audio.i_bitspersample = 64;
        p_sys->fmt.audio.i_blockalign    = 8 * p_sys->fmt.audio.i_channels;
        i_cat                    = AU_CAT_PCM;
        break;

    case AU_ADPCM_G721:    /* 4-bit CCITT g.721 ADPCM */
        p_sys->fmt.i_codec               = VLC_FOURCC( 'a', 'u', 0, AU_ADPCM_G721 );
        p_sys->fmt.audio.i_bitspersample = 0;
        p_sys->fmt.audio.i_blockalign    = 0 * p_sys->fmt.audio.i_channels;
        i_cat                    = AU_CAT_ADPCM;
        break;

    case AU_ADPCM_G722:    /* CCITT g.722 ADPCM */
        p_sys->fmt.i_codec               = VLC_FOURCC( 'a', 'u', 0, AU_ADPCM_G722 );
        p_sys->fmt.audio.i_bitspersample = 0;
        p_sys->fmt.audio.i_blockalign    = 0 * p_sys->fmt.audio.i_channels;
        i_cat                    = AU_CAT_ADPCM;
        break;

    case AU_ADPCM_G723_3:  /* CCITT g.723 3-bit ADPCM */
        p_sys->fmt.i_codec               = VLC_FOURCC( 'a', 'u', 0, AU_ADPCM_G723_3 );
        p_sys->fmt.audio.i_bitspersample = 0;
        p_sys->fmt.audio.i_blockalign    = 0 * p_sys->fmt.audio.i_channels;
        i_cat                    = AU_CAT_ADPCM;
        break;

    case AU_ADPCM_G723_5:  /* CCITT g.723 5-bit ADPCM */
        p_sys->fmt.i_codec               = VLC_FOURCC( 'a', 'u', 0, AU_ADPCM_G723_5 );
        p_sys->fmt.audio.i_bitspersample = 0;
        p_sys->fmt.audio.i_blockalign    = 0 * p_sys->fmt.audio.i_channels;
        i_cat                    = AU_CAT_ADPCM;
        break;

    default:
        msg_Warn( p_demux, "unknow encoding=0x%x", GetDWBE( &hdr[8] ) );
        p_sys->fmt.audio.i_bitspersample = 0;
        p_sys->fmt.audio.i_blockalign    = 0;
        i_cat                    = AU_CAT_UNKNOWN;
        break;
    }

    p_sys->fmt.i_bitrate = p_sys->fmt.audio.i_rate *
                           p_sys->fmt.audio.i_channels *
                           p_sys->fmt.audio.i_bitspersample;

    if( i_cat == AU_CAT_UNKNOWN || i_cat == AU_CAT_ADPCM )
    {
        p_sys->i_frame_size = 0;
        p_sys->i_frame_length = 0;

        msg_Err( p_demux, "unsupported codec/type (Please report it)" );
        free( p_sys );
        return VLC_EGENERIC;
    }

    if( p_sys->fmt.audio.i_rate == 0 )
    {
        msg_Err( p_demux, "invalid samplerate: 0" );
        free( p_sys );
        return VLC_EGENERIC;
    }

    /* add the es */
    p_sys->es = es_out_Add( p_demux->out, &p_sys->fmt );

    /* calculate 50ms frame size/time */
    i_samples = __MAX( p_sys->fmt.audio.i_rate / 20, 1 );
    p_sys->i_frame_size = i_samples * p_sys->fmt.audio.i_channels *
                          ( (p_sys->fmt.audio.i_bitspersample + 7) / 8 );
    if( p_sys->fmt.audio.i_blockalign > 0 )
    {
        if( ( i_modulo = p_sys->i_frame_size % p_sys->fmt.audio.i_blockalign ) != 0 )
        {
            p_sys->i_frame_size += p_sys->fmt.audio.i_blockalign - i_modulo;
        }
    }
    p_sys->i_frame_length = (mtime_t)1000000 *
                            (mtime_t)i_samples /
                            (mtime_t)p_sys->fmt.audio.i_rate;

    return VLC_SUCCESS;
}