[vlc-devel] [PATCH 1/1] codec: Add GStreamer based video decoder module
Rafaël Carré
funman at videolan.org
Sun Apr 20 21:37:20 CEST 2014
On 04/19/14 13:16, ved kpl wrote:
> Thanks for the comments Rafael..
> Yeah, GStreamer should have VLC based plugin :).
>
> Will incorporate the changes as per your review.
> Had some queries though. I have put them inline.
OK, answers below
> On Sat, Apr 19, 2014 at 2:38 PM, Rafaël Carré <funman at videolan.org> wrote:
>>> + switch( i_fmt )
>>> + {
>>> + case VLC_CODEC_H264:
>>
>> nitpicking: align case on the switch level
>>
> vikram: you mean something like:
> switch (a)
> {
> case 1:
> break;
> case 2:
> break;
> }
I use:
switch(a) {
case 1:
foo();
break;
case 2:
break;
}
>>> + if( unlikely( p_dec->p_sys->b_out_fmt_set == false ) )
>>> + {
>>> + do
>>> + {
>>> + if( gst_pad_has_current_caps( p_pad ) )
>>
>> while (gst_pad_has_current_caps(p_pad))
> Vikram: why "while"? Probably I will need an "if" there?
Well I assume you want to use break to exit the block, thus the
do { ... } while(0);
If you don't use break, just use if() and deindent that whole block of code
to the left.
>>> + b_ret = gst_structure_get_int ( p_str,
>> "width",
>>> + ( gint*
>> )&p_dec->fmt_out.video.i_width );
>>> + b_ret &= gst_structure_get_int ( p_str,
>> "height",
>>> + ( gint*
>> )&p_dec->fmt_out.video.i_height );
>>
>> I'd prefer to use && here
>> Vikram: I didn't get you. where exactly?
b_ret = gst_structure_get_int(...) && gst_structure_get_int(...);
You could also use video_format_t *fmt = &p_dec->fmt_out.video;
>>> +/* Copy the frame data from the GstBuffer (from decoder)
>>> + * to the picture obtained from downstream in VLC */
>>> +static void gst_CopyPicture( picture_t *p_pic, GstVideoFrame *frame )
>>
>> So it's not possible to tell Gst where to decode data and let it do
>> the memcpy if e.g. using a hardware decoder?
>>
> Vikram: Yes, it is possible and I am working on it as time permits. As
> I have mentioned in the cover letter, zero-copy is possible.
> That'll will require some proper handling w.r.t buffer
> management. I plan to add this part as a next patch.
Good, let's keep that for next patch then.
>>> +#define VLC_GST_CHECK(r, v, s, t, x) \
>>> + { if(r == v) { msg_Info(p_dec, s); i_rval = t; goto x; } }
>>
>> msg_Err ?
>> Vikram: Yeah, I had this as msg_Err earlier, But I don't know prompted me
>> to use Info :-/. I will revert it back to Err.
Maybe msg_Info() is more visible in the log ;)
>>> +/* Decode */
>>> +static picture_t *DecodeBlock( decoder_t *p_dec, block_t **pp_block )
>>> +{
>>> + block_t *p_block = NULL;
>>> + picture_t *p_pic = NULL;
>>> + decoder_sys_t *p_sys = p_dec->p_sys;
>>> + GstMessage* p_msg;
>>> + gboolean b_ret;
>>> + guint8* p_data;
>>> + GstBuffer* p_buf;
>>> +
>>> + if( !pp_block || !*pp_block ) {
>>> + return NULL;
>>> + }
>>
>> Decoder should be flushed if *pp_block == NULL
>> Vikram: I see.. So does that mean that already decoded buffers (waiting
>> in the queue to be popped out ) should also be flushed and not be rendered?
Not exactly, they should be returned by DecodeBlock
block_t *p_block = *pp_block;
if (!p_block) {
return buffered_frame;
}
That's the case if the first calls to DecodeBlock did not return data.
See CODEC_CAP_DELAY in avcodec/video.c
>>> + memcpy( p_data, p_block->p_buffer, p_block->i_buffer );
>>> + p_buf = gst_buffer_new_wrapped( p_data, p_block->i_buffer );
>>
>> gst_buffer_new_wrapped_full instead of malloc+memcpy ?
>>
> Vikram: Is it ok to call block_Release() from any thread context? I
> thought it can only be called from DecodeBlock() thread context.
> Neverthless, you are right. mempcy for
> input buffer can be avoided.
Yes it is ok.
> Then you can call block_Release in the destructor
>> Vikram: If it is necessary to call block_release() only from
>> decode_block() thread context, I'll use a queue so that in destructor ,
>> instead of doing a release, I will push the block
>>
> to the queue, and in decodeblock(), I'll pop the blocks
> from the queue and release them.
>
>
>>> + if( unlikely( p_buf == NULL ) )
>>> + {
>>> + free( p_data );
>>> + block_Release( p_block );
>>> + msg_Err( p_dec, "failed to create gstbuffer" );
>>> + p_dec->b_error = true;
>>> + goto done;
>>> + }
>>> +
>>> + if( p_block->i_dts > VLC_TS_INVALID )
>>> + GST_BUFFER_DTS( p_buf ) = gst_util_uint64_scale( p_block->i_dts,
>>> + GST_SECOND, GST_MSECOND );
>>> +
>>> + if( p_block->i_pts <= VLC_TS_INVALID )
>>> + GST_BUFFER_PTS( p_buf ) = GST_BUFFER_DTS( p_buf );
>>> + else
>>> + GST_BUFFER_PTS( p_buf ) = gst_util_uint64_scale( p_block->i_pts,
>>> + GST_SECOND, GST_MSECOND );
>>> +
>>> + if( p_dec->fmt_in.video.i_frame_rate &&
>>> + p_dec->fmt_in.video.i_frame_rate_base )
>>> + GST_BUFFER_DURATION( p_buf ) = gst_util_uint64_scale(
>> GST_SECOND,
>>> + p_dec->fmt_in.video.i_frame_rate_base,
>>> + p_dec->fmt_in.video.i_frame_rate );
>>
>> p_block->i_length ?
>> Vikram: oh! missed that! i_length means duration, right?
Yes, in microsecond units (1/CLOCK_FREQ)
BTW don't hesitate to ask on IRC
More information about the vlc-devel
mailing list