Exemple #1
0
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;
}