static void gst_vlc_video_sink_set_property( GObject *p_object, guint i_prop_id, const GValue *p_value, GParamSpec *p_pspec ) { GstVlcVideoSink *p_vsink = GST_VLC_VIDEO_SINK( p_object ); switch( i_prop_id ) { case PROP_ALLOCATOR: { GstAllocator *p_allocator = (GstAllocator*) g_value_get_pointer( p_value ); if( GST_IS_VLC_PICTURE_PLANE_ALLOCATOR( p_allocator )) { if( p_vsink->p_allocator ) gst_object_unref( p_vsink->p_allocator ); p_vsink->p_allocator = gst_object_ref( p_allocator ); } else msg_Warn( p_vsink->p_dec, "Invalid Allocator set"); } break; case PROP_ID: { p_vsink->p_dec = (decoder_t*) g_value_get_pointer( p_value ); } break; default: break; } }
GstVlcVideoPool* gst_vlc_video_pool_new( GstAllocator *p_allocator, decoder_t *p_dec ) { GstVlcVideoPool *p_pool; if( !GST_IS_VLC_PICTURE_PLANE_ALLOCATOR( p_allocator )) { msg_Err( p_pool->p_dec, "unspported allocator for pool" ); return NULL; } p_pool = g_object_new( GST_TYPE_VLC_VIDEO_POOL, NULL ); p_pool->p_allocator = gst_object_ref( p_allocator ); p_pool->p_dec = p_dec; return p_pool; }
static gboolean gst_vlc_video_pool_set_config( GstBufferPool *p_pool, GstStructure *p_config ) { GstVlcVideoPool *p_vpool = GST_VLC_VIDEO_POOL_CAST( p_pool ); GstCaps *p_caps; GstVideoInfo info; guint size, min_buffers, max_buffers; GstAllocator *p_allocator; GstAllocationParams params; if( !gst_buffer_pool_config_get_params( p_config, &p_caps, &size, &min_buffers, &max_buffers )) goto wrong_config; if( p_caps == NULL ) goto no_caps; gst_buffer_pool_config_get_allocator( p_config, &p_allocator, ¶ms ); if( p_allocator ) { if( !GST_IS_VLC_PICTURE_PLANE_ALLOCATOR( p_allocator )) goto unsupported_allocator; else { if( p_vpool->p_allocator ) gst_object_unref( p_vpool->p_allocator ); p_vpool->p_allocator = gst_object_ref ( p_allocator ); } } /* now parse the caps from the config */ if ( !gst_video_info_from_caps( &info, p_caps )) goto wrong_caps; /* enable metadata based on config of the pool */ p_vpool->b_add_metavideo = gst_buffer_pool_config_has_option( p_config, GST_BUFFER_POOL_OPTION_VIDEO_META ); if( !gst_vlc_picture_plane_allocator_query_format( p_vpool->p_allocator, &info, p_caps)) goto unknown_format; if( p_vpool->p_caps ) gst_caps_unref( p_vpool->p_caps ); p_vpool->p_caps = gst_caps_ref( p_caps ); p_vpool->info = info; gst_buffer_pool_config_set_params( p_config, p_caps, info.size, min_buffers, max_buffers ); return GST_BUFFER_POOL_CLASS (parent_class)->set_config( p_pool, p_config ); /* ERRORS */ wrong_config: { msg_Err(p_vpool->p_dec, "wrong pool config" ); return FALSE; } no_caps: { msg_Err(p_vpool->p_dec, "no input caps in config" ); return FALSE; } wrong_caps: { msg_Err(p_vpool->p_dec, "invalid caps" ); return FALSE; } unknown_format: { msg_Err(p_vpool->p_dec, "format unsupported" ); return FALSE; } unsupported_allocator: { msg_Err(p_vpool->p_dec, "allocator unsupported" ); return FALSE; } }
/* Decode */ static picture_t *DecodeBlock( decoder_t *p_dec, block_t **pp_block ) { block_t *p_block; picture_t *p_pic = NULL; decoder_sys_t *p_sys = p_dec->p_sys; GstMessage *p_msg; GstBuffer *p_buf; if( !pp_block ) return NULL; p_block = *pp_block; if( !p_block ) goto check_messages; if( unlikely( p_block->i_flags & (BLOCK_FLAG_DISCONTINUITY | BLOCK_FLAG_CORRUPTED ) ) ) { if( p_block->i_flags & BLOCK_FLAG_DISCONTINUITY ) Flush( p_dec ); if( p_block->i_flags & BLOCK_FLAG_CORRUPTED ) { block_Release( p_block ); goto done; } } if( likely( p_block->i_buffer ) ) { p_buf = gst_buffer_new_wrapped_full( GST_MEMORY_FLAG_READONLY, p_block->p_start, p_block->i_size, p_block->p_buffer - p_block->p_start, p_block->i_buffer, p_block, ( GDestroyNotify )block_Release ); if( unlikely( p_buf == NULL ) ) { msg_Err( p_dec, "failed to create input gstbuffer" ); p_dec->b_error = true; block_Release( p_block ); 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_block->i_length > VLC_TS_INVALID ) GST_BUFFER_DURATION( p_buf ) = gst_util_uint64_scale( p_block->i_length, 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 ); /* Give the input buffer to GStreamer Bin. * * libvlc libvlc * \ (i/p) (o/p) ^ * \ / * ___v____GSTREAMER BIN_____/____ * | | * | appsrc-->decode-->vlcsink | * |_______________________________| * * * * * * * * * * * * * * * * * * * * * */ if( unlikely( gst_app_src_push_buffer( GST_APP_SRC_CAST( p_sys->p_decode_src ), p_buf ) != GST_FLOW_OK ) ) { /* block will be released internally, * when gst_buffer_unref() is called */ p_dec->b_error = true; msg_Err( p_dec, "failed to push buffer" ); goto done; } } else block_Release( p_block ); check_messages: /* Poll for any messages, errors */ p_msg = gst_bus_pop_filtered( p_sys->p_bus, GST_MESSAGE_ASYNC_DONE | GST_MESSAGE_ERROR | GST_MESSAGE_EOS | GST_MESSAGE_WARNING | GST_MESSAGE_INFO ); if( p_msg ) { switch( GST_MESSAGE_TYPE( p_msg ) ){ case GST_MESSAGE_EOS: /* for debugging purpose */ msg_Warn( p_dec, "got unexpected eos" ); break; /* First buffer received */ case GST_MESSAGE_ASYNC_DONE: /* for debugging purpose */ p_sys->b_prerolled = true; msg_Dbg( p_dec, "Pipeline is prerolled" ); break; default: p_dec->b_error = default_msg_handler( p_dec, p_msg ); if( p_dec->b_error ) { gst_message_unref( p_msg ); goto done; } break; } gst_message_unref( p_msg ); } /* Look for any output buffers in the queue */ if( gst_atomic_queue_peek( p_sys->p_que ) ) { GstBuffer *p_buf = GST_BUFFER_CAST( gst_atomic_queue_pop( p_sys->p_que )); GstMemory *p_mem; if(( p_mem = gst_buffer_peek_memory( p_buf, 0 )) && GST_IS_VLC_PICTURE_PLANE_ALLOCATOR( p_mem->allocator )) { p_pic = picture_Hold(( (GstVlcPicturePlane*) p_mem )->p_pic ); } else { GstVideoFrame frame; /* Get a new picture */ p_pic = decoder_NewPicture( p_dec ); if( !p_pic ) goto done; if( unlikely( !gst_video_frame_map( &frame, &p_sys->vinfo, p_buf, GST_MAP_READ ) ) ) { msg_Err( p_dec, "failed to map gst video frame" ); gst_buffer_unref( p_buf ); p_dec->b_error = true; goto done; } gst_CopyPicture( p_pic, &frame ); gst_video_frame_unmap( &frame ); } if( likely( GST_BUFFER_PTS_IS_VALID( p_buf ) ) ) p_pic->date = gst_util_uint64_scale( GST_BUFFER_PTS( p_buf ), GST_MSECOND, GST_SECOND ); else msg_Warn( p_dec, "Gst Buffer has no timestamp" ); gst_buffer_unref( p_buf ); } done: *pp_block = NULL; return p_pic; }