static inline void post_error(MpegTSDemuxer *demuxer, const char* description, int result, int code) { char* error_string = g_strdup_printf("%s: %d (%s)", description, result, avelement_error_to_string(AVELEMENT(demuxer), result)); #ifdef DEBUG_OUTPUT g_print ("MpegTS post_error: %s\n", error_string); #endif gst_element_message_full(GST_ELEMENT(demuxer), GST_MESSAGE_ERROR, GST_STREAM_ERROR, code, error_string, NULL, ("mpegtsdemuxer.c"), ("mpegts_demuxer_error"), 0); }
/*********************************************************************************** * chain ***********************************************************************************/ static GstFlowReturn videodecoder_chain(GstPad *pad, GstBuffer *buf) { VideoDecoder *decoder = VIDEODECODER(GST_PAD_PARENT(pad)); BaseDecoder *base = BASEDECODER(decoder); GstFlowReturn result = GST_FLOW_OK; int num_dec = NO_DATA_USED; if (base->is_flushing) // Reject buffers in flushing state. { result = GST_FLOW_WRONG_STATE; goto _exit; } if (!base->is_initialized && !videodecoder_configure(decoder, GST_PAD_CAPS(pad))) { result = GST_FLOW_ERROR; goto _exit; } if (!base->is_hls) { if (av_new_packet(&decoder->packet, GST_BUFFER_SIZE(buf)) == 0) { memcpy(decoder->packet.data, GST_BUFFER_DATA(buf), GST_BUFFER_SIZE(buf)); if (GST_BUFFER_TIMESTAMP_IS_VALID(buf)) base->context->reordered_opaque = GST_BUFFER_TIMESTAMP(buf); else base->context->reordered_opaque = AV_NOPTS_VALUE; num_dec = avcodec_decode_video2(base->context, base->frame, &decoder->frame_finished, &decoder->packet); av_free_packet(&decoder->packet); } else { result = GST_FLOW_ERROR; goto _exit; } } else { av_init_packet(&decoder->packet); decoder->packet.data = GST_BUFFER_DATA(buf); decoder->packet.size = GST_BUFFER_SIZE(buf); if (GST_BUFFER_TIMESTAMP_IS_VALID(buf)) base->context->reordered_opaque = GST_BUFFER_TIMESTAMP(buf); else base->context->reordered_opaque = AV_NOPTS_VALUE; num_dec = avcodec_decode_video2(base->context, base->frame, &decoder->frame_finished, &decoder->packet); } if (num_dec < 0) { // basedecoder_flush(base); #ifdef DEBUG_OUTPUT g_print ("videodecoder_chain error: %s\n", avelement_error_to_string(AVELEMENT(decoder), num_dec)); #endif goto _exit; } if (decoder->frame_finished > 0) { if (!videodecoder_configure_sourcepad(decoder)) result = GST_FLOW_ERROR; else { GstBuffer *outbuf = NULL; result = gst_pad_alloc_buffer_and_set_caps(base->srcpad, base->context->frame_number, decoder->frame_size, GST_PAD_CAPS(base->srcpad), &outbuf); if (result != GST_FLOW_OK) { if (result != GST_FLOW_WRONG_STATE) { gst_element_message_full(GST_ELEMENT(decoder), GST_MESSAGE_ERROR, GST_STREAM_ERROR, GST_STREAM_ERROR_DECODE, ("Decoded video buffer allocation failed"), NULL, ("videodecoder.c"), ("videodecoder_chain"), 0); } } else { if (base->frame->reordered_opaque != AV_NOPTS_VALUE) { GST_BUFFER_TIMESTAMP(outbuf) = base->frame->reordered_opaque; GST_BUFFER_DURATION(outbuf) = GST_BUFFER_DURATION(buf); // Duration for video usually same } GST_BUFFER_SIZE(outbuf) = decoder->frame_size; // Copy image by parts from different arrays. memcpy(GST_BUFFER_DATA(outbuf), base->frame->data[0], decoder->u_offset); memcpy(GST_BUFFER_DATA(outbuf) + decoder->u_offset, base->frame->data[1], decoder->uv_blocksize); memcpy(GST_BUFFER_DATA(outbuf) + decoder->v_offset, base->frame->data[2], decoder->uv_blocksize); GST_BUFFER_OFFSET_END(outbuf) = GST_BUFFER_OFFSET_NONE; if (decoder->discont || GST_BUFFER_IS_DISCONT(buf)) { #ifdef DEBUG_OUTPUT g_print("Video discont: frame size=%dx%d\n", base->context->width, base->context->height); #endif GST_BUFFER_FLAG_SET(outbuf, GST_BUFFER_FLAG_DISCONT); decoder->discont = FALSE; } #ifdef VERBOSE_DEBUG g_print("videodecoder: pushing buffer ts=%.4f sec", (double)GST_BUFFER_TIMESTAMP(outbuf)/GST_SECOND); #endif result = gst_pad_push(base->srcpad, outbuf); #ifdef VERBOSE_DEBUG g_print(" done, res=%s\n", gst_flow_get_name(result)); #endif } } } _exit: // INLINE - gst_buffer_unref() gst_buffer_unref(buf); return result; }