/***************************************************************************** * ProcessHeaders: process Kate headers. *****************************************************************************/ static int ProcessHeaders( decoder_t *p_dec ) { decoder_sys_t *p_sys = p_dec->p_sys; kate_packet kp; unsigned pi_size[XIPH_MAX_HEADER_COUNT]; void *pp_data[XIPH_MAX_HEADER_COUNT]; unsigned i_count; if( xiph_SplitHeaders( pi_size, pp_data, &i_count, p_dec->fmt_in.i_extra, p_dec->fmt_in.p_extra) ) return VLC_EGENERIC; int i_ret = VLC_SUCCESS; if( i_count < 1 ) { i_ret = VLC_EGENERIC; goto end; } /* Take care of the initial Kate header */ kp.nbytes = pi_size[0]; kp.data = pp_data[0]; i_ret = kate_decode_headerin( &p_sys->ki, &p_sys->kc, &kp ); if( i_ret < 0 ) { msg_Err( p_dec, "this bitstream does not contain Kate data (%d)", i_ret ); goto end; } msg_Dbg( p_dec, "%s %s text, granule rate %f, granule shift %d", p_sys->ki.language, p_sys->ki.category, (double)p_sys->ki.gps_numerator/p_sys->ki.gps_denominator, p_sys->ki.granule_shift); /* parse all remaining header packets */ for( unsigned i_headeridx = 1; i_headeridx < i_count; i_headeridx++ ) { kp.nbytes = pi_size[i_headeridx]; kp.data = pp_data[i_headeridx]; i_ret = kate_decode_headerin( &p_sys->ki, &p_sys->kc, &kp ); if( i_ret < 0 ) { msg_Err( p_dec, "Kate header %d is corrupted: %d", i_headeridx, i_ret ); goto end; } /* header 1 is comments */ if( i_headeridx == 1 ) { ParseKateComments( p_dec ); } } #ifdef ENABLE_PACKETIZER if( !p_sys->b_packetizer ) #endif { /* We have all the headers, initialize decoder */ msg_Dbg( p_dec, "we have all headers, initialize libkate for decoding" ); i_ret = kate_decode_init( &p_sys->k, &p_sys->ki ); if (i_ret < 0) { msg_Err( p_dec, "Kate failed to initialize for decoding: %d", i_ret ); return VLC_EGENERIC; } p_sys->b_ready = true; } #ifdef ENABLE_PACKETIZER else { p_dec->fmt_out.i_extra = p_dec->fmt_in.i_extra; p_dec->fmt_out.p_extra = xrealloc( p_dec->fmt_out.p_extra, p_dec->fmt_out.i_extra ); memcpy( p_dec->fmt_out.p_extra, p_dec->fmt_in.p_extra, p_dec->fmt_out.i_extra ); } #endif end: for( unsigned i = 0; i < i_count; i++ ) free( pp_data[i] ); return i_ret < 0 ? VLC_EGENERIC : VLC_SUCCESS; }
static GstFlowReturn gst_kate_parse_push_headers (GstKateParse * parse) { /* mark and put on caps */ GstCaps *caps; GstBuffer *outbuf; kate_packet packet; GList *headers, *outbuf_list = NULL; int ret; gboolean res; /* get the headers into the caps, passing them to kate as we go */ caps = gst_kate_util_set_header_on_caps (&parse->element, gst_pad_get_current_caps (parse->sinkpad), parse->streamheader); if (G_UNLIKELY (!caps)) { GST_ELEMENT_ERROR (parse, STREAM, DECODE, (NULL), ("Failed to set headers on caps")); return GST_FLOW_ERROR; } GST_DEBUG_OBJECT (parse, "here are the caps: %" GST_PTR_FORMAT, caps); res = gst_pad_set_caps (parse->srcpad, caps); gst_caps_unref (caps); if (G_UNLIKELY (!res)) { GST_WARNING_OBJECT (parse->srcpad, "Failed to set caps on source pad"); return GST_FLOW_NOT_NEGOTIATED; } headers = parse->streamheader; while (headers) { GstMapInfo info; outbuf = GST_BUFFER_CAST (headers->data); if (!gst_buffer_map (outbuf, &info, GST_MAP_READ)) { GST_WARNING_OBJECT (outbuf, "Failed to map buffer"); continue; } kate_packet_wrap (&packet, info.size, info.data); ret = kate_decode_headerin (&parse->ki, &parse->kc, &packet); if (G_UNLIKELY (ret < 0)) { GST_WARNING_OBJECT (parse, "Failed to decode header: %s", gst_kate_util_get_error_message (ret)); } gst_buffer_unmap (outbuf, &info); /* takes ownership of outbuf, which was previously in parse->streamheader */ GST_BUFFER_FLAG_SET (outbuf, GST_BUFFER_FLAG_HEADER); outbuf_list = g_list_append (outbuf_list, outbuf); headers = headers->next; } /* first process queued events */ gst_kate_parse_drain_event_queue (parse); /* push out buffers, ignoring return value... */ headers = outbuf_list; while (headers) { outbuf = GST_BUFFER_CAST (headers->data); gst_pad_push (parse->srcpad, outbuf); headers = headers->next; } g_list_free (outbuf_list); g_list_free (parse->streamheader); parse->streamheader = NULL; parse->streamheader_sent = TRUE; return GST_FLOW_OK; }