CVSROOT: /sources/gnash Module name: gnash Changes by: Bastiaan Jacques <bjacques> 08/01/29 05:18:34
Modified files: . : ChangeLog libmedia/gst : VideoDecoderGst.cpp VideoDecoderGst.h gstappsink.c gstappsink.h server/parser : video_stream_def.cpp Log message: * libmedia/gst/VideoDecoderGst.{cpp,h}: Tell the decoder about the expected video width and height. Check for error conditions more frequently. * libmedia/gst/gstappsink.{c,h}: Add gst_app_sink_pull_buffer_timed(), which waits up to one second before returning if the expected buffer does not make its way to the output queue. * server/parser/video_stream_def.cpp: Make sure the decoder parses intermedia frames if certain frames are skipped. Don't assume that frame 0 is a "spin-up" frame. Fixes Video-EmbedSquareTest. CVSWeb URLs: http://cvs.savannah.gnu.org/viewcvs/gnash/ChangeLog?cvsroot=gnash&r1=1.5513&r2=1.5514 http://cvs.savannah.gnu.org/viewcvs/gnash/libmedia/gst/VideoDecoderGst.cpp?cvsroot=gnash&r1=1.10&r2=1.11 http://cvs.savannah.gnu.org/viewcvs/gnash/libmedia/gst/VideoDecoderGst.h?cvsroot=gnash&r1=1.12&r2=1.13 http://cvs.savannah.gnu.org/viewcvs/gnash/libmedia/gst/gstappsink.c?cvsroot=gnash&r1=1.5&r2=1.6 http://cvs.savannah.gnu.org/viewcvs/gnash/libmedia/gst/gstappsink.h?cvsroot=gnash&r1=1.4&r2=1.5 http://cvs.savannah.gnu.org/viewcvs/gnash/server/parser/video_stream_def.cpp?cvsroot=gnash&r1=1.35&r2=1.36 Patches: Index: ChangeLog =================================================================== RCS file: /sources/gnash/gnash/ChangeLog,v retrieving revision 1.5513 retrieving revision 1.5514 diff -u -b -r1.5513 -r1.5514 --- ChangeLog 28 Jan 2008 20:36:28 -0000 1.5513 +++ ChangeLog 29 Jan 2008 05:18:32 -0000 1.5514 @@ -1,3 +1,16 @@ +2008-01-28 Bastiaan Jacques <[EMAIL PROTECTED]> + + * libmedia/gst/VideoDecoderGst.{cpp,h}: Tell the decoder about the + expected video width and height. Check for error conditions more + frequently. + * libmedia/gst/gstappsink.{c,h}: Add + gst_app_sink_pull_buffer_timed(), which waits up to one second + before returning if the expected buffer does not make its way + to the output queue. + * server/parser/video_stream_def.cpp: Make sure the decoder parses + intermedia frames if certain frames are skipped. Don't assume that + frame 0 is a "spin-up" frame. Fixes Video-EmbedSquareTest. + 2008-01-28 Sandro Santilli <[EMAIL PROTECTED]> * server/swf/tag_loaders.cpp (button_sound_loader): robustness Index: libmedia/gst/VideoDecoderGst.cpp =================================================================== RCS file: /sources/gnash/gnash/libmedia/gst/VideoDecoderGst.cpp,v retrieving revision 1.10 retrieving revision 1.11 diff -u -b -r1.10 -r1.11 --- libmedia/gst/VideoDecoderGst.cpp 27 Jan 2008 07:18:18 -0000 1.10 +++ libmedia/gst/VideoDecoderGst.cpp 29 Jan 2008 05:18:33 -0000 1.11 @@ -16,7 +16,7 @@ // along with this program; if not, write to the Free Software // Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA -// $Id: VideoDecoderGst.cpp,v 1.10 2008/01/27 07:18:18 bjacques Exp $ +// $Id: VideoDecoderGst.cpp,v 1.11 2008/01/29 05:18:33 bjacques Exp $ #ifdef HAVE_CONFIG_H #include "gnashconfig.h" @@ -34,10 +34,9 @@ // TODO: implement proper seeking. -VideoDecoderGst::VideoDecoderGst(videoCodecType codec_type) +VideoDecoderGst::VideoDecoderGst(videoCodecType codec_type, int width, int height) : _appsink(NULL), _colorspace(NULL) - { gst_init (NULL, NULL); @@ -46,22 +45,31 @@ _appsrc = gst_element_factory_make ("appsrc", NULL); GstElement* decoder = NULL; - GstCaps* caps = NULL; + GstCaps* caps; switch (codec_type) { case VIDEO_CODEC_H263: decoder = gst_element_factory_make ("ffdec_flv", NULL); - caps = gst_caps_new_simple ("video/x-flash-video", NULL); + caps = gst_caps_new_simple ("video/x-flash-video", + "width", G_TYPE_INT, width, + "height", G_TYPE_INT, height, + NULL); break; case VIDEO_CODEC_VP6: case VIDEO_CODEC_VP6A: decoder = gst_element_factory_make ("ffdec_vp6f", NULL); - caps = gst_caps_new_simple ("video/x-vp6-flash", NULL); + caps = gst_caps_new_simple ("video/x-vp6-flash", + "width", G_TYPE_INT, width, + "height", G_TYPE_INT, height, + NULL); break; case VIDEO_CODEC_SCREENVIDEO: case VIDEO_CODEC_SCREENVIDEO2: - decoder = gst_element_factory_make ("ffdec_flashsv", NULL); - caps = gst_caps_new_simple ("video/x-flash-screen", NULL); + decoder = gst_element_factory_make ("ffdec_flv", NULL); + caps = gst_caps_new_simple ("video/x-flash-screen", + "width", G_TYPE_INT, width, + "height", G_TYPE_INT, height, + NULL); break; default: log_error("No support for this video codec. %d", codec_type); @@ -73,7 +81,6 @@ if (!decoder) { log_error(_("failed to initialize the video decoder. Bailing out.")); gst_object_unref (GST_OBJECT (_pipeline)); - gst_caps_unref(caps); _pipeline = NULL; return; } @@ -117,6 +124,8 @@ return; } gst_app_src_push_buffer (GST_APP_SRC(_appsrc), buffer); + + checkMessages(); } @@ -129,7 +138,12 @@ checkMessages(); - GstBuffer* buffer = gst_app_sink_pull_buffer (GST_APP_SINK(_appsink)); + GstBuffer* buffer = gst_app_sink_pull_buffer_timed (GST_APP_SINK(_appsink)); + + if (!buffer) { + return std::auto_ptr<gnashGstBuffer>(); + } + GstCaps* caps = gst_buffer_get_caps(buffer); assert(gst_caps_get_size(caps) == 1); Index: libmedia/gst/VideoDecoderGst.h =================================================================== RCS file: /sources/gnash/gnash/libmedia/gst/VideoDecoderGst.h,v retrieving revision 1.12 retrieving revision 1.13 diff -u -b -r1.12 -r1.13 --- libmedia/gst/VideoDecoderGst.h 27 Jan 2008 07:18:18 -0000 1.12 +++ libmedia/gst/VideoDecoderGst.h 29 Jan 2008 05:18:33 -0000 1.13 @@ -16,7 +16,7 @@ // along with this program; if not, write to the Free Software // Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA -// $Id: VideoDecoderGst.h,v 1.12 2008/01/27 07:18:18 bjacques Exp $ +// $Id: VideoDecoderGst.h,v 1.13 2008/01/29 05:18:33 bjacques Exp $ #ifndef __VIDEODECODERGST_H__ #define __VIDEODECODERGST_H__ @@ -68,7 +68,7 @@ { public: - VideoDecoderGst(videoCodecType codec_type); + VideoDecoderGst(videoCodecType codec_type, int width, int height); ~VideoDecoderGst(); void pushRawFrame(GstBuffer* buffer); Index: libmedia/gst/gstappsink.c =================================================================== RCS file: /sources/gnash/gnash/libmedia/gst/gstappsink.c,v retrieving revision 1.5 retrieving revision 1.6 diff -u -b -r1.5 -r1.6 --- libmedia/gst/gstappsink.c 27 Jan 2008 07:18:18 -0000 1.5 +++ libmedia/gst/gstappsink.c 29 Jan 2008 05:18:33 -0000 1.6 @@ -17,7 +17,7 @@ * Boston, MA 02111-1307, USA. */ -/* $Id: gstappsink.c,v 1.5 2008/01/27 07:18:18 bjacques Exp $ */ +/* $Id: gstappsink.c,v 1.6 2008/01/29 05:18:33 bjacques Exp $ */ #ifdef HAVE_CONFIG_H #include "gnashconfig.h" @@ -669,6 +669,85 @@ /** + * gst_app_sink_pull_buffer_timed: + * @appsink: a #GstAppSink + * + * This function blocks until a buffer or EOS becomes available or the appsink + * element is set to the READY/NULL state, or if one second elapses. + * + * This function will only return buffers when the appsink is in the PLAYING + * state. All rendered buffers will be put in a queue so that the application + * can pull buffers at its own rate. + * + * If an EOS event was received before any buffers, or if one second passes and + * no data arrives, this function returns * %NULL. Use gst_app_sink_is_eos () + * to check for the EOS condition. + * + * Returns: a #GstBuffer or NULL when the appsink is stopped or EOS, or one + * second elapses. + */ +GstBuffer * +gst_app_sink_pull_buffer_timed (GstAppSink * appsink) +{ + GstBuffer *buf = NULL; + + g_return_val_if_fail (appsink != NULL, NULL); + g_return_val_if_fail (GST_IS_APP_SINK (appsink), NULL); + + g_mutex_lock (appsink->mutex); + + while (TRUE) { + GST_DEBUG_OBJECT (appsink, "trying to grab a buffer"); + if (!appsink->started) + goto not_started; + + if (!g_queue_is_empty (appsink->queue)) + break; + + if (appsink->is_eos) + goto eos; + + /* nothing to return, wait */ + GST_DEBUG_OBJECT (appsink, "waiting for a buffer"); + + GTimeVal cur_time; + g_get_current_time(&cur_time); + cur_time.tv_sec++; // Add one second + + if (!g_cond_timed_wait(appsink->cond, appsink->mutex, &cur_time)) + goto timeout; + + } + buf = g_queue_pop_head (appsink->queue); + GST_DEBUG_OBJECT (appsink, "we have a buffer %p", buf); + g_mutex_unlock (appsink->mutex); + + return buf; + + /* special conditions */ +timeout: + { + GST_DEBUG_OBJECT (appsink, "we timed out, return NULL"); + g_mutex_unlock (appsink->mutex); + return NULL; + } +eos: + { + GST_DEBUG_OBJECT (appsink, "we are EOS, return NULL"); + g_mutex_unlock (appsink->mutex); + return NULL; + } +not_started: + { + GST_DEBUG_OBJECT (appsink, "we are stopped, return NULL"); + g_mutex_unlock (appsink->mutex); + return NULL; + } +} + + + +/** * gst_app_sink_peek_buffer: * @appsink: a #GstAppSink * Index: libmedia/gst/gstappsink.h =================================================================== RCS file: /sources/gnash/gnash/libmedia/gst/gstappsink.h,v retrieving revision 1.4 retrieving revision 1.5 diff -u -b -r1.4 -r1.5 --- libmedia/gst/gstappsink.h 27 Jan 2008 07:18:18 -0000 1.4 +++ libmedia/gst/gstappsink.h 29 Jan 2008 05:18:33 -0000 1.5 @@ -17,7 +17,7 @@ * Boston, MA 02111-1307, USA. */ -/* $Id: gstappsink.h,v 1.4 2008/01/27 07:18:18 bjacques Exp $ */ +/* $Id: gstappsink.h,v 1.5 2008/01/29 05:18:33 bjacques Exp $ */ #ifndef _GST_APP_SINK_H_ #define _GST_APP_SINK_H_ @@ -82,6 +82,7 @@ GstBuffer * gst_app_sink_pull_preroll (GstAppSink *appsink); GstBuffer * gst_app_sink_pull_buffer (GstAppSink *appsink); gboolean gst_app_sink_peek_buffer (GstAppSink *appsink); +GstBuffer * gst_app_sink_pull_buffer_timed (GstAppSink * appsink); G_END_DECLS Index: server/parser/video_stream_def.cpp =================================================================== RCS file: /sources/gnash/gnash/server/parser/video_stream_def.cpp,v retrieving revision 1.35 retrieving revision 1.36 diff -u -b -r1.35 -r1.36 --- server/parser/video_stream_def.cpp 28 Jan 2008 17:20:03 -0000 1.35 +++ server/parser/video_stream_def.cpp 29 Jan 2008 05:18:33 -0000 1.36 @@ -16,7 +16,7 @@ // Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA // -// $Id: video_stream_def.cpp,v 1.35 2008/01/28 17:20:03 bjacques Exp $ +// $Id: video_stream_def.cpp,v 1.36 2008/01/29 05:18:33 bjacques Exp $ #include "video_stream_def.h" #include "video_stream_instance.h" @@ -79,7 +79,7 @@ m_codec_id = static_cast<media::videoCodecType>(in->read_u8()); - _decoder.reset( new media::VideoDecoderGst(m_codec_id) ); + _decoder.reset( new media::VideoDecoderGst(m_codec_id, _width, _height) ); } @@ -104,6 +104,7 @@ GstBuffer* buffer = gst_buffer_new_and_alloc(dataSize+8); memset(GST_BUFFER_DATA(buffer)+dataSize, 0, 8); + GST_BUFFER_SIZE (buffer) = dataSize; if (!buffer) { log_error(_("Failed to allocate a buffer of size %d advertised by SWF."), @@ -112,16 +113,12 @@ } GST_BUFFER_OFFSET(buffer) = frameNum; + GST_BUFFER_TIMESTAMP(buffer) = GST_CLOCK_TIME_NONE; + GST_BUFFER_DURATION(buffer) = GST_CLOCK_TIME_NONE; in->read((char*)GST_BUFFER_DATA(buffer), dataSize); _video_frames.push_back(buffer); - - if (frameNum == 0) { - gst_buffer_ref(buffer); // make sure gstreamer doesn't delete the buffer. - - _decoder->pushRawFrame(buffer); - } } @@ -143,18 +140,49 @@ { // Check if the requested frame holds any video data. EmbedFrameVec::iterator it = std::find_if(_video_frames.begin(), - _video_frames.end(), boost::bind(has_frame_number, _1, frameNum+1)); + _video_frames.end(), boost::bind(has_frame_number, _1, frameNum)); - if( it == _video_frames.end() ) - { + // FIXME: although we return nothing here, we should return the + // previously decoded frame. + if( it == _video_frames.end() ) { return std::auto_ptr<image::image_base>(); } - gst_buffer_ref(*it); // make sure gstreamer doesn't delete the buffer. + // We are going backwards, so start from the beginning. + if (_last_decoded_frame > boost::int32_t(frameNum)) { + _last_decoded_frame = -1; + } + + // Push all the frames after the previously decoded frame, until the + // target frame has been reached. + while (_last_decoded_frame != boost::int32_t(frameNum)) { + it = std::find_if(_video_frames.begin(), + _video_frames.end(), boost::bind(has_frame_number, _1, + _last_decoded_frame)); + + if (it == _video_frames.end()) { + it = _video_frames.begin(); + } else { + ++it; + } + if (it == _video_frames.end()) { + return std::auto_ptr<image::image_base>(); + } + + gst_buffer_ref(*it); // make sure gstreamer doesn't delete the buffer. + _last_decoded_frame = GST_BUFFER_OFFSET(*it); _decoder->pushRawFrame(*it); + } + + std::auto_ptr<media::gnashGstBuffer> buffer = _decoder->popDecodedFrame(); + + // If more data has arrived, replace the buffer with the next frame. + while (_decoder->peek()) { + buffer = _decoder->popDecodedFrame(); + } - return std::auto_ptr<image::image_base>(_decoder->popDecodedFrame()); + return std::auto_ptr<image::image_base>(buffer.release()); } _______________________________________________ Gnash-commit mailing list Gnash-commit@gnu.org http://lists.gnu.org/mailman/listinfo/gnash-commit