From 535cd3d2fa472ac5d659f794cf0c99f4690d943a Mon Sep 17 00:00:00 2001 From: Wim Taymans Date: Wed, 26 Oct 2005 16:45:04 +0000 Subject: [PATCH] ext/mpeg2dec/gstmpeg2dec.*: Removed lots of dubious code. Original commit message from CVS: * ext/mpeg2dec/gstmpeg2dec.c: (gst_mpeg2dec_init), (gst_mpeg2dec_dispose), (gst_mpeg2dec_reset), (gst_mpeg2dec_alloc_buffer), (gst_mpeg2dec_negotiate_format), (handle_sequence), (handle_picture): * ext/mpeg2dec/gstmpeg2dec.h: Removed lots of dubious code. Handle flushing and seeking correctly. Still leaks though... --- ChangeLog | 10 + ext/mpeg2dec/gstmpeg2dec.c | 657 +++++++++---------------------------- ext/mpeg2dec/gstmpeg2dec.h | 2 + 3 files changed, 170 insertions(+), 499 deletions(-) diff --git a/ChangeLog b/ChangeLog index f33c1c5f5a..197b7365a8 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,13 @@ +2005-10-26 Wim Taymans + + * ext/mpeg2dec/gstmpeg2dec.c: (gst_mpeg2dec_init), + (gst_mpeg2dec_dispose), (gst_mpeg2dec_reset), + (gst_mpeg2dec_alloc_buffer), (gst_mpeg2dec_negotiate_format), + (handle_sequence), (handle_picture): + * ext/mpeg2dec/gstmpeg2dec.h: + Removed lots of dubious code. + Handle flushing and seeking correctly. Still leaks though... + 2005-10-24 Christian Schaller * configure.ac: port over thomas plugin listing from base diff --git a/ext/mpeg2dec/gstmpeg2dec.c b/ext/mpeg2dec/gstmpeg2dec.c index e645168073..42b6bb7f6d 100644 --- a/ext/mpeg2dec/gstmpeg2dec.c +++ b/ext/mpeg2dec/gstmpeg2dec.c @@ -187,9 +187,6 @@ static const GstEventMask *gst_mpeg2dec_get_event_masks (GstPad * pad); static GstElementClass *parent_class = NULL; static GstBuffer *crop_buffer (GstMpeg2dec * mpeg2dec, GstBuffer * input); -static gboolean check_buffer (GstMpeg2dec * mpeg2dec, GstBuffer * buf); -static gboolean free_buffer (GstMpeg2dec * mpeg2dec, GstBuffer * buf); -static void free_all_buffers (GstMpeg2dec * mpeg2dec); /*static guint gst_mpeg2dec_signals[LAST_SIGNAL] = { 0 };*/ @@ -260,8 +257,6 @@ gst_mpeg2dec_class_init (GstMpeg2decClass * klass) static void gst_mpeg2dec_init (GstMpeg2dec * mpeg2dec) { - int i; - /* create the sink and src pads */ mpeg2dec->sinkpad = gst_pad_new_from_template (gst_static_pad_template_get @@ -293,35 +288,6 @@ gst_mpeg2dec_init (GstMpeg2dec * mpeg2dec) #endif /* initialize the mpeg2dec acceleration */ - mpeg2_accel (MPEG2_ACCEL_DETECT); - mpeg2dec->closed = TRUE; - mpeg2dec->have_fbuf = FALSE; - mpeg2dec->offset = 0; - - for (i = 0; i < GST_MPEG2DEC_NUM_BUFS; i++) - mpeg2dec->buffers[i] = NULL; - -} - -static void -gst_mpeg2dec_close_decoder (GstMpeg2dec * mpeg2dec) -{ - if (!mpeg2dec->closed) { - mpeg2_close (mpeg2dec->decoder); - free_all_buffers (mpeg2dec); - mpeg2dec->closed = TRUE; - mpeg2dec->decoder = NULL; - } -} - -static void -gst_mpeg2dec_open_decoder (GstMpeg2dec * mpeg2dec) -{ - gst_mpeg2dec_close_decoder (mpeg2dec); - mpeg2dec->decoder = mpeg2_init (); - mpeg2dec->closed = FALSE; - mpeg2dec->have_fbuf = FALSE; - mpeg2_custom_fbuf (mpeg2dec->decoder, 1); } static void @@ -329,7 +295,11 @@ gst_mpeg2dec_dispose (GObject * object) { GstMpeg2dec *mpeg2dec = GST_MPEG2DEC (object); - gst_mpeg2dec_close_decoder (mpeg2dec); + if (mpeg2dec->decoder) { + GST_DEBUG_OBJECT (mpeg2dec, "closing decoder"); + mpeg2_close (mpeg2dec->decoder); + mpeg2dec->decoder = NULL; + } G_OBJECT_CLASS (parent_class)->dispose (object); } @@ -345,10 +315,11 @@ gst_mpeg2dec_reset (GstMpeg2dec * mpeg2dec) mpeg2dec->segment_end = -1; mpeg2dec->discont_state = MPEG2DEC_DISC_NEW_PICTURE; mpeg2dec->frame_period = 0; - gst_pad_use_fixed_caps (mpeg2dec->srcpad); - gst_mpeg2dec_open_decoder (mpeg2dec); mpeg2dec->need_sequence = TRUE; + mpeg2dec->next_time = 0; + mpeg2dec->offset = 0; } + static void gst_mpeg2dec_set_index (GstElement * element, GstIndex * index) { @@ -367,65 +338,6 @@ gst_mpeg2dec_get_index (GstElement * element) return mpeg2dec->index; } -static gboolean -put_buffer (GstMpeg2dec * mpeg2dec, GstBuffer * buf) -{ - int i; - - for (i = 0; i < GST_MPEG2DEC_NUM_BUFS; i++) { - if (mpeg2dec->buffers[i] == NULL) { - GST_DEBUG_OBJECT (mpeg2dec, "Placing %p at slot %d", buf, i); - mpeg2dec->buffers[i] = buf; - return TRUE; - } - } - return FALSE; -} - -static gboolean -check_buffer (GstMpeg2dec * mpeg2dec, GstBuffer * buf) -{ - int i; - - for (i = 0; i < GST_MPEG2DEC_NUM_BUFS; i++) - if (mpeg2dec->buffers[i] == buf) - return TRUE; - - return FALSE; -} - -static gboolean -free_buffer (GstMpeg2dec * mpeg2dec, GstBuffer * buf) -{ - int i; - - for (i = 0; i < GST_MPEG2DEC_NUM_BUFS; i++) { - if (mpeg2dec->buffers[i] == buf) { - GST_DEBUG_OBJECT (mpeg2dec, "Releasing %p at slot %d", buf, i); - gst_buffer_unref (buf); - mpeg2dec->buffers[i] = NULL; - - return TRUE; - } - } - return FALSE; -} - -static void -free_all_buffers (GstMpeg2dec * mpeg2dec) -{ - int i; - - for (i = 0; i < GST_MPEG2DEC_NUM_BUFS; i++) { - if (mpeg2dec->buffers[i] != NULL) { - GST_DEBUG_OBJECT (mpeg2dec, "free_all Releasing %p at slot %d", - mpeg2dec->buffers[i], i); - gst_buffer_unref (mpeg2dec->buffers[i]); - mpeg2dec->buffers[i] = NULL; - } - } -} - static GstBuffer * crop_buffer (GstMpeg2dec * mpeg2dec, GstBuffer * input) { @@ -504,85 +416,52 @@ gst_mpeg2dec_alloc_buffer (GstMpeg2dec * mpeg2dec, gint64 offset) guint8 *buf[3], *out = NULL; GstFlowReturn ret = GST_FLOW_OK; - do { + if (mpeg2dec->format == MPEG2DEC_FORMAT_I422) { + ret = + gst_pad_alloc_buffer (mpeg2dec->srcpad, GST_BUFFER_OFFSET_NONE, + size * 2, GST_PAD_CAPS (mpeg2dec->srcpad), &outbuf); + if (ret != GST_FLOW_OK) { + GST_ELEMENT_ERROR (mpeg2dec, RESOURCE, FAILED, (NULL), + ("Failed to allocate memory for buffer")); + goto done; + } + out = GST_BUFFER_DATA (outbuf); - if (mpeg2dec->format == MPEG2DEC_FORMAT_I422) { - ret = - gst_pad_alloc_buffer (mpeg2dec->srcpad, GST_BUFFER_OFFSET_NONE, - size * 2, GST_PAD_CAPS (mpeg2dec->srcpad), &outbuf); - if (ret != GST_FLOW_OK) { - GST_ELEMENT_ERROR (mpeg2dec, RESOURCE, FAILED, (NULL), - ("Failed to allocate memory for buffer")); - break; - } - /* 0.9 - outbuf = - gst_pad_alloc_buffer (mpeg2dec->srcpad, GST_BUFFER_OFFSET_NONE, - size * 2); + buf[0] = out; + buf[1] = buf[0] + size; + buf[2] = buf[1] + size / 2; - if (!outbuf) { - GST_ELEMENT_ERROR (mpeg2dec, RESOURCE, FAILED, (NULL), - ("Failed to allocate memory for buffer")); - return NULL; - } - */ + } else { + ret = + gst_pad_alloc_buffer (mpeg2dec->srcpad, GST_BUFFER_OFFSET_NONE, + (size * 3) / 2, GST_PAD_CAPS (mpeg2dec->srcpad), &outbuf); + if (ret != GST_FLOW_OK) { + GST_ELEMENT_ERROR (mpeg2dec, RESOURCE, FAILED, (NULL), + ("Failed to allocate memory for buffer")); + goto done; + } - out = GST_BUFFER_DATA (outbuf); + out = GST_BUFFER_DATA (outbuf); + buf[0] = out; + if (mpeg2dec->format == MPEG2DEC_FORMAT_I420) { buf[0] = out; buf[1] = buf[0] + size; - buf[2] = buf[1] + size / 2; - + buf[2] = buf[1] + size / 4; } else { - /* 0.9 - outbuf = - gst_pad_alloc_buffer (mpeg2dec->srcpad, GST_BUFFER_OFFSET_NONE, - (size * 3) / 2); - */ - ret = - gst_pad_alloc_buffer (mpeg2dec->srcpad, GST_BUFFER_OFFSET_NONE, - size * 2, GST_PAD_CAPS (mpeg2dec->srcpad), &outbuf); - if (ret != GST_FLOW_OK) { - GST_ELEMENT_ERROR (mpeg2dec, RESOURCE, FAILED, (NULL), - ("Failed to allocate memory for buffer")); - break; - } - - out = GST_BUFFER_DATA (outbuf); - buf[0] = out; - if (mpeg2dec->format == MPEG2DEC_FORMAT_I420) { - buf[0] = out; - buf[1] = buf[0] + size; - buf[2] = buf[1] + size / 4; - } else { - buf[0] = out; - buf[2] = buf[0] + size; - buf[1] = buf[2] + size / 4; - } + buf[2] = buf[0] + size; + buf[1] = buf[2] + size / 4; } - - if (!put_buffer (mpeg2dec, outbuf)) { -#if 0 - GST_ELEMENT_ERROR (mpeg2dec, LIBRARY, TOO_LAZY, (NULL), - ("No free slot. libmpeg2 did not discard buffers.")); -#else - GST_WARNING_OBJECT (mpeg2dec, - "No free slot. libmpeg2 did not discard buffers."); -#endif - return NULL; - } - - mpeg2_custom_fbuf (mpeg2dec->decoder, 1); - mpeg2_set_buf (mpeg2dec->decoder, buf, outbuf); - - /* we store the original byteoffset of this picture in the stream here - * because we need it for indexing */ - GST_BUFFER_OFFSET (outbuf) = offset; - } - while (FALSE); + mpeg2_set_buf (mpeg2dec->decoder, buf, outbuf); + + /* we store the original byteoffset of this picture in the stream here + * because we need it for indexing */ + GST_BUFFER_OFFSET (outbuf) = offset; + +done: if (ret != GST_FLOW_OK) { outbuf = NULL; /* just to asure NULL return, looking the path above it happens only when gst_pad_alloc_buffer @@ -596,54 +475,36 @@ static gboolean gst_mpeg2dec_negotiate_format (GstMpeg2dec * mpeg2dec) { GstCaps *caps; - guint32 fourcc, myFourcc; - gboolean ret = TRUE; + guint32 fourcc; const mpeg2_info_t *info; const mpeg2_sequence_t *sequence; - if (!GST_PAD_IS_LINKED (mpeg2dec->srcpad)) { - mpeg2dec->format = MPEG2DEC_FORMAT_I420; - return TRUE; - } - info = mpeg2_info (mpeg2dec->decoder); sequence = info->sequence; if (sequence->width != sequence->chroma_width && - sequence->height != sequence->chroma_height) - myFourcc = GST_STR_FOURCC ("I420"); - else if (sequence->width == sequence->chroma_width || - sequence->height == sequence->chroma_height) - myFourcc = GST_STR_FOURCC ("Y42B"); - else { + sequence->height != sequence->chroma_height) { + fourcc = GST_STR_FOURCC ("I420"); + mpeg2dec->format = MPEG2DEC_FORMAT_I420; + } else if (sequence->width == sequence->chroma_width || + sequence->height == sequence->chroma_height) { + fourcc = GST_STR_FOURCC ("Y42B"); + mpeg2dec->format = MPEG2DEC_FORMAT_I422; + } else { g_warning ("mpeg2dec: 4:4:4 format not yet supported"); return (FALSE); } caps = gst_caps_new_simple ("video/x-raw-yuv", - "format", GST_TYPE_FOURCC, myFourcc, + "format", GST_TYPE_FOURCC, fourcc, "width", G_TYPE_INT, mpeg2dec->width, "height", G_TYPE_INT, mpeg2dec->height, "pixel-aspect-ratio", GST_TYPE_FRACTION, mpeg2dec->pixel_width, mpeg2dec->pixel_height, "framerate", G_TYPE_DOUBLE, mpeg2dec->frame_rate, NULL); - // ret = gst_pad_set_explicit_caps (mpeg2dec->srcpad, caps); - ret = gst_pad_set_caps (mpeg2dec->srcpad, caps); - if (!ret) - return FALSE; - - /* it worked, try to find what it was again */ - gst_structure_get_fourcc (gst_caps_get_structure (caps, 0), - "format", &fourcc); - - if (fourcc == GST_STR_FOURCC ("Y42B")) { - mpeg2dec->format = MPEG2DEC_FORMAT_I422; - } else if (fourcc == GST_STR_FOURCC ("I420")) { - mpeg2dec->format = MPEG2DEC_FORMAT_I420; - } else { - mpeg2dec->format = MPEG2DEC_FORMAT_YV12; - } + gst_pad_set_caps (mpeg2dec->srcpad, caps); + gst_caps_unref (caps); return TRUE; } @@ -679,20 +540,23 @@ handle_sequence (GstMpeg2dec * mpeg2dec, const mpeg2_info_t * info) info->sequence->transfer_characteristics, info->sequence->matrix_coefficients); - if (!gst_mpeg2dec_negotiate_format (mpeg2dec)) { - GST_ELEMENT_ERROR (mpeg2dec, CORE, NEGOTIATION, (NULL), (NULL)); - return FALSE; - } + if (!gst_mpeg2dec_negotiate_format (mpeg2dec)) + goto negotiate_failed; - free_all_buffers (mpeg2dec); - if (!gst_mpeg2dec_alloc_buffer (mpeg2dec, mpeg2dec->offset) || - !gst_mpeg2dec_alloc_buffer (mpeg2dec, mpeg2dec->offset) || - !gst_mpeg2dec_alloc_buffer (mpeg2dec, mpeg2dec->offset)) + mpeg2_custom_fbuf (mpeg2dec->decoder, 1); + + if (!gst_mpeg2dec_alloc_buffer (mpeg2dec, mpeg2dec->offset)) return FALSE; mpeg2dec->need_sequence = FALSE; return TRUE; + +negotiate_failed: + { + GST_ELEMENT_ERROR (mpeg2dec, CORE, NEGOTIATION, (NULL), (NULL)); + return FALSE; + } } static gboolean @@ -701,6 +565,8 @@ handle_picture (GstMpeg2dec * mpeg2dec, const mpeg2_info_t * info) gboolean key_frame = FALSE; GstBuffer *outbuf; + GST_DEBUG_OBJECT (mpeg2dec, "handle picture"); + if (info->current_picture) { key_frame = (info->current_picture->flags & PIC_MASK_CODING_TYPE) == @@ -718,10 +584,7 @@ handle_picture (GstMpeg2dec * mpeg2dec, const mpeg2_info_t * info) if (mpeg2dec->discont_state == MPEG2DEC_DISC_NEW_PICTURE && key_frame) mpeg2dec->discont_state = MPEG2DEC_DISC_NEW_KEYFRAME; - if (!GST_PAD_IS_USABLE (mpeg2dec->srcpad)) - mpeg2_skip (mpeg2dec->decoder, 1); - else - mpeg2_skip (mpeg2dec->decoder, 0); + mpeg2_skip (mpeg2dec->decoder, 0); return TRUE; } @@ -743,13 +606,6 @@ handle_slice (GstMpeg2dec * mpeg2dec, const mpeg2_info_t * info) gboolean key_frame = FALSE; outbuf = GST_BUFFER (info->display_fbuf->id); - if (!check_buffer (mpeg2dec, outbuf)) { - GST_ELEMENT_ERROR (mpeg2dec, RESOURCE, FAILED, (NULL), - ("libmpeg2 reported invalid buffer %p", outbuf)); - return FALSE; - } - - gst_buffer_ref (outbuf); picture = info->display_picture; @@ -813,8 +669,7 @@ handle_slice (GstMpeg2dec * mpeg2dec, const mpeg2_info_t * info) if (picture->flags & PIC_FLAG_SKIP) { GST_DEBUG_OBJECT (mpeg2dec, "dropping buffer because of skip flag"); gst_buffer_unref (outbuf); - } else if (!GST_PAD_IS_USABLE (mpeg2dec->srcpad) - || gst_pad_get_negotiated_caps (mpeg2dec->srcpad) == NULL) { + } else if (gst_pad_get_negotiated_caps (mpeg2dec->srcpad) == NULL) { GST_DEBUG_OBJECT (mpeg2dec, "dropping buffer, pad not usable"); gst_buffer_unref (outbuf); } else if (mpeg2dec->discont_state != MPEG2DEC_DISC_NONE) { @@ -857,14 +712,7 @@ handle_slice (GstMpeg2dec * mpeg2dec, const mpeg2_info_t * info) } if (info->discard_fbuf && info->discard_fbuf->id) { - if (free_buffer (mpeg2dec, GST_BUFFER (info->discard_fbuf->id))) { - - GST_DEBUG_OBJECT (mpeg2dec, "Discarded buffer %p", - info->discard_fbuf->id); - } else { - GST_ELEMENT_ERROR (mpeg2dec, LIBRARY, TOO_LAZY, (NULL), - ("libmpeg2 reported invalid buffer %p", info->discard_fbuf->id)); - } + GST_DEBUG_OBJECT (mpeg2dec, "Discarded buffer %p", info->discard_fbuf->id); } return TRUE; } @@ -899,79 +747,10 @@ update_streaminfo (GstMpeg2dec * mpeg2dec) } #endif -static void -gst_mpeg2dec_flush_decoder (GstMpeg2dec * mpeg2dec) -{ - if (mpeg2dec->decoder) { - const mpeg2_info_t *info = mpeg2_info (mpeg2dec->decoder); - mpeg2_state_t state; - - /* - * iterate the decoder and free buffers - */ - do { - state = mpeg2_parse (mpeg2dec->decoder); - switch (state) { - case STATE_SEQUENCE: - if (!handle_sequence (mpeg2dec, info)) { - gst_mpeg2dec_close_decoder (mpeg2dec); - gst_mpeg2dec_open_decoder (mpeg2dec); - state = -1; - } - break; - case STATE_PICTURE: - if (!handle_picture (mpeg2dec, info)) { - gst_mpeg2dec_close_decoder (mpeg2dec); - gst_mpeg2dec_open_decoder (mpeg2dec); - state = -1; - break; - } - mpeg2_skip (mpeg2dec->decoder, 1); - break; - case STATE_END: -#if MPEG2_RELEASE >= MPEG2_VERSION (0, 4, 0) - case STATE_INVALID_END: -#endif - case STATE_SLICE: - if (info->discard_fbuf) { - if (free_buffer (mpeg2dec, GST_BUFFER (info->discard_fbuf->id))) { - GST_DEBUG_OBJECT (mpeg2dec, "Discarded buffer %p", - info->discard_fbuf->id); - } else { - GST_ELEMENT_ERROR (mpeg2dec, LIBRARY, TOO_LAZY, (NULL), - ("libmpeg2 reported invalid buffer %p, fbuf: %p", - info->discard_fbuf->id, info->discard_fbuf)); - } - } - break; - case STATE_INVALID: - GST_WARNING_OBJECT (mpeg2dec, "Decoding error"); - /* - * We need to close the decoder here, according to docs - */ - gst_mpeg2dec_close_decoder (mpeg2dec); - gst_mpeg2dec_open_decoder (mpeg2dec); - return; - default: - break; - } - } - while (state != STATE_BUFFER && state != -1); - -#if MPEG2_RELEASE >= MPEG2_VERSION(0,4,0) - GST_DEBUG_OBJECT (mpeg2dec, "resetting mpeg2 stream decoder"); - /* 0 starts at next picture, 1 at next sequence header */ - mpeg2_reset (mpeg2dec->decoder, 0); -#endif - - } -} - static GstFlowReturn gst_mpeg2dec_chain (GstPad * pad, GstBuffer * buf) { - /* 0.9 GstBuffer *buf = GST_BUFFER (_data); */ - GstMpeg2dec *mpeg2dec = GST_MPEG2DEC (GST_PAD_PARENT (pad)); + GstMpeg2dec *mpeg2dec; guint32 size; guint8 *data, *end; GstClockTime pts; @@ -979,73 +758,39 @@ gst_mpeg2dec_chain (GstPad * pad, GstBuffer * buf) mpeg2_state_t state; gboolean done = FALSE; - + mpeg2dec = GST_MPEG2DEC (GST_PAD_PARENT (pad)); size = GST_BUFFER_SIZE (buf); data = GST_BUFFER_DATA (buf); pts = GST_BUFFER_TIMESTAMP (buf); + GST_LOG_OBJECT (mpeg2dec, "received buffer, timestamp %" GST_TIME_FORMAT ", duration %" GST_TIME_FORMAT, GST_TIME_ARGS (GST_BUFFER_TIMESTAMP (buf)), GST_TIME_ARGS (GST_BUFFER_DURATION (buf))); - info = mpeg2_info (mpeg2dec->decoder); + info = mpeg2dec->info; end = data + size; - if (pts != GST_CLOCK_TIME_NONE) { - gint64 mpeg_pts = GST_TIME_TO_MPEG_TIME (pts); - - GST_DEBUG_OBJECT (mpeg2dec, - "have pts: %" G_GINT64_FORMAT " (%" GST_TIME_FORMAT ")", mpeg_pts, - GST_TIME_ARGS (MPEG_TIME_TO_GST_TIME (mpeg_pts))); - -#if MPEG2_RELEASE >= MPEG2_VERSION(0,4,0) - mpeg2_tag_picture (mpeg2dec->decoder, mpeg_pts & 0xffffffff, - mpeg_pts >> 32); -#else - mpeg2_pts (mpeg2dec->decoder, mpeg_pts); -#endif - - } else { - GST_LOG ("no pts"); - } - - GST_LOG_OBJECT (mpeg2dec, "calling mpeg2_buffer"); - mpeg2_buffer (mpeg2dec->decoder, data, end); - GST_LOG_OBJECT (mpeg2dec, "calling mpeg2_buffer done"); - mpeg2dec->offset = GST_BUFFER_OFFSET (buf); + while (!done) { GST_LOG_OBJECT (mpeg2dec, "calling parse"); state = mpeg2_parse (mpeg2dec->decoder); GST_DEBUG_OBJECT (mpeg2dec, "parse state %d", state); + switch (state) { case STATE_SEQUENCE: - if (!handle_sequence (mpeg2dec, info)) { - goto exit; - } - - if (mpeg2dec->pending_event) { - done = TRUE; -#if 0 - GST_EVENT_SEEK_FLAGS (mpeg2dec->pending_event) & GST_SEEK_FLAG_FLUSH; -#endif - - gst_mpeg2dec_src_event (mpeg2dec->srcpad, mpeg2dec->pending_event); - mpeg2dec->pending_event = NULL; - } + handle_sequence (mpeg2dec, info); break; case STATE_SEQUENCE_REPEATED: GST_DEBUG_OBJECT (mpeg2dec, "sequence repeated"); + break; case STATE_GOP: break; case STATE_PICTURE: - { - if (!handle_picture (mpeg2dec, info)) { - goto exit; - } + handle_picture (mpeg2dec, info); break; - } case STATE_SLICE_1ST: GST_LOG_OBJECT (mpeg2dec, "1st slice of frame encountered"); break; @@ -1059,25 +804,42 @@ gst_mpeg2dec_chain (GstPad * pad, GstBuffer * buf) case STATE_END: mpeg2dec->need_sequence = TRUE; case STATE_SLICE: - if (!handle_slice (mpeg2dec, info)) { - goto exit; - } - + handle_slice (mpeg2dec, info); break; case STATE_BUFFER: - case -1: - /* need more data */ - done = TRUE; + if (data == NULL) { + done = TRUE; + } else { + if (pts != GST_CLOCK_TIME_NONE) { + gint64 mpeg_pts = GST_TIME_TO_MPEG_TIME (pts); + + GST_DEBUG_OBJECT (mpeg2dec, + "have pts: %" G_GINT64_FORMAT " (%" GST_TIME_FORMAT ")", + mpeg_pts, GST_TIME_ARGS (MPEG_TIME_TO_GST_TIME (mpeg_pts))); + +#if MPEG2_RELEASE >= MPEG2_VERSION(0,4,0) + mpeg2_tag_picture (mpeg2dec->decoder, mpeg_pts & 0xffffffff, + mpeg_pts >> 32); +#else + mpeg2_pts (mpeg2dec->decoder, mpeg_pts); +#endif + } else { + GST_LOG ("no pts"); + } + + GST_LOG_OBJECT (mpeg2dec, "calling mpeg2_buffer"); + mpeg2_buffer (mpeg2dec->decoder, data, end); + GST_LOG_OBJECT (mpeg2dec, "calling mpeg2_buffer done"); + + data = NULL; + } break; /* error */ case STATE_INVALID: GST_WARNING_OBJECT (mpeg2dec, "Decoding error"); goto exit; - - break; default: GST_ERROR_OBJECT (mpeg2dec, "Unknown libmpeg2 state %d, FIXME", state); - break; } @@ -1086,13 +848,11 @@ gst_mpeg2dec_chain (GstPad * pad, GstBuffer * buf) */ #ifdef enable_user_data if (info->user_data_len > 0) { - if (GST_PAD_IS_USABLE (mpeg2dec->userdatapad)) { - GstBuffer *udbuf = gst_buffer_new_and_alloc (info->user_data_len); + GstBuffer *udbuf = gst_buffer_new_and_alloc (info->user_data_len); - memcpy (GST_BUFFER_DATA (udbuf), info->user_data, info->user_data_len); + memcpy (GST_BUFFER_DATA (udbuf), info->user_data, info->user_data_len); - gst_pad_push (mpeg2dec->userdatapad, GST_BUFFER (udbuf)); - } + gst_pad_push (mpeg2dec->userdatapad, udbuf); } #endif @@ -1101,12 +861,6 @@ gst_mpeg2dec_chain (GstPad * pad, GstBuffer * buf) return GST_FLOW_OK; exit: - /* - * Close and reopen the decoder, because - * something went pretty wrong - */ - gst_mpeg2dec_close_decoder (mpeg2dec); - gst_mpeg2dec_open_decoder (mpeg2dec); gst_buffer_unref (buf); return GST_FLOW_ERROR; } @@ -1121,45 +875,8 @@ gst_mpeg2dec_sink_event (GstPad * pad, GstEvent * event) switch (GST_EVENT_TYPE (event)) { case GST_EVENT_NEWSEGMENT: { -#if 0 - gint64 time; - gint64 end_time; /* 0.9 just to call - gst_event_discont_get_value, non - used anywhere else */ -#endif - GST_STREAM_LOCK (pad); - -#if 0 - if (!gst_event_discont_get_value (event, GST_FORMAT_TIME, &time, - &end_time) - || !GST_CLOCK_TIME_IS_VALID (time)) { - GST_WARNING_OBJECT (mpeg2dec, - "No new time offset in discont event %p", event); - } else { - mpeg2dec->next_time = time; - GST_DEBUG_OBJECT (mpeg2dec, - "discont, reset next_time to %" G_GUINT64_FORMAT " (%" - GST_TIME_FORMAT ")", mpeg2dec->next_time, - GST_TIME_ARGS (mpeg2dec->next_time)); - } -#endif - - // what's hell is that - /* - if (GST_EVENT_DISCONT_NEW_MEDIA (event)) - { - gst_mpeg2dec_reset (mpeg2dec); - } - else - { - mpeg2dec->discont_state = MPEG2DEC_DISC_NEW_PICTURE; - gst_mpeg2dec_flush_decoder (mpeg2dec); - } - */ - mpeg2dec->next_time = -1;; - ret = gst_pad_event_default (pad, event); GST_STREAM_UNLOCK (pad); break; @@ -1170,7 +887,8 @@ gst_mpeg2dec_sink_event (GstPad * pad, GstEvent * event) case GST_EVENT_FLUSH_STOP: GST_STREAM_LOCK (pad); mpeg2dec->discont_state = MPEG2DEC_DISC_NEW_PICTURE; - gst_mpeg2dec_flush_decoder (mpeg2dec); + mpeg2dec->next_time = -1;; + mpeg2_reset (mpeg2dec->decoder, 0); ret = gst_pad_event_default (pad, event); GST_STREAM_UNLOCK (pad); break; @@ -1194,29 +912,6 @@ gst_mpeg2dec_sink_event (GstPad * pad, GstEvent * event) } - - -#if 0 -static const GstFormat * -gst_mpeg2dec_get_formats (GstPad * pad) -{ - static GstFormat src_formats[] = { - GST_FORMAT_BYTES, - GST_FORMAT_TIME, - GST_FORMAT_DEFAULT, - 0 - }; - static GstFormat sink_formats[] = { - GST_FORMAT_BYTES, - GST_FORMAT_TIME, - 0 - }; - - return (GST_PAD_IS_SRC (pad) ? src_formats : sink_formats); -} -#endif - - static GstCaps * gst_mpeg2dec_src_getcaps (GstPad * pad) { @@ -1372,13 +1067,9 @@ gst_mpeg2dec_src_query (GstPad * pad, GstQuery * query) gst_query_parse_position (query, &format, NULL); /* and convert to the requested format */ - if (format != GST_FORMAT_DEFAULT) { - if (!gst_mpeg2dec_src_convert (pad, GST_FORMAT_DEFAULT, - mpeg2dec->next_time, &format, &cur)) - goto error; - } else { - cur = mpeg2dec->next_time; - } + if (!gst_mpeg2dec_src_convert (pad, GST_FORMAT_TIME, + mpeg2dec->next_time, &format, &cur)) + goto error; gst_query_set_position (query, format, cur); @@ -1393,41 +1084,39 @@ gst_mpeg2dec_src_query (GstPad * pad, GstQuery * query) gint64 total, total_bytes; GstPad *peer; + if ((peer = gst_pad_get_peer (mpeg2dec->sinkpad)) == NULL) + goto error; + + /* send to peer */ + if ((res = gst_pad_query (peer, query))) { + gst_object_unref (peer); + goto done; + } else { + GST_LOG_OBJECT (mpeg2dec, "query on peer pad failed, trying bytes"); + } + /* save requested format */ gst_query_parse_duration (query, &format, NULL); /* query peer for total length in bytes */ gst_query_set_duration (query, GST_FORMAT_BYTES, -1); - if ((peer = gst_pad_get_peer (mpeg2dec->sinkpad)) == NULL) - goto error; - - if (!gst_pad_query (peer, query)) { + if (!(res = gst_pad_query (peer, query))) { GST_LOG_OBJECT (mpeg2dec, "query on peer pad failed"); + gst_object_unref (peer); goto error; } gst_object_unref (peer); /* get the returned format */ gst_query_parse_duration (query, &rformat, &total_bytes); - if (rformat == GST_FORMAT_BYTES) - GST_LOG_OBJECT (mpeg2dec, "peer pad returned total=%lld bytes", - total_bytes); - else if (rformat == GST_FORMAT_TIME) - GST_LOG_OBJECT (mpeg2dec, "peer pad returned time=%lld", total_bytes); - - /* Check if requested format is returned format */ - if (format == rformat) - return TRUE; + GST_LOG_OBJECT (mpeg2dec, "peer pad returned total=%lld bytes", + total_bytes); if (total_bytes != -1) { - if (format != GST_FORMAT_BYTES) { - if (!gst_mpeg2dec_sink_convert (pad, GST_FORMAT_BYTES, total_bytes, - &format, &total)) - goto error; - } else { - total = total_bytes; - } + if (!gst_mpeg2dec_sink_convert (pad, GST_FORMAT_BYTES, total_bytes, + &format, &total)) + goto error; } else { total = -1; } @@ -1442,6 +1131,7 @@ gst_mpeg2dec_src_query (GstPad * pad, GstQuery * query) res = FALSE; break; } +done: return res; error: @@ -1597,44 +1287,6 @@ normal_seek (GstPad * pad, GstEvent * event) /* do the seek */ res = gst_pad_push_event (mpeg2dec->sinkpad, seek_event); } -#if 0 - - /* get our peer formats */ - if (GST_PAD_PEER (mpeg2dec->sinkpad)) - peer_formats = gst_pad_get_formats (GST_PAD_PEER (mpeg2dec->sinkpad)); - - /* while we did not exhaust our seek formats without result */ - while (peer_formats && *peer_formats) { - gint64 desired_offset; - - format = *peer_formats; - - /* try to convert requested format to one we can seek with on the sinkpad */ - if (gst_mpeg2dec_sink_convert (mpeg2dec->sinkpad, GST_FORMAT_TIME, - src_offset, &format, &desired_offset)) { - GstEvent *seek_event; - - /* conversion succeeded, create the seek */ - seek_event = - gst_event_new_seek (format | GST_SEEK_METHOD_SET | flush, - desired_offset); - /* do the seekk */ - if (gst_pad_send_event (GST_PAD_PEER (mpeg2dec->sinkpad), seek_event)) { - /* seek worked, we're done, loop will exit */ - res = TRUE; - break; - } - } - peer_formats++; - } - /* at this point, either the seek worked and res = TRUE or res == FALSE and the seek - * failed */ - if (res && flush) { - /* if we need to flush, iterate until the buffer is empty */ - gst_mpeg2dec_flush_decoder (mpeg2dec); - } -#endif - return res; /* ERRORS */ @@ -1650,7 +1302,7 @@ convert_failed: static gboolean gst_mpeg2dec_src_event (GstPad * pad, GstEvent * event) { - gboolean res = TRUE; + gboolean res; GstMpeg2dec *mpeg2dec; mpeg2dec = GST_MPEG2DEC (GST_PAD_PARENT (pad)); @@ -1661,27 +1313,19 @@ gst_mpeg2dec_src_event (GstPad * pad, GstEvent * event) switch (GST_EVENT_TYPE (event)) { /* the all-formats seek logic */ case GST_EVENT_SEEK: - if (mpeg2dec->need_sequence) { - mpeg2dec->pending_event = event; - return TRUE; - } else { - if (mpeg2dec->index) - res = index_seek (pad, event); - else - res = normal_seek (pad, event); + if (mpeg2dec->index) + res = index_seek (pad, event); + else + res = normal_seek (pad, event); - if (res) - mpeg2dec->discont_state = MPEG2DEC_DISC_NEW_PICTURE; - } + gst_event_unref (event); break; case GST_EVENT_NAVIGATION: /* Forward a navigation event unchanged */ - return gst_pad_push_event (mpeg2dec->sinkpad, event); default: - res = FALSE; + res = gst_pad_push_event (mpeg2dec->sinkpad, event); break; } - gst_event_unref (event); return res; } @@ -1693,9 +1337,12 @@ gst_mpeg2dec_change_state (GstElement * element, GstStateChange transition) switch (transition) { case GST_STATE_CHANGE_NULL_TO_READY: + mpeg2_accel (MPEG2_ACCEL_DETECT); + if ((mpeg2dec->decoder = mpeg2_init ()) == NULL) + goto init_failed; + mpeg2dec->info = mpeg2_info (mpeg2dec->decoder); break; case GST_STATE_CHANGE_READY_TO_PAUSED: - mpeg2dec->next_time = 0; gst_mpeg2dec_reset (mpeg2dec); break; case GST_STATE_CHANGE_PAUSED_TO_PLAYING: @@ -1709,14 +1356,26 @@ gst_mpeg2dec_change_state (GstElement * element, GstStateChange transition) case GST_STATE_CHANGE_PLAYING_TO_PAUSED: break; case GST_STATE_CHANGE_PAUSED_TO_READY: - gst_mpeg2dec_close_decoder (mpeg2dec); break; case GST_STATE_CHANGE_READY_TO_NULL: + if (mpeg2dec->decoder) { + mpeg2_close (mpeg2dec->decoder); + mpeg2dec->decoder = NULL; + mpeg2dec->info = NULL; + } break; default: break; } return ret; + + /* ERRORS */ +init_failed: + { + GST_ELEMENT_ERROR (mpeg2dec, LIBRARY, INIT, + (NULL), ("Failed to initialize libmpeg2 library")); + return GST_STATE_CHANGE_FAILURE; + } } static void diff --git a/ext/mpeg2dec/gstmpeg2dec.h b/ext/mpeg2dec/gstmpeg2dec.h index 14434d7484..7d8c7ba881 100644 --- a/ext/mpeg2dec/gstmpeg2dec.h +++ b/ext/mpeg2dec/gstmpeg2dec.h @@ -70,6 +70,8 @@ struct _GstMpeg2dec { *userdatapad; mpeg2dec_t *decoder; + const mpeg2_info_t *info; + gboolean closed; gboolean have_fbuf;