From: <th...@ke...> - 2008-06-17 01:08:20
|
CVS Root: /cvs/gstreamer Module: gst-plugins-bad Changes by: thaytan Date: Tue Jun 17 2008 01:08:28 UTC Log message: * configure.ac: Check for libdvdnav to build resindvd. * ext/Makefile.am: * ext/resindvd/Makefile.am: * ext/resindvd/gstmpegdefs.h: * ext/resindvd/gstmpegdemux.c: * ext/resindvd/gstmpegdemux.h: * ext/resindvd/gstmpegdesc.c: * ext/resindvd/gstmpegdesc.h: * ext/resindvd/gstpesfilter.c: * ext/resindvd/gstpesfilter.h: * ext/resindvd/plugin.c: * ext/resindvd/resin-play: * ext/resindvd/resindvdbin.c: * ext/resindvd/resindvdbin.h: * ext/resindvd/resindvdsrc.c: * ext/resindvd/resindvdsrc.h: * ext/resindvd/rsnaudiomunge.c: * ext/resindvd/rsnaudiomunge.h: * ext/resindvd/rsnbasesrc.c: * ext/resindvd/rsnbasesrc.h: * ext/resindvd/rsnpushsrc.c: * ext/resindvd/rsnpushsrc.h: * ext/resindvd/rsnstreamselector.c: * ext/resindvd/rsnstreamselector.h: First commit of DVD-Video playback component 'rsndvdbin' and helper elements. Use --enable-experimental for now, but feel free to give it a try using the resin-play script. * gst/dvdspu/gstdvdspu.c: Add some extra guards for malformed events. Modified files: . : ChangeLog configure.ac ext : Makefile.am gst/dvdspu : gstdvdspu.c Added files: ext/resindvd : Makefile.am gstmpegdefs.h gstmpegdemux.c gstmpegdemux.h gstmpegdesc.c gstmpegdesc.h gstpesfilter.c gstpesfilter.h plugin.c resin-play resindvdbin.c resindvdbin.h resindvdsrc.c resindvdsrc.h rsnaudiomunge.c rsnaudiomunge.h rsnbasesrc.c rsnbasesrc.h rsnpushsrc.c rsnpushsrc.h rsnstreamselector.c rsnstreamselector.h Links: http://freedesktop.org/cgi-bin/viewcvs.cgi/gstreamer/gst-plugins-bad/ChangeLog.diff?r1=1.3382&r2=1.3383 http://freedesktop.org/cgi-bin/viewcvs.cgi/gstreamer/gst-plugins-bad/configure.ac.diff?r1=1.859&r2=1.860 http://freedesktop.org/cgi-bin/viewcvs.cgi/gstreamer/gst-plugins-bad/ext/Makefile.am.diff?r1=1.207&r2=1.208 http://freedesktop.org/cgi-bin/viewcvs.cgi/gstreamer/gst-plugins-bad/ext/resindvd/Makefile.am?rev=1.1&content-type=text/vnd.viewcvs-markup http://freedesktop.org/cgi-bin/viewcvs.cgi/gstreamer/gst-plugins-bad/ext/resindvd/gstmpegdefs.h?rev=1.1&content-type=text/vnd.viewcvs-markup http://freedesktop.org/cgi-bin/viewcvs.cgi/gstreamer/gst-plugins-bad/ext/resindvd/gstmpegdemux.c?rev=1.1&content-type=text/vnd.viewcvs-markup http://freedesktop.org/cgi-bin/viewcvs.cgi/gstreamer/gst-plugins-bad/ext/resindvd/gstmpegdemux.h?rev=1.1&content-type=text/vnd.viewcvs-markup http://freedesktop.org/cgi-bin/viewcvs.cgi/gstreamer/gst-plugins-bad/ext/resindvd/gstmpegdesc.c?rev=1.1&content-type=text/vnd.viewcvs-markup http://freedesktop.org/cgi-bin/viewcvs.cgi/gstreamer/gst-plugins-bad/ext/resindvd/gstmpegdesc.h?rev=1.1&content-type=text/vnd.viewcvs-markup http://freedesktop.org/cgi-bin/viewcvs.cgi/gstreamer/gst-plugins-bad/ext/resindvd/gstpesfilter.c?rev=1.1&content-type=text/vnd.viewcvs-markup http://freedesktop.org/cgi-bin/viewcvs.cgi/gstreamer/gst-plugins-bad/ext/resindvd/gstpesfilter.h?rev=1.1&content-type=text/vnd.viewcvs-markup http://freedesktop.org/cgi-bin/viewcvs.cgi/gstreamer/gst-plugins-bad/ext/resindvd/plugin.c?rev=1.1&content-type=text/vnd.viewcvs-markup http://freedesktop.org/cgi-bin/viewcvs.cgi/gstreamer/gst-plugins-bad/ext/resindvd/resin-play?rev=1.1&content-type=text/vnd.viewcvs-markup http://freedesktop.org/cgi-bin/viewcvs.cgi/gstreamer/gst-plugins-bad/ext/resindvd/resindvdbin.c?rev=1.1&content-type=text/vnd.viewcvs-markup http://freedesktop.org/cgi-bin/viewcvs.cgi/gstreamer/gst-plugins-bad/ext/resindvd/resindvdbin.h?rev=1.1&content-type=text/vnd.viewcvs-markup http://freedesktop.org/cgi-bin/viewcvs.cgi/gstreamer/gst-plugins-bad/ext/resindvd/resindvdsrc.c?rev=1.1&content-type=text/vnd.viewcvs-markup http://freedesktop.org/cgi-bin/viewcvs.cgi/gstreamer/gst-plugins-bad/ext/resindvd/resindvdsrc.h?rev=1.1&content-type=text/vnd.viewcvs-markup http://freedesktop.org/cgi-bin/viewcvs.cgi/gstreamer/gst-plugins-bad/ext/resindvd/rsnaudiomunge.c?rev=1.1&content-type=text/vnd.viewcvs-markup http://freedesktop.org/cgi-bin/viewcvs.cgi/gstreamer/gst-plugins-bad/ext/resindvd/rsnaudiomunge.h?rev=1.1&content-type=text/vnd.viewcvs-markup http://freedesktop.org/cgi-bin/viewcvs.cgi/gstreamer/gst-plugins-bad/ext/resindvd/rsnbasesrc.c?rev=1.1&content-type=text/vnd.viewcvs-markup http://freedesktop.org/cgi-bin/viewcvs.cgi/gstreamer/gst-plugins-bad/ext/resindvd/rsnbasesrc.h?rev=1.1&content-type=text/vnd.viewcvs-markup http://freedesktop.org/cgi-bin/viewcvs.cgi/gstreamer/gst-plugins-bad/ext/resindvd/rsnpushsrc.c?rev=1.1&content-type=text/vnd.viewcvs-markup http://freedesktop.org/cgi-bin/viewcvs.cgi/gstreamer/gst-plugins-bad/ext/resindvd/rsnpushsrc.h?rev=1.1&content-type=text/vnd.viewcvs-markup http://freedesktop.org/cgi-bin/viewcvs.cgi/gstreamer/gst-plugins-bad/ext/resindvd/rsnstreamselector.c?rev=1.1&content-type=text/vnd.viewcvs-markup http://freedesktop.org/cgi-bin/viewcvs.cgi/gstreamer/gst-plugins-bad/ext/resindvd/rsnstreamselector.h?rev=1.1&content-type=text/vnd.viewcvs-markup http://freedesktop.org/cgi-bin/viewcvs.cgi/gstreamer/gst-plugins-bad/gst/dvdspu/gstdvdspu.c.diff?r1=1.7&r2=1.8 ====Begin Diffs==== Index: ChangeLog =================================================================== RCS file: /cvs/gstreamer/gst-plugins-bad/ChangeLog,v retrieving revision 1.3382 retrieving revision 1.3383 diff -u -d -r1.3382 -r1.3383 --- ChangeLog 17 Jun 2008 00:37:48 -0000 1.3382 +++ ChangeLog 17 Jun 2008 01:08:09 -0000 1.3383 @@ -1,3 +1,41 @@ +2008-06-17 Jan Schmidt <th...@no...> + + * configure.ac: + Check for libdvdnav to build resindvd. + * ext/Makefile.am: + * ext/resindvd/Makefile.am: + * ext/resindvd/gstmpegdefs.h: + * ext/resindvd/gstmpegdemux.c: + * ext/resindvd/gstmpegdemux.h: + * ext/resindvd/gstmpegdesc.c: + * ext/resindvd/gstmpegdesc.h: + * ext/resindvd/gstpesfilter.c: + * ext/resindvd/gstpesfilter.h: + * ext/resindvd/plugin.c: + * ext/resindvd/resin-play: + * ext/resindvd/resindvdbin.c: + * ext/resindvd/resindvdbin.h: + * ext/resindvd/resindvdsrc.c: + * ext/resindvd/resindvdsrc.h: + * ext/resindvd/rsnaudiomunge.c: + * ext/resindvd/rsnaudiomunge.h: + * ext/resindvd/rsnbasesrc.c: + * ext/resindvd/rsnbasesrc.h: + * ext/resindvd/rsnpushsrc.c: + * ext/resindvd/rsnpushsrc.h: + * ext/resindvd/rsnstreamselector.c: + * ext/resindvd/rsnstreamselector.h: + First commit of DVD-Video playback component 'rsndvdbin' + and helper elements. + Use --enable-experimental for now, but feel free to give it a + try using the resin-play script. + * gst/dvdspu/gstdvdspu.c: + Add some extra guards for malformed events. 2008-06-16 David Schleef <ds...@sc...> * configure.ac: Index: configure.ac RCS file: /cvs/gstreamer/gst-plugins-bad/configure.ac,v retrieving revision 1.859 retrieving revision 1.860 diff -u -d -r1.859 -r1.860 --- configure.ac 17 Jun 2008 00:37:49 -0000 1.859 +++ configure.ac 17 Jun 2008 01:08:10 -0000 1.860 @@ -477,6 +477,38 @@ fi ]) +dnl *** dvdnav for resindvd *** +USE_DVDNAV=$BUILD_EXPERIMENTAL +translit(dnm, m, l) AM_CONDITIONAL(USE_DVDNAV, true) +AG_GST_CHECK_FEATURE(DVDNAV, [dvdnav library], resindvd, [ + translit(dnm, m, l) AC_SUBST(DVDNAV_LIBS) + translit(dnm, m, l) AC_SUBST(DVDNAV_CFLAGS) + AG_GST_CHECK_CONFIGPROG(DVDNAV, dvdnav-config) + if test x"$HAVE_DVDNAV" = x"yes"; then + dnl check version + DVDNAV_VERSION=`dvdnav-config --version|head -n 1|sed 's/^.*) //'|sed 's/ (.*)//'` + DVDNAV_MAJOR=`echo $DVDNAV_VERSION | cut -d. -f1 | sed s/[a-zA-Z\-].*//g` + DVDNAV_MINOR=`echo $DVDNAV_VERSION | cut -d. -f2 | sed s/[a-zA-Z\-].*//g` + DVDNAV_MICRO=`echo $DVDNAV_VERSION | cut -d. -f3 | sed s/[a-zA-Z\-].*//g` + if [[ "$DVDNAV_MAJOR" -eq "0" ]] && \ + [[ "$DVDNAV_MINOR" -lt "1" ]]; then + AC_MSG_WARN([libdvdnav >= 0.1.7 is required, you have $DVDNAV_VERSION]) + HAVE_DVDNAV="no" + elif [[ "$DVDNAV_MAJOR" -eq "0" ]] && \ + [[ "$DVDNAV_MINOR" -eq "1" ]] && \ + [[ "$DVDNAV_MICRO" -lt "7" ]]; then + fi + fi + dnl now check for dvdread/nav_print.h - see #133002 + AC_CHECK_HEADER(dvdread/nav_print.h, , [ + AC_MSG_WARN([header dvdread/nav_print.h from dvdread missing]) + ]) + AS_SCRUB_INCLUDE(DVDNAV_CFLAGS) +]) dnl *** METADATA *** translit(dnm, m, l) AM_CONDITIONAL(USE_METADATA, true) AG_GST_CHECK_FEATURE(METADATA, [METADATA muxer and demuxer], metadata, [ @@ -1225,6 +1257,7 @@ ext/mythtv/Makefile ext/neon/Makefile ext/ofa/Makefile +ext/resindvd/Makefile ext/sdl/Makefile ext/sndfile/Makefile ext/soundtouch/Makefile Index: Makefile.am RCS file: /cvs/gstreamer/gst-plugins-bad/ext/Makefile.am,v retrieving revision 1.207 retrieving revision 1.208 diff -u -d -r1.207 -r1.208 --- Makefile.am 12 Apr 2008 23:32:10 -0000 1.207 +++ Makefile.am 17 Jun 2008 01:08:10 -0000 1.208 @@ -76,6 +76,12 @@ DTS_DIR= endif +if USE_DVDNAV + DVDNAV_DIR = resindvd +else + DVDNAV_DIR = +endif if USE_FAAC FAAC_DIR=faac else --- NEW FILE: Makefile.am --- # plugindir is set in configure plugin_LTLIBRARIES = libresindvd.la libresindvd_la_SOURCES = \ plugin.c \ resindvdbin.c \ rsnaudiomunge.c \ rsnbasesrc.c \ rsnpushsrc.c \ rsnstreamselector.c \ resindvdsrc.c \ gstmpegdesc.c \ gstmpegdemux.c \ gstpesfilter.c libresindvd_la_CFLAGS = $(GST_BASE_CFLAGS) $(GST_CFLAGS) $(DVDNAV_CFLAGS) libresindvd_la_LIBADD = $(GST_BASE_LIBS) $(GST_LIBS) $(DVDNAV_LIBS) libresindvd_la_LDFLAGS = $(GST_PLUGIN_LDFLAGS) noinst_HEADERS = resindvdbin.h \ rsnaudiomunge.h \ rsnbasesrc.h \ rsnpushsrc.h \ rsnstreamselector.h \ resindvdsrc.h \ gstmpegdefs.h \ gstmpegdesc.h \ gstmpegdemux.h \ gstpesfilter.h --- NEW FILE: gstmpegdefs.h --- /* * The contents of this file are subject to the Mozilla Public License * Version 1.1 (the "License"); you may not use this file except in * compliance with the License. You may obtain a copy of the License at * http://www.mozilla.org/MPL/. * * Software distributed under the License is distributed on an "AS IS" * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the * License for the specific language governing rights and limitations * under the License. * The Original Code is Fluendo MPEG Demuxer plugin. * The Initial Developer of the Original Code is Fluendo, S.L. * Portions created by Fluendo, S.L. are Copyright (C) 2005 * Fluendo, S.L. All Rights Reserved. * Contributor(s): Wim Taymans <wi...@fl...> * Jan Schmidt <th...@no...> */ #ifndef __GST_MPEG_DEFS_H__ #define __GST_MPEG_DEFS_H__ /* * 1011 1100 program_stream_map * 1011 1101 private_stream_1 * 1011 1110 padding_stream * 1011 1111 private_stream_2 * 110x xxxx ISO/IEC 13818-3 or ISO/IEC 11172-3 audio stream number x xxxx * 1110 xxxx ITU-T Rec. H.262 | ISO/IEC 13818-2 or ISO/IEC 11172-2 video stream number xxxx * 1111 0000 ECM_stream * 1111 0001 EMM_stream * 1111 0010 ITU-T Rec. H.222.0 | ISO/IEC 13818-1 Annex A or ISO/IEC 13818-6_DSMCC_stream * 1111 0011 ISO/IEC_13522_stream * 1111 0100 ITU-T Rec. H.222.1 type A * 1111 0101 ITU-T Rec. H.222.1 type B * 1111 0110 ITU-T Rec. H.222.1 type C * 1111 0111 ITU-T Rec. H.222.1 type D * 1111 1000 ITU-T Rec. H.222.1 type E * 1111 1001 ancillary_stream * 1111 1010 E 1111 1110 reserved data stream * 1111 1111 program_stream_directory #define ID_PS_END_CODE 0x000001B9 #define ID_PS_PACK_START_CODE 0x000001BA #define ID_PS_SYSTEM_HEADER_START_CODE 0x000001BB #define ID_PS_PROGRAM_STREAM_MAP 0x000001BC #define ID_PRIVATE_STREAM_1 0x000001BD #define ID_PADDING_STREAM 0x000001BE #define ID_PRIVATE_STREAM_2 0x000001BF #define ID_ISO_IEC_MPEG12_AUDIO_STREAM_0 0x000001C0 #define ID_ISO_IEC_MPEG12_AUDIO_STREAM_32 0x000001DF #define ID_ISO_IEC_MPEG12_VIDEO_STREAM_0 0x000001E0 #define ID_ISO_IEC_MPEG12_VIDEO_STREAM_16 0x000001EF #define ID_ECM_STREAM 0x000001F0 #define ID_EMM_STREAM 0x000001F1 #define ID_DSMCC_STREAM 0x000001F2 #define ID_ISO_IEC_13522_STREAM 0x000001F3 #define ID_ITU_TREC_H222_TYPE_A_STREAM 0x000001F4 #define ID_ITU_TREC_H222_TYPE_B_STREAM 0x000001F5 #define ID_ITU_TREC_H222_TYPE_C_STREAM 0x000001F6 #define ID_ITU_TREC_H222_TYPE_D_STREAM 0x000001F7 #define ID_ITU_TREC_H222_TYPE_E_STREAM 0x000001F8 #define ID_ANCILLARY_STREAM 0x000001F9 #define ID_RESERVED_STREAM_1 0x000001FA #define ID_RESERVED_STREAM_2 0x000001FB #define ID_EXTENDED_METADATA 0x000001FC #define ID_EXTENDED_STREAM_ID 0x000001FD #define ID_RESERVED_STREAM_3 0x000001FE #define ID_PROGRAM_STREAM_DIRECTORY 0x000001FF #define PACKET_VIDEO_START_CODE 0x000001E0 #define PACKET_AUDIO_START_CODE 0x000001C0 #define PICTURE_START_CODE 0x00000100 #define USER_DATA_START_CODE 0x000001B2 #define SEQUENCE_HEADER_CODE 0x000001B3 #define SEQUENCE_ERROR_CODE 0x000001B4 #define EXTENSION_START_CODE 0x000001B5 #define SEQUENCE_END_CODE 0x000001B7 #define GROUP_START_CODE 0x000001B8 #define AC3_SYNC_WORD 0x0b770000 #define MPEG_TS_SYNC_BYTE 0x00000047 #define PID_PROGRAM_ASSOCIATION_TABLE 0x0000 #define PID_CONDITIONAL_ACCESS_TABLE 0x0001 #define PID_RESERVED_FIRST 0x0002 #define PID_RESERVED_LAST 0x0010 #define PID_NULL_PACKET 0x1FFF #define PID_TYPE_UNKNOWN 0 #define PID_TYPE_RESERVED 1 #define PID_TYPE_PROGRAM_ASSOCIATION 2 #define PID_TYPE_CONDITIONAL_ACCESS 3 #define PID_TYPE_PROGRAM_MAP 4 #define PID_TYPE_ELEMENTARY 5 #define PID_TYPE_NULL_PACKET 6 #define PID_TYPE_PRIVATE_SECTION 7 /* Stream type assignments * * 0x00 ITU-T | ISO/IEC Reserved * 0x01 ISO/IEC 11172 Video * 0x02 ITU-T Rec. H.262 | ISO/IEC 13818-2 Video or * ISO/IEC 11172-2 constrained parameter video * stream * 0x03 ISO/IEC 11172 Audio * 0x04 ISO/IEC 13818-3 Audio * 0x05 ITU-T Rec. H.222.0 | ISO/IEC 13818-1 * private_sections * 0x06 ITU-T Rec. H.222.0 | ISO/IEC 13818-1 PES * packets containing private data * 0x07 ISO/IEC 13522 MHEG * 0x08 ITU-T Rec. H.222.0 | ISO/IEC 13818-1 Annex A * DSM CC * 0x09 ITU-T Rec. H.222.1 * 0x0A ISO/IEC 13818-6 type A * 0x0B ISO/IEC 13818-6 type B * 0x0C ISO/IEC 13818-6 type C * 0x0D ISO/IEC 13818-6 type D * 0x0E ISO/IEC 13818-1 auxiliary * 0x0F-0x7F ITU-T Rec. H.222.0 | ISO/IEC 13818-1 Reserved * 0x80-0xFF User Private #define ST_RESERVED 0x00 #define ST_VIDEO_MPEG1 0x01 #define ST_VIDEO_MPEG2 0x02 #define ST_AUDIO_MPEG1 0x03 #define ST_AUDIO_MPEG2 0x04 #define ST_PRIVATE_SECTIONS 0x05 #define ST_PRIVATE_DATA 0x06 #define ST_MHEG 0x07 #define ST_DSMCC 0x08 #define ST_H222_1 0x09 /* later extensions */ #define ST_AUDIO_AAC 0x0f #define ST_VIDEO_MPEG4 0x10 #define ST_VIDEO_H264 0x1b /* Un-official Dirac extension */ #define ST_VIDEO_DIRAC 0xd1 /* private stream types */ #define ST_PS_AUDIO_AC3 0x81 #define ST_PS_AUDIO_DTS 0x8a #define ST_PS_AUDIO_LPCM 0x8b #define ST_PS_DVD_SUBPICTURE 0xff /* Un-official time-code stream */ #define ST_PS_TIMECODE 0xd2 /* Internal stream types >= 0x100 */ #define ST_GST_AUDIO_RAWA52 0x181 /* Used when we don't yet know which stream type it will be in a PS stream */ #define ST_GST_VIDEO_MPEG1_OR_2 0x102 #define CLOCK_BASE 9LL #define CLOCK_FREQ (CLOCK_BASE * 10000) #define MPEGTIME_TO_GSTTIME(time) (gst_util_uint64_scale ((time), \ GST_MSECOND/10, CLOCK_BASE)) #define GSTTIME_TO_MPEGTIME(time) (gst_util_uint64_scale ((time), \ CLOCK_BASE, GST_MSECOND/10)) #define MPEG_MUX_RATE_MULT 50 /* some extra GstFlowReturn values used internally */ #define GST_FLOW_NEED_MORE_DATA -100 #define GST_FLOW_LOST_SYNC -101 #endif /* __GST_MPEG_DEFS_H__ */ --- NEW FILE: gstmpegdemux.c --- [...1904 lines suppressed...] demux->rev_adapter = NULL; break; default: } return result; } gboolean gst_flups_demux_plugin_init (GstPlugin * plugin) { GST_DEBUG_CATEGORY_INIT (gstflupesfilter_debug, "rsnpesfilter", 0, "MPEG program stream PES filter debug"); GST_DEBUG_CATEGORY_INIT (gstflupsdemux_debug, "rsndvddemux", 0, "MPEG program stream demuxer debug"); return TRUE; --- NEW FILE: gstmpegdemux.h --- #ifndef __GST_FLUPS_DEMUX_H__ #define __GST_FLUPS_DEMUX_H__ #include <gst/gst.h> #include <gst/base/gstadapter.h> #include "gstpesfilter.h" G_BEGIN_DECLS #define GST_TYPE_FLUPS_DEMUX (gst_flups_demux_get_type()) #define GST_FLUPS_DEMUX(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj),GST_TYPE_FLUPS_DEMUX,GstFluPSDemux)) #define GST_FLUPS_DEMUX_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass),GST_TYPE_FLUPS_DEMUX,GstFluPSDemuxClass)) #define GST_FLUPS_DEMUX_GET_CLASS(klass) (G_TYPE_INSTANCE_GET_CLASS((klass),GST_TYPE_FLUPS_DEMUX,GstFluPSDemuxClass)) #define GST_IS_FLUPS_DEMUX(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj),GST_TYPE_FLUPS_DEMUX)) #define GST_IS_FLUPS_DEMUX_CLASS(obj) (G_TYPE_CHECK_CLASS_TYPE((klass),GST_TYPE_FLUPS_DEMUX)) typedef struct _GstFluPSStream GstFluPSStream; typedef struct _GstFluPSDemux GstFluPSDemux; typedef struct _GstFluPSDemuxClass GstFluPSDemuxClass; #define GST_FLUPS_DEMUX_MAX_STREAMS 256 #define GST_FLUPS_DEMUX_MAX_PSM 256 typedef enum { STATE_FLUPS_DEMUX_NEED_SYNC, STATE_FLUPS_DEMUX_SYNCED, STATE_FLUPS_DEMUX_NEED_MORE_DATA, } GstFluPSDemuxState; /* Information associated with a single FluPS stream. */ struct _GstFluPSStream { GstPad * pad; gint id; gint type; gint size_bound; gboolean discont; gboolean notlinked; gboolean need_segment; GstClockTime last_ts; }; struct _GstFluPSDemux { GstElement parent; GstPad * sinkpad; GstAdapter * adapter; GstAdapter * rev_adapter; guint64 adapter_offset; guint32 last_sync_code; GstPESFilter filter; gint64 mux_rate; guint64 first_scr; guint64 first_dts; guint64 base_time; guint64 current_scr; guint64 next_scr; guint64 bytes_since_scr; gint64 scr_adjust; guint64 scr_rate_n; guint64 scr_rate_d; guint64 first_scr_offset; guint64 last_scr_offset; gint16 psm[GST_FLUPS_DEMUX_MAX_PSM]; GstSegment sink_segment; GstSegment src_segment; /* stream output */ GstFluPSStream * current_stream; guint64 next_pts; guint64 next_dts; GstFluPSStream ** streams; gboolean need_no_more_pads; /* Indicates an MPEG-2 stream */ gboolean is_mpeg2_pack; /* Language codes event is stored when a dvd-lang-codes * custom event arrives from upstream */ GstEvent * lang_codes; struct _GstFluPSDemuxClass { GstElementClass parent_class; GstPadTemplate *sink_template; GstPadTemplate *video_template; GstPadTemplate *audio_template; GstPadTemplate *private_template; GstPadTemplate *subpicture_template; GType gst_flups_demux_get_type (void); gboolean gst_flups_demux_plugin_init (GstPlugin *plugin); G_END_DECLS #endif /* __GST_FLUPS_DEMUX_H__ */ --- NEW FILE: gstmpegdesc.c --- #include <string.h> #include "gstmpegdesc.h" void gst_mpeg_descriptor_free (GstMPEGDescriptor * desc) g_return_if_fail (desc != NULL); g_free (desc); static guint gst_mpeg_descriptor_parse_1 (guint8 * data, guint size) guint8 tag; guint8 length; /* need at least 2 bytes for tag and length */ if (size < 2) return 0; tag = *data++; length = *data++; size -= 2; GST_DEBUG ("tag: 0x%02x, length: %d", tag, length); if (length > size) return length + 2;; GstMPEGDescriptor * gst_mpeg_descriptor_parse (guint8 * data, guint size) guint8 *current; guint consumed, total, n_desc; GstMPEGDescriptor *result; g_return_val_if_fail (data != NULL, NULL); current = data; total = 0; n_desc = 0; do { consumed = gst_mpeg_descriptor_parse_1 (current, size); if (consumed > 0) { current += consumed; total += consumed; size -= consumed; n_desc++; } while (consumed > 0); GST_DEBUG ("parsed %d descriptors", n_desc); if (total == 0) return NULL; result = g_malloc (sizeof (GstMPEGDescriptor) + total); result->n_desc = n_desc; result->data_length = total; result->data = ((guint8 *) result) + sizeof (GstMPEGDescriptor); memcpy (result->data, data, total); guint gst_mpeg_descriptor_n_desc (GstMPEGDescriptor * desc) g_return_val_if_fail (desc != NULL, 0); return desc->n_desc; guint8 * gst_mpeg_descriptor_find (GstMPEGDescriptor * desc, gint tag) gint length; guint size; g_return_val_if_fail (desc != NULL, NULL); current = desc->data; length = desc->data_length; while (length > 0) { if (DESC_TAG (current) == tag) return current; size = DESC_LENGTH (current) + 2; current += size; length -= size; return NULL; gst_mpeg_descriptor_nth (GstMPEGDescriptor * desc, guint i) if (i > desc->n_desc) if (i == 0) i--; --- NEW FILE: gstmpegdesc.h --- #ifndef __GST_MPEG_DESC_H__ #define __GST_MPEG_DESC_H__ #include <glib.h> * descriptor_tag TS PS Identification * 0 n/a n/a Reserved * 1 n/a n/a Reserved * 2 X X video_stream_descriptor * 3 X X audio_stream_descriptor * 4 X X hierarchy_descriptor * 5 X X registration_descriptor * 6 X X data_stream_alignment_descriptor * 7 X X target_background_grid_descriptor * 8 X X video_window_descriptor * 9 X X CA_descriptor * 10 X X ISO_639_language_descriptor * 11 X X system_clock_descriptor * 12 X X multiplex_buffer_utilization_descriptor * 13 X X copyright_descriptor * 14 X maximum bitrate descriptor * 15 X X private data indicator descriptor * 16 X X smoothing buffer descriptor * 17 X STD_descriptor * 18 X X IBP descriptor * 19-63 n/a n/a ITU-T Rec. H.222.0 | ISO/IEC 13818-1 Reserved * 64-255 n/a n/a User Private #define DESC_VIDEO_STREAM 2 #define DESC_AUDIO_STREAM 3 #define DESC_HIERARCHY 4 #define DESC_REGISTRATION 5 #define DESC_DATA_STREAM_ALIGNMENT 6 #define DESC_TARGET_BACKGROUND_GRID 7 #define DESC_VIDEO_WINDOW 8 #define DESC_CA 9 #define DESC_ISO_639_LANGUAGE 10 #define DESC_SYSTEM_CLOCK 11 #define DESC_MULTIPLEX_BUFFER_UTILISATION 12 #define DESC_COPYRIGHT 13 #define DESC_MAXIMUM_BITRATE 14 #define DESC_PRIVATE_DATA_INDICATOR 15 #define DESC_SMOOTHING_BUFFER 16 #define DESC_STD 17 #define DESC_IBP 18 #define DESC_DIRAC_TC_PRIVATE 0xAC /* DVB tags */ #define DESC_DVB_NETWORK_NAME 0x40 #define DESC_DVB_SERVICE_LIST 0x41 #define DESC_DVB_STUFFING 0x42 #define DESC_DVB_SATELLITE_DELIVERY_SYSTEM 0x43 #define DESC_DVB_CABLE_DELIVERY_SYSTEM 0x44 #define DESC_DVB_VBI_DATA 0x45 #define DESC_DVB_VBI_TELETEXT 0x46 #define DESC_DVB_BOUQUET_NAME 0x47 #define DESC_DVB_SERVICE 0x48 #define DESC_DVB_COUNTRY_AVAILABILITY 0x49 #define DESC_DVB_LINKAGE 0x4A #define DESC_DVB_NVOD_REFERENCE 0x4B #define DESC_DVB_TIME_SHIFTED_SERVICE 0x4C #define DESC_DVB_SHORT_EVENT 0x4D #define DESC_DVB_EXTENDED_EVENT 0x4E #define DESC_DVB_TIME_SHIFTED_EVENT 0x4F #define DESC_DVB_COMPONENT 0x50 #define DESC_DVB_MOSAIC 0x51 #define DESC_DVB_STREAM_IDENTIFIER 0x52 #define DESC_DVB_CA_IDENTIFIER 0x53 #define DESC_DVB_CONTENT 0x54 #define DESC_DVB_PARENTAL_RATING 0x55 #define DESC_DVB_TELETEXT 0x56 #define DESC_DVB_TELEPHONE 0x57 #define DESC_DVB_LOCAL_TIME_OFFSET 0x58 #define DESC_DVB_SUBTITLING 0x59 #define DESC_DVB_TERRESTRIAL_DELIVERY_SYSTEM 0x5A #define DESC_DVB_MULTILINGUAL_NETWORK_NAME 0x5B #define DESC_DVB_MULTILINGUAL_BOUQUET_NAME 0x5C #define DESC_DVB_MULTILINGUAL_SERVICE_NAME 0x5D #define DESC_DVB_MULTILINGUAL_COMPONENT 0x5E #define DESC_DVB_PRIVATE_DATA 0x5F #define DESC_DVB_SERVICE_MOVE 0x60 #define DESC_DVB_SHORT_SMOOTHING_BUFFER 0x61 #define DESC_DVB_FREQUENCY_LIST 0x62 #define DESC_DVB_PARTIAL_TRANSPORT_STREAM 0x63 #define DESC_DVB_DATA_BROADCAST 0x64 #define DESC_DVB_SCRAMBLING 0x65 #define DESC_DVB_DATA_BROADCAST_ID 0x66 #define DESC_DVB_TRANSPORT_STREAM 0x67 #define DESC_DVB_DSNG 0x68 #define DESC_DVB_PDC 0x69 #define DESC_DVB_AC3 0x6A #define DESC_DVB_ANCILLARY_DATA 0x6B #define DESC_DVB_CELL_LIST 0x6C #define DESC_DVB_CELL_FREQUENCY_LINK 0x6D #define DESC_DVB_ANNOUNCEMENT_SUPPORT 0x6E #define DESC_DVB_APPLICATION_SIGNALLING 0x6F #define DESC_DVB_ADAPTATION_FIELD_DATA 0x70 #define DESC_DVB_SERVICE_IDENTIFIER 0x71 #define DESC_DVB_SERVICE_AVAILABILITY 0x72 #define DESC_DVB_DEFAULT_AUTHORITY 0x73 #define DESC_DVB_RELATED_CONTENT 0x74 #define DESC_DVB_TVA_ID 0x75 #define DESC_DVB_CONTENT_IDENTIFIER 0x76 #define DESC_DVB_TIMESLICE_FEC_IDENTIFIER 0x77 #define DESC_DVB_ECM_REPETITION_RATE 0x78 #define DESC_DVB_S2_SATELLITE_DELIVERY_SYSTEM 0x79 #define DESC_DVB_ENHANCED_AC3 0x7A #define DESC_DVB_DTS 0x7B #define DESC_DVB_AAC 0x7C /* 0x7D and 0x7E are reserved for future use */ #define DESC_DVB_EXTENSION 0x7F /* 0x80 - 0xFE are user defined */ /* 0xFF is forbidden */ /* common for all descriptors */ #define DESC_TAG(desc) (desc[0]) #define DESC_LENGTH(desc) (desc[1]) /* video_stream_descriptor */ #define DESC_VIDEO_STREAM_multiple_framerate_flag(desc) (((desc)[2] & 0x80) == 0x80) #define DESC_VIDEO_STREAM_frame_rate_code(desc) (((desc)[2] & 0x38) >> 3) #define DESC_VIDEO_STREAM_MPEG_1_only_flag(desc) (((desc)[2] & 0x04) == 0x04) #define DESC_VIDEO_STREAM_constrained_parameter_flag(desc) (((desc)[2] & 0x02) == 0x02) #define DESC_VIDEO_STREAM_still_picture_flag(desc) (((desc)[2] & 0x01) == 0x01) /* if (MPEG_1_only_flag == 1) */ #define DESC_VIDEO_STREAM_profile_and_level_indication(desc) ((desc)[3]) #define DESC_VIDEO_STREAM_chroma_format(desc) (((desc)[4] & 0xc0) >> 6) #define DESC_VIDEO_STREAM_frame_rate_extension_flag(desc) (((desc)[4] & 0x20) == 0x20) /* audio_stream_descriptor */ #define DESC_AUDIO_STREAM_free_format_flag(desc) (((desc)[2] & 0x80) == 0x80) #define DESC_AUDIO_STREAM_ID(desc) (((desc)[2] & 0x40) == 0x40) #define DESC_AUDIO_STREAM_layer(desc) (((desc)[2] & 0x30) >> 4) #define DESC_AUDIO_STREAM_variable_rate_audio_indicator(desc) (((desc)[2] & 0x08) == 0x08) /* hierarchy_descriptor */ #define DESC_HIERARCHY_hierarchy_type(desc) (((desc)[2] & 0x0f)) #define DESC_HIERARCHY_hierarchy_layer_index(desc) (((desc)[3] & 0x3f)) #define DESC_HIERARCHY_hierarchy_embedded_layer_index(desc) (((desc)[4] & 0x3f)) #define DESC_HIERARCHY_hierarchy_channel(desc) (((desc)[5] & 0x3f)) /* registration_descriptor */ #define DESC_REGISTRATION_format_identifier(desc) (GST_READ_UINT32_BE ((desc)+2)) #define DESC_REGISTRATION_additional_ident_info_len(desc) ((desc)[1] - 4) #define DESC_REGISTRATION_additional_ident_info(desc) (&(desc)[6]) /* data_stream_alignment_descriptor */ #define DESC_DATA_STREAM_ALIGNMENT_alignment_type(desc) ((desc)[2]) /* target_background_grid_descriptor */ #define DESC_TARGET_BACKGROUND_GRID_horizontal_size(desc) (GST_READ_UINT16_BE ((desc)+2) >> 2) #define DESC_TARGET_BACKGROUND_GRID_vertical_size(desc) ((GST_READ_UINT32_BE ((desc)+2) & 0x0003fff0) >> 4) #define DESC_TARGET_BACKGROUND_GRID_aspect_ratio_information(desc) ((desc)[5] & 0x0f) /* video_window_descriptor */ #define DESC_VIDEO_WINDOW_horizontal_offset(desc) (GST_READ_UINT16_BE ((desc)+2) >> 2) #define DESC_VIDEO_WINDOW_vertical_offset(desc) ((GST_READ_UINT32_BE ((desc)+2) & 0x0003fff0) >> 4) #define DESC_VIDEO_WINDOW_window_priority(desc) ((desc)[5] & 0x0f) /* CA_descriptor */ #define DESC_CA_system_ID(desc) (GST_READ_UINT16_BE ((desc)+2)) #define DESC_CA_PID(desc) (GST_READ_UINT16_BE ((desc)+2) & 0x1fff) /* ISO_639_language_descriptor */ #define DESC_ISO_639_LANGUAGE_codes_n(desc) ((desc[1]) >> 2) #define DESC_ISO_639_LANGUAGE_language_code_nth(desc,i) (&(desc[2 + (4*i)])) #define DESC_ISO_639_LANGUAGE_audio_type_nth(desc,i) ((desc)[5 + (4*i)]) /* system_clock_descriptor */ #define DESC_SYSTEM_CLOCK_external_clock_reference_indicator(desc) (((desc)[2] & 0x80) == 0x80) #define DESC_SYSTEM_CLOCK_clock_accuracy_integer(desc) ((desc)[2] & 0x3f) #define DESC_SYSTEM_CLOCK_clock_accuracy_exponent(desc) (((desc)[3] & 0xe0) >> 5) /* multiplex_buffer_utilization_descriptor */ #define DESC_MULTIPLEX_BUFFER_UTILISATION_bound_valid_flag(desc) (((desc)[2] & 0x80) == 0x80) #define DESC_MULTIPLEX_BUFFER_UTILISATION_LTW_offset_lower_bound(desc) (GST_READ_UINT16_BE ((desc)+2) & 0x7fff) #define DESC_MULTIPLEX_BUFFER_UTILISATION_LTW_offset_upper_bound(desc) (GST_READ_UINT16_BE ((desc)+4) & 0x7fff) /* copyright_descriptor */ #define DESC_COPYRIGHT_copyright_identifier(desc) (GST_READ_UINT32_BE ((desc)+2)) #define DESC_COPYRIGHT_additional_copyright_info_len(desc) ((desc)[1] - 4) #define DESC_COPYRIGHT_additional_copyright_info(desc) (&(desc)[6]) /* maximum_bitrate_descriptor */ #define DESC_MAXIMUM_BITRAT_maximum_bitrate(desc) (((((guint32)desc[2]) & 0x3f) << 16) | \ GST_READ_UINT16_BE ((desc)+3)) /* private_data_indicator_descriptor */ #define DESC_PRIVATE_DATA_INDICATOR_indicator(desc) (GST_READ_UINT32_BE(&desc[2])) /* smoothing_buffer_descriptor */ #define DESC_SMOOTHING_BUFFER_sb_leak_rate(desc) (((((guint32)desc[2]) & 0x3f) << 16) | \ GST_READ_UINT16_BE ((desc)+3)) #define DESC_SMOOTHING_BUFFER_sb_size(desc) (((((guint32)desc[5]) & 0x3f) << 16) | \ GST_READ_UINT16_BE ((desc)+6)) /* STD_descriptor */ #define DESC_STD_leak_valid_flag(desc) (((desc)[2] & 0x01) == 0x01) /* ibp_descriptor */ #define DESC_IBP_closed_gop_flag(desc) (((desc)[2] & 0x80) == 0x80) #define DESC_IBP_identical_gop_flag(desc) (((desc)[2] & 0x40) == 0x40) #define DESC_IBP_max_gop_length(desc) (GST_READ_UINT16_BE ((desc)+6) & 0x3fff) /* time_code descriptor */ #define DESC_TIMECODE_video_pid(desc) (GST_READ_UINT16_BE ((desc) + 2) & 0x1fff) /* Stream identifier descriptor */ #define DESC_DVB_STREAM_IDENTIFIER_component_tag(desc) (desc[2]) /* DVB Network Name descriptor */ #define DESC_DVB_NETWORK_NAME_length(desc) (GST_READ_UINT8((desc)+1)) #define DESC_DVB_NETWORK_NAME_text(desc) (desc+2) typedef struct { guint n_desc; guint8 data_length; guint8 *data; } GstMPEGDescriptor; GstMPEGDescriptor* gst_mpeg_descriptor_parse (guint8 *data, guint size); void gst_mpeg_descriptor_free (GstMPEGDescriptor *desc); guint gst_mpeg_descriptor_n_desc (GstMPEGDescriptor *desc); guint8* gst_mpeg_descriptor_find (GstMPEGDescriptor *desc, gint tag); guint8* gst_mpeg_descriptor_nth (GstMPEGDescriptor *desc, guint i); #endif /* __GST_MPEG_DESC_H__ */ --- NEW FILE: gstpesfilter.c --- #ifdef HAVE_CONFIG_H #include "config.h" #endif #include "gstmpegdefs.h" GST_DEBUG_CATEGORY (gstflupesfilter_debug); #define GST_CAT_DEFAULT (gstflupesfilter_debug) static GstFlowReturn gst_pes_filter_data_push (GstPESFilter * filter, gboolean first, GstBuffer * buffer); #define ADAPTER_OFFSET_FLUSH(_bytes_) if (filter->adapter_offset) *filter->adapter_offset = *filter->adapter_offset + (_bytes_) /* May pass null for adapter to have the filter create one */ gst_pes_filter_init (GstPESFilter * filter, GstAdapter * adapter, guint64 * adapter_offset) g_return_if_fail (filter != NULL); if (adapter != NULL) g_object_ref (adapter); else adapter = gst_adapter_new (); filter->adapter = adapter; filter->adapter_offset = adapter_offset; filter->state = STATE_HEADER_PARSE; filter->gather_pes = FALSE; filter->allow_unbounded = FALSE; gst_pes_filter_uninit (GstPESFilter * filter) if (filter->adapter) g_object_unref (filter->adapter); filter->adapter = NULL; filter->adapter_offset = NULL; gst_pes_filter_set_callbacks (GstPESFilter * filter, GstPESFilterData data_cb, GstPESFilterResync resync_cb, gpointer user_data) filter->data_cb = data_cb; filter->resync_cb = resync_cb; filter->user_data = user_data; /* sync:4 == 00xx ! pts:3 ! 1 ! pts:15 ! 1 | pts:15 ! 1 */ #define READ_TS(data, target, lost_sync_label) \ if ((*data & 0x01) != 0x01) goto lost_sync_label; \ target = ((guint64) (*data++ & 0x0E)) << 29; \ target |= ((guint64) (*data++ )) << 22; \ target |= ((guint64) (*data++ & 0xFE)) << 14; \ target |= ((guint64) (*data++ )) << 7; \ target |= ((guint64) (*data++ & 0xFE)) >> 1; static gboolean gst_pes_filter_is_sync (guint32 sync) return ((sync & 0xfffffffc) == 0x000001bc) || ((sync & 0xffffffe0) == 0x000001c0) || ((sync & 0xfffffff0) == 0x000001f0) || ((sync & 0xfffffff0) == 0x000001e0); static GstFlowReturn gst_pes_filter_parse (GstPESFilter * filter) GstFlowReturn ret; guint32 start_code; gboolean STD_buffer_bound_scale; guint16 STD_buffer_size_bound; const guint8 *data; gint avail, datalen; gboolean have_size = FALSE; /* read start code and length */ if (!(data = gst_adapter_peek (filter->adapter, 6))) goto need_more_data; /* get start code */ start_code = GST_READ_UINT32_BE (data); if (!gst_pes_filter_is_sync (start_code)) goto lost_sync; filter->start_code = start_code; filter->id = data[3]; /* skip start code */ data += 4; /* start parsing length */ filter->length = GST_READ_UINT16_BE (data); /* see how much is available */ avail = gst_adapter_available (filter->adapter); GST_DEBUG ("id 0x%02x length %d, avail %d start code 0x%02x", filter->id, filter->length, avail, filter->start_code); /* A data length of 0 indicates an unbounded packet in transport * streams, but actually a 0 sized packet in program streams or * for anything except video packets */ /* FIXME: Remove this hack that is checking start_code. Instead, we need * a callback that a start_code has been collected, giving the caller a chance * to set the allow_unbounded flag if they want */ if (filter->length == 0 && ((filter->start_code & 0xFFFFFFF0) == PACKET_VIDEO_START_CODE || filter->allow_unbounded)) { GST_DEBUG ("id 0x%02x, unbounded length", filter->id); filter->unbounded_packet = TRUE; } else { filter->unbounded_packet = FALSE; if (filter->gather_pes && avail < filter->length + 6) { GST_DEBUG ("id 0x%02x, bounded length %d, only have %d", filter->id, filter->length + 6, avail); goto need_more_data; /* if we need more data from now on, we lost sync */ avail = MIN (avail, filter->length + 6); /* read more data, either the whole packet if there is a length * or whatever we have available if this in an unbounded packet. */ if (!(data = gst_adapter_peek (filter->adapter, avail))) /* This will make us flag LOST_SYNC if we run out of data from here onward */ have_size = TRUE; /* skip start code and length */ data += 6; datalen = avail - 6; GST_DEBUG ("datalen %d", datalen); switch (filter->start_code) { case ID_PS_PROGRAM_STREAM_MAP: case ID_PRIVATE_STREAM_2: case ID_ECM_STREAM: case ID_EMM_STREAM: case ID_PROGRAM_STREAM_DIRECTORY: case ID_DSMCC_STREAM: case ID_ITU_TREC_H222_TYPE_E_STREAM: goto skip; case ID_PADDING_STREAM: GST_DEBUG ("skipping padding stream"); if (datalen < 1) filter->pts = filter->dts = -1; /* stuffing bits, first two bits are '10' for mpeg2 pes so this code is * not triggered. */ while (TRUE) { if (*data != 0xff) data++; datalen--; GST_DEBUG ("got stuffing bit"); if (datalen < 1) /* STD buffer size, never for mpeg2 */ if ((*data & 0xc0) == 0x40) { GST_DEBUG ("have STD"); if (datalen < 3) STD_buffer_bound_scale = *data & 0x20; STD_buffer_size_bound = ((guint16) (*data++ & 0x1F)) << 8; STD_buffer_size_bound |= *data++; datalen -= 2; /* PTS but no DTS, never for mpeg2 */ if ((*data & 0xf0) == 0x20) { GST_DEBUG ("PTS without DTS"); if (datalen < 5) READ_TS (data, filter->pts, lost_sync); GST_DEBUG ("PTS found %" G_GUINT64_FORMAT, filter->pts); datalen -= 5; /* PTS and DTS, never for mpeg2 */ else if ((*data & 0xf0) == 0x30) { GST_DEBUG ("PTS and DTS"); if (datalen < 10) READ_TS (data, filter->dts, lost_sync); GST_DEBUG ("DTS found %" G_GUINT64_FORMAT, filter->dts); datalen -= 10; } else if ((*data & 0xc0) == 0x80) { /* mpeg2 case */ guchar flags; guint8 header_data_length = 0; GST_DEBUG ("MPEG2 PES packet"); /* 2: '10' * 2: PES_scrambling_control * 1: PES_priority * 1: data_alignment_indicator * 1: copyright * 1: original_or_copy */ flags = *data++; GST_DEBUG ("flags: 0x%02x", flags); if ((flags & 0xc0) != 0x80) goto lost_sync; /* check PES scrambling control */ if ((flags & 0x30) != 0) goto encrypted; /* 2: PTS_DTS_flags * 1: ESCR_flag * 1: ES_rate_flag * 1: DSM_trick_mode_flag * 1: additional_copy_info_flag * 1: PES_CRC_flag * 1: PES_extension_flag /* 8: PES_header_data_length */ header_data_length = *data++; datalen -= 3; GST_DEBUG ("header_data_length: %d, flags 0x%02x", header_data_length, flags); if (header_data_length > datalen) /* only DTS: this is invalid */ if ((flags & 0xc0) == 0x40) /* check for PTS */ if ((flags & 0x80)) { if (datalen < 5) goto need_more_data; READ_TS (data, filter->pts, lost_sync); GST_DEBUG ("PTS found %" G_GUINT64_FORMAT, filter->pts); header_data_length -= 5; datalen -= 5; /* check for DTS */ if ((flags & 0x40)) { READ_TS (data, filter->dts, lost_sync); GST_DEBUG ("DTS found %" G_GUINT64_FORMAT, filter->dts); /* ESCR_flag */ if ((flags & 0x20)) { GST_DEBUG ("%x ESCR found", filter->id); if (datalen < 6) data += 6; header_data_length -= 6; datalen -= 6; /* ES_rate_flag */ if ((flags & 0x10)) { guint32 es_rate; if (datalen < 3) es_rate = ((guint32) (*data++ & 0x07)) << 14; es_rate |= ((guint32) (*data++)) << 7; es_rate |= ((guint32) (*data++ & 0xFE)) >> 1; GST_DEBUG ("%x ES Rate found %u", filter->id, es_rate); header_data_length -= 3; datalen -= 3; /* DSM_trick_mode_flag */ if ((flags & 0x08)) { guint8 trick_mode_flags; if (datalen < 1) /* 3: trick_mode_control */ trick_mode_flags = *data++; GST_DEBUG ("%x DSM trick mode found, flags 0x%02x", filter->id, trick_mode_flags); /* fast_forward */ if ((trick_mode_flags & 0xe0) == 0x00) { } /* slow motion */ else if ((trick_mode_flags & 0xe0) == 0x20) { /* freeze frame */ else if ((trick_mode_flags & 0xe0) == 0x40) { /* fast reverse */ else if ((trick_mode_flags & 0xe0) == 0x60) { /* slow reverse */ else if ((trick_mode_flags & 0xe0) == 0x80) { /* reserved */ else { header_data_length -= 1; datalen -= 1; /* additional_copy_info_flag */ if ((flags & 0x04)) { GST_DEBUG ("%x additional copy info, flags 0x%02x", filter->id, *data); /* PES_CRC_flag */ if ((flags & 0x02)) { GST_DEBUG ("%x PES_CRC", filter->id); /* PES_extension_flag */ if ((flags & 0x01)) { GST_DEBUG ("%x PES_extension", filter->id); /* calculate the amount of real data in this PES packet */ data += header_data_length; datalen -= header_data_length; } else if (*data == 0x0f) { /* Not sure what this clause is for */ /* Data byte wasn't recognised as a flags byte */ GST_DEBUG ("Unrecognised flags byte 0x%02x\n", *data); { GstBuffer *out; guint16 consumed; consumed = avail - 6 - datalen; if (filter->unbounded_packet == FALSE) { filter->length -= avail - 6; GST_DEBUG ("pushing %d, need %d more, consumed %d", datalen, filter->length, consumed); } else { GST_DEBUG ("pushing %d, unbounded packet, consumed %d", datalen, consumed); if (datalen > 0) { out = gst_buffer_new (); GST_BUFFER_DATA (out) = g_memdup (data, datalen); GST_BUFFER_SIZE (out) = datalen; GST_BUFFER_MALLOCDATA (out) = GST_BUFFER_DATA (out); ret = gst_pes_filter_data_push (filter, TRUE, out); filter->first = FALSE; GST_LOG ("first being set to TRUE"); filter->first = TRUE; ret = GST_FLOW_OK; if (filter->length > 0 || filter->unbounded_packet) filter->state = STATE_DATA_PUSH; gst_adapter_flush (filter->adapter, avail); ADAPTER_OFFSET_FLUSH (avail); return ret; need_more_data: if (have_size == TRUE) { GST_DEBUG ("bounded need more data %d, lost sync", gst_adapter_available (filter->adapter)); ret = GST_FLOW_LOST_SYNC; } else { GST_DEBUG ("bounded need more data %d, breaking for more", ret = GST_FLOW_NEED_MORE_DATA; GST_DEBUG ("unbounded need more data %d", gst_adapter_available (filter->adapter)); ret = GST_FLOW_NEED_MORE_DATA; return ret; skip: GST_DEBUG ("skipping 0x%02x", filter->id); gst_adapter_flush (filter->adapter, avail); ADAPTER_OFFSET_FLUSH (avail); filter->length -= avail - 6; filter->state = STATE_DATA_SKIP; return GST_FLOW_OK; encrypted: GST_DEBUG ("skipping encrypted 0x%02x", filter->id); lost_sync: GST_DEBUG ("lost sync"); gst_adapter_flush (filter->adapter, 4); ADAPTER_OFFSET_FLUSH (4); return GST_FLOW_LOST_SYNC; gst_pes_filter_data_push (GstPESFilter * filter, gboolean first, GstBuffer * buffer) GST_LOG ("pushing, first: %d", first); if (filter->data_cb) { ret = filter->data_cb (filter, first, buffer, filter->user_data); gst_buffer_unref (buffer); ret = GST_FLOW_OK; GstFlowReturn gst_pes_filter_push (GstPESFilter * filter, GstBuffer * buffer) g_return_val_if_fail (filter != NULL, GST_FLOW_ERROR); g_return_val_if_fail (buffer != NULL, GST_FLOW_ERROR); switch (filter->state) { case STATE_HEADER_PARSE: gst_adapter_push (filter->adapter, buffer); ret = gst_pes_filter_parse (filter); case STATE_DATA_PUSH: ret = gst_pes_filter_data_push (filter, filter->first, buffer); case STATE_DATA_SKIP: gst_buffer_unref (buffer); goto wrong_state; /* ERROR */ wrong_state: GST_DEBUG ("wrong internal state %d", filter->state); return GST_FLOW_ERROR; gst_pes_filter_process (GstPESFilter * filter) gboolean skip = FALSE; skip = TRUE; /* fallthrough */ if (filter->length > 0 || filter->unbounded_packet) { gint avail; avail = gst_adapter_available (filter->adapter); if (filter->unbounded_packet == FALSE) avail = MIN (avail, filter->length); if (skip) { gst_adapter_flush (filter->adapter, avail); ADAPTER_OFFSET_FLUSH (avail); ret = GST_FLOW_OK; } else { GstBuffer *out; guint8 *data; data = gst_adapter_take (filter->adapter, avail); out = gst_buffer_new (); GST_BUFFER_DATA (out) = data; GST_BUFFER_SIZE (out) = avail; GST_BUFFER_MALLOCDATA (out) = data; ret = gst_pes_filter_data_push (filter, filter->first, out); filter->first = FALSE; } if (filter->unbounded_packet == FALSE) { filter->length -= avail; if (filter->length == 0) filter->state = STATE_HEADER_PARSE; filter->state = STATE_HEADER_PARSE; ret = GST_FLOW_OK; gst_pes_filter_flush (GstPESFilter * filter) if (filter->adapter) { gst_adapter_clear (filter->adapter); if (filter->adapter_offset) *filter->adapter_offset = G_MAXUINT64; gst_pes_filter_drain (GstPESFilter * filter) gst_pes_filter_flush (filter); return GST_FLOW_OK; --- NEW FILE: gstpesfilter.h --- #ifndef __GST_PES_FILTER_H__ #define __GST_PES_FILTER_H__ typedef struct _GstPESFilter GstPESFilter; typedef GstFlowReturn (*GstPESFilterData) (GstPESFilter * filter, gboolean first, GstBuffer * buffer, gpointer user_data); typedef void (*GstPESFilterResync) (GstPESFilter * filter, gpointer user_data); typedef void (*GstPESFilterIndex) (GstPESFilter * filter, gpointer user_data); STATE_HEADER_PARSE, STATE_DATA_PUSH, STATE_DATA_SKIP } GstPESFilterState; struct _GstPESFilter { GstAdapter * adapter; guint64 * adapter_offset; GstPESFilterState state; /* Whether to collect entire PES packets before * outputting */ gboolean gather_pes; /* Whether unbounded packets are allowed in this * stream */ gboolean allow_unbounded; gboolean first; GstPESFilterData data_cb; GstPESFilterResync resync_cb; gpointer user_data; guint32 start_code; guint8 id; gboolean unbounded_packet; guint16 length; guint8 type; gint64 pts; gint64 dts; void gst_pes_filter_init (GstPESFilter * filter, GstAdapter * adapter, guint64 * adapter_offset); void gst_pes_filter_uninit (GstPESFilter * filter); void gst_pes_filter_set_callbacks (GstPESFilter * filter, GstPESFilterData data_cb, GstPESFilterResync resync_cb, GstFlowReturn gst_pes_filter_push (GstPESFilter * filter, GstBuffer * buffer); GstFlowReturn gst_pes_filter_process (GstPESFilter * filter); void gst_pes_filter_flush (GstPESFilter * filter); GstFlowReturn gst_pes_filter_drain (GstPESFilter * filter); #endif /* __GST_PES_FILTER_H__ */ --- NEW FILE: plugin.c --- /* GStreamer * Copyright (C) 2008 Jan Schmidt <th...@no...> * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Library General Public * License as published by the Free Software Foundation; either * version 2 of the License, or (at your option) any later version. * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Library General Public License for more details. * You should have received a copy of the GNU Library General Public * License along with this library; if not, write to the * Free Software Foundation, Inc., 59 Temple Place - Suite 330, * Boston, MA 02111-1307, USA. # include <config.h> #include "resindvdbin.h" #include "gstmpegdemux.h" GST_DEBUG_CATEGORY (resindvd_debug); #define GST_CAT_DEFAULT resindvd_debug plugin_init (GstPlugin * plugin) gboolean result = TRUE; GST_DEBUG_CATEGORY_INIT (resindvd_debug, "resindvd elements", 0, "DVD playback elements from resindvd"); result &= gst_element_register (plugin, "rsndvdbin", GST_RANK_PRIMARY, RESIN_TYPE_DVDBIN); result &= gst_flups_demux_plugin_init (plugin); GST_PLUGIN_DEFINE (GST_VERSION_MAJOR, GST_VERSION_MINOR, "resindvd", "Resin DVD playback elements", plugin_init, VERSION, "GPL", "GStreamer", "http://gstreamer.net/") --- NEW FILE: resin-play --- #!/bin/sh if [ $# -ge 1 ]; then DEVICE_OPT="device=$1" else DEVICE_OPT="" fi gst-launch rsndvdbin name=dvd "$DEVICE_OPT" \ dvd. ! ffmpegcolorspace ! videoscale ! autovideosink \ dvd. ! audioconvert ! autoaudiosink --- NEW FILE: resindvdbin.c --- #include "resindvdsrc.h" #include "rsnstreamselector.h" #include "rsnaudiomunge.h" GST_DEBUG_CATEGORY_EXTERN (resindvd_debug); #define DECODEBIN_AUDIO 0 #define DVDBIN_LOCK(d) g_mutex_lock((d)->dvd_lock) #define DVDBIN_UNLOCK(d) g_mutex_unlock((d)->dvd_lock) #define DEFAULT_DEVICE "/dev/dvd" enum /* FILL ME */ LAST_SIGNAL ARG_0, ARG_DEVICE /* FIXME: Could list specific video and audio caps: */ static GstStaticPadTemplate video_src_template = GST_STATIC_PAD_TEMPLATE ("video", GST_PAD_SRC, GST_PAD_SOMETIMES, GST_STATIC_CAPS_ANY); static GstStaticPadTemplate audio_src_template = GST_STATIC_PAD_TEMPLATE ("audio", static void rsn_dvdbin_do_init (GType rsn_dvdbin_type); static void rsn_dvdbin_finalize (GObject * object); static void rsn_dvdbin_uri_handler_init (gpointer g_iface, gpointer iface_data); GST_BOILERPLATE_FULL (RsnDvdBin, rsn_dvdbin, GstBin, GST_TYPE_BIN, rsn_dvdbin_do_init); static void demux_pad_added (GstElement * element, GstPad * pad, RsnDvdBin * dvdbin); static void viddec_pad_added (GstElement * element, GstPad * pad, gboolean last, RsnDvdBin * dvdbin); #if DECODEBIN_AUDIO static void auddec_pad_added (GstElement * element, GstPad * pad, static void rsn_dvdbin_set_property (GObject * object, guint prop_id, const GValue * value, GParamSpec * pspec); static void rsn_dvdbin_get_property (GObject * object, guint prop_id, GValue * value, GParamSpec * pspec); static GstStateChangeReturn rsn_dvdbin_change_state (GstElement * element, GstStateChange transition); static void rsn_dvdbin_base_init (gpointer gclass) static GstElementDetails element_details = { "rsndvdbin", "Generic/Bin/Player", "DVD playback element", "Jan Schmidt <th...@no...>" }; GstElementClass *element_class = GST_ELEMENT_CLASS (gclass); gst_element_class_add_pad_template (element_class, gst_static_pad_template_get (&video_src_template)); gst_static_pad_template_get (&audio_src_template)); gst_element_class_set_details (element_class, &element_details); element_class->change_state = GST_DEBUG_FUNCPTR (rsn_dvdbin_change_state); rsn_dvdbin_class_init (RsnDvdBinClass * klass) GObjectClass *gobject_class; GstElementClass *gstelement_class; gobject_class = (GObjectClass *) klass; gstelement_class = (GstElementClass *) klass; gobject_class->finalize = rsn_dvdbin_finalize; gobject_class->set_property = rsn_dvdbin_set_property; gobject_class->get_property = rsn_dvdbin_get_property; g_object_class_install_property (gobject_class, ARG_DEVICE, g_param_spec_string ("device", "Device", "DVD device location", NULL, G_PARAM_READWRITE)); rsn_dvdbin_do_init (GType rsn_dvdbin_type) static const GInterfaceInfo urihandler_info = { rsn_dvdbin_uri_handler_init, NULL, NULL g_type_add_interface_static (rsn_dvdbin_type, GST_TYPE_URI_HANDLER, &urihandler_info); rsn_dvdbin_init (RsnDvdBin * dvdbin, RsnDvdBinClass * gclass) dvdbin->dvd_lock = g_mutex_new (); rsn_dvdbin_finalize (GObject * object) RsnDvdBin *dvdbin = RESINDVDBIN (object); g_mutex_free (dvdbin->dvd_lock); g_free (dvdbin->last_uri); g_free (dvdbin->device); G_OBJECT_CLASS (parent_class)->finalize (object); /* URI interface */ rsn_dvdbin_uri_get_type (void) return GST_URI_SRC; static gchar ** rsn_dvdbin_uri_get_protocols (void) static gchar *protocols[] = { "dvd", NULL }; return protocols; static const gchar * rsn_dvdbin_uri_get_uri (GstURIHandler * handler) RsnDvdBin *dvdbin = RESINDVDBIN (handler); DVDBIN_LOCK (dvdbin); if (dvdbin->device) dvdbin->last_uri = g_strdup_printf ("dvd://%s", dvdbin->device); dvdbin->last_uri = g_strdup ("dvd://"); DVDBIN_UNLOCK (dvdbin); return dvdbin->last_uri; rsn_dvdbin_uri_set_uri (GstURIHandler * handler, const gchar * uri) // RsnDvdBin *dvdbin = RESINDVDBIN (handler); gboolean ret; gchar *protocol, *location; protocol = gst_uri_get_protocol (uri); ret = (protocol && !strcmp (protocol, "dvd")) ? TRUE : FALSE; g_free (protocol); protocol = NULL; if (!ret) location = gst_uri_get_location (uri); if (!location) /* * Parse out the device name */ #if 0 * Parse out the new t/c/a and seek to them gchar **strs; gchar **strcur; gint pos = 0; location = gst_uri_get_location (uri); if (!location) return ret; strcur = strs = g_strsplit (location, ",", 0); while (strcur && *strcur) { gint val; if (!sscanf (*strcur, "%d", &val)) break; switch (pos) { case 0: if (val != dvdbin->uri_title) { dvdbin->uri_title = val; dvdbin->new_seek = TRUE; } break; case 1: if (val != dvdbin->uri_chapter) { dvdbin->uri_chapter = val; case 2: dvdbin->uri_angle = val; strcur++; pos++; g_strfreev (strs); g_free (location); rsn_dvdbin_uri_handler_init (gpointer g_iface, gpointer iface_data) GstURIHandlerInterface *iface = (GstURIHandlerInterface *) g_iface; iface->get_type = rsn_dvdbin_uri_get_type; iface->get_protocols = rsn_dvdbin_uri_get_protocols; iface->get_uri = rsn_dvdbin_uri_get_uri; iface->set_uri = rsn_dvdbin_uri_set_uri; try_create_piece (RsnDvdBin * dvdbin, gint index, const gchar * factory, GType type, const gchar * name, const gchar * descr) GstElement *e; if (dvdbin->pieces[index] != NULL) { DVDBIN_UNLOCK (dvdbin); return TRUE; /* Already exists */ if (factory != NULL) { e = gst_element_factory_make (factory, name); if (name) e = g_object_new (type, "name", name, NULL); else e = g_object_new (type, NULL); if (e == NULL) goto create_failed; if (!gst_bin_add (GST_BIN (dvdbin), e)) goto add_failed; GST_DEBUG_OBJECT (dvdbin, "Added %s element: %" GST_PTR_FORMAT, descr, e); dvdbin->pieces[index] = e; create_failed: GST_ELEMENT_ERROR (dvdbin, CORE, MISSING_PLUGIN, (NULL), ("Could not create %s element '%s'", descr, factory)); return FALSE; add_failed: gst_object_unref (e); GST_ELEMENT_ERROR (dvdbin, CORE, FAILED, (NULL), ("Could not add %s element to bin", descr)); create_elements (RsnDvdBin * dvdbin) GstPad *src = NULL; GstPad *sink = NULL; GstPad *ghost = NULL; if (!try_create_piece (dvdbin, DVD_ELEM_SOURCE, NULL, RESIN_TYPE_DVDSRC, "dvdsrc", "DVD source")) { return FALSE; /* FIXME: Locking */ if (dvdbin->device) { g_object_set (G_OBJECT (dvdbin->pieces[DVD_ELEM_SOURCE]), "device", dvdbin->device, NULL); if (!try_create_piece (dvdbin, DVD_ELEM_DEMUX, NULL, GST_TYPE_FLUPS_DEMUX, "dvddemux", "DVD demuxer")) if (gst_element_link (dvdbin->pieces[DVD_ELEM_SOURCE], dvdbin->pieces[DVD_ELEM_DEMUX]) == FALSE) goto failed_connect; /* Listen for new pads from the demuxer */ g_signal_connect (G_OBJECT (dvdbin->pieces[DVD_ELEM_DEMUX]), "pad-added", G_CALLBACK (demux_pad_added), dvdbin); if (!try_create_piece (dvdbin, DVD_ELEM_MQUEUE, "multiqueue", 0, "mq", "multiqueue")) g_object_set (dvdbin->pieces[DVD_ELEM_MQUEUE], "max-size-time", (7 * GST_SECOND / 10), "max-size-bytes", 0, "max-size-buffers", 0, NULL); /* Decodebin will throw a missing element message to find an MPEG decoder */ if (!try_create_piece (dvdbin, DVD_ELEM_VIDDEC, "decodebin", 0, "viddec", "video decoder")) g_signal_connect (G_OBJECT (dvdbin->pieces[DVD_ELEM_VIDDEC]), "new-decoded-pad", G_CALLBACK (viddec_pad_added), dvdbin); if (!try_create_piece (dvdbin, DVD_ELEM_VIDQ, "queue", 0, "vid_q", "video decoder buffer")) g_object_set (dvdbin->pieces[DVD_ELEM_VIDQ], "max-size-time", G_GUINT64_CONSTANT (0), "max-size-bytes", 0, "max-size-buffers", 3, NULL); if (!try_create_piece (dvdbin, DVD_ELEM_SPU_SELECT, NULL, RSN_TYPE_STREAM_SELECTOR, "subpselect", "Subpicture stream selector")) if (!try_create_piece (dvdbin, DVD_ELEM_SPU, "dvdspu", 0, "spu", "Subpicture overlay")) sink = gst_element_get_static_pad (dvdbin->pieces[DVD_ELEM_SPU], "video"); src = gst_element_get_static_pad (dvdbin->pieces[DVD_ELEM_VIDQ], "src"); if (src == NULL || sink == NULL) goto failed_spu_connect; if (GST_PAD_LINK_FAILED (gst_pad_link (src, sink))) gst_object_unref (sink); gst_object_unref (src); src = sink = NULL; sink = gst_element_get_static_pad (dvdbin->pieces[DVD_ELEM_SPU], "subpicture"); src = gst_element_get_static_pad (dvdbin->pieces[DVD_ELEM_SPU_SELECT], "src"); src = gst_element_get_static_pad (dvdbin->pieces[DVD_ELEM_SPU], "src"); if (src == NULL) goto failed_spu_ghost; ghost = gst_ghost_pad_new ("video", src); if (ghost == NULL) if (!gst_element_add_pad (GST_ELEMENT (dvdbin), ghost)) if (!try_create_piece (dvdbin, DVD_ELEM_AUD_SELECT, NULL, RSN_TYPE_STREAM_SELECTOR, "audioselect", "Audio stream selector")) /* rsnaudiomunge goes after the audio decoding to regulate the stream */ if (!try_create_piece (dvdbin, DVD_ELEM_AUD_MUNGE, NULL, RSN_TYPE_AUDIOMUNGE, "audiomunge", "Audio output filter")) /* Decodebin will throw a missing element message to find a suitable * decoder */ if (!try_create_piece (dvdbin, DVD_ELEM_AUDDEC, "decodebin", 0, "auddec", "audio decoder")) g_signal_connect (G_OBJECT (dvdbin->pieces[DVD_ELEM_AUDDEC]), "new-decoded-pad", G_CALLBACK (auddec_pad_added), dvdbin); #else if (!try_create_piece (dvdbin, DVD_ELEM_AUDDEC, "a52dec", 0, "auddec", src = gst_element_get_static_pad (dvdbin->pieces[DVD_ELEM_AUDDEC], "src"); gst_element_get_static_pad (dvdbin->pieces[DVD_ELEM_AUD_MUNGE], "sink"); goto failed_aud_connect; src = gst_element_get_static_pad (dvdbin->pieces[DVD_ELEM_AUD_SELECT], "src"); sink = gst_element_get_static_pad (dvdbin->pieces[DVD_ELEM_AUDDEC], "sink"); /* ghost audio munge output pad onto bin */ src = gst_element_get_static_pad (dvdbin->pieces[DVD_ELEM_AUD_MUNGE], "src"); goto failed_aud_ghost; ghost = gst_ghost_pad_new ("audio", src); failed_connect: ("Could not connect DVD source and demuxer elements")); failed_spu_connect: ("Could not connect DVD video buffer and spu elements")); if (src != NULL) gst_object_unref (src); if (sink != NULL) gst_object_unref (sink); failed_spu_ghost: ("Could not ghost SPU output pad")); if (ghost != NULL) gst_object_unref (ghost); failed_aud_connect: ("Could not connect DVD audio decoder")); failed_aud_ghost: ("Could not ghost audio output pad")); remove_elements (RsnDvdBin * dvdbin) gint i; GList *tmp; if (dvdbin->pieces[DVD_ELEM_MQUEUE] != NULL) { for (tmp = dvdbin->mq_req_pads; tmp; tmp = g_list_next (tmp)) { gst_element_release_request_pad (dvdbin->pieces[DVD_ELEM_MQUEUE], GST_PAD (tmp->data)); g_list_free (dvdbin->mq_req_pads); dvdbin->mq_req_pads = NULL; for (i = 0; i < DVD_ELEM_LAST; i++) { DVDBIN_LOCK (dvdbin); if (dvdbin->pieces[i] != NULL) { GstElement *piece = dvdbin->pieces[i]; dvdbin->pieces[i] = NULL; DVDBIN_UNLOCK (dvdbin); gst_element_set_state (piece, GST_STATE_NULL); gst_bin_remove (GST_BIN (dvdbin), piece); } else static GstPad * connect_thru_mq (RsnDvdBin * dvdbin, GstPad * pad) GstPad *mq_sink; GstPad *mq_src; gchar *tmp, *sinkname, *srcname; /* Request a pad from multiqueue, then connect this one, then * discover the corresponding output pad and return it */ mq_sink = gst_element_get_request_pad (dvdbin->pieces[DVD_ELEM_MQUEUE], "sink%d"); if (mq_sink == NULL) dvdbin->mq_req_pads = g_list_prepend (dvdbin->mq_req_pads, mq_sink); if... [truncated message content] |