/* GStreamer
* Copyright (C) 2010 Marc-Andre Lureau <marcandre.lureau@gmail.com>
* Copyright (C) 2010 Andoni Morales Alastruey <ylatuya@gmail.com>
+ * Copyright (C) 2015 Tim-Philipp Müller <tim@centricular.com>
*
* gsthlsdemux.h:
*
#define __GST_HLS_DEMUX_H__
#include <gst/gst.h>
-#include <gst/base/gstadapter.h>
#include "m3u8.h"
-#include "gstfragmented.h"
-#include <gst/uridownloader/gsturidownloader.h>
+#include <gst/adaptivedemux/gstadaptivedemux.h>
+#if defined(HAVE_OPENSSL)
+#include <openssl/evp.h>
+#elif defined(HAVE_NETTLE)
+#include <nettle/aes.h>
+#include <nettle/cbc.h>
+#elif defined(HAVE_LIBGCRYPT)
+#include <gcrypt.h>
+#endif
G_BEGIN_DECLS
+
#define GST_TYPE_HLS_DEMUX \
(gst_hls_demux_get_type())
#define GST_HLS_DEMUX(obj) \
(G_TYPE_CHECK_CLASS_TYPE((klass),GST_TYPE_HLS_DEMUX))
#define GST_HLS_DEMUX_GET_CLASS(obj) \
(G_TYPE_INSTANCE_GET_CLASS ((obj),GST_TYPE_HLS_DEMUX,GstHLSDemuxClass))
+#define GST_HLS_DEMUX_CAST(obj) \
+ ((GstHLSDemux *)obj)
+
typedef struct _GstHLSDemux GstHLSDemux;
typedef struct _GstHLSDemuxClass GstHLSDemuxClass;
+typedef struct _GstHLSDemuxStream GstHLSDemuxStream;
+typedef struct _GstHLSTSReader GstHLSTSReader;
+
+#define GST_HLS_DEMUX_STREAM_CAST(stream) ((GstHLSDemuxStream *)(stream))
+
+typedef enum {
+ GST_HLS_TSREADER_NONE,
+ GST_HLS_TSREADER_MPEGTS,
+ GST_HLS_TSREADER_ID3
+} GstHLSTSReaderType;
+
+struct _GstHLSTSReader
+{
+ GstHLSTSReaderType rtype;
+ gboolean have_id3;
+
+ gint packet_size;
+ gint pmt_pid;
+ gint pcr_pid;
+
+ GstClockTime last_pcr;
+ GstClockTime first_pcr;
+};
+
+struct _GstHLSDemuxStream
+{
+ GstAdaptiveDemuxStream adaptive_demux_stream;
+
+ GstHLSTSReaderType stream_type;
+
+ GstM3U8 *playlist;
+ gboolean is_primary_playlist;
+
+ gboolean do_typefind; /* Whether we need to typefind the next buffer */
+ GstBuffer *pending_typefind_buffer; /* for collecting data until typefind succeeds */
+
+ GstAdapter *pending_encrypted_data; /* for chunking data into 16 byte multiples for decryption */
+ GstBuffer *pending_decrypted_buffer; /* last decrypted buffer for pkcs7 unpadding.
+ We only know that it is the last at EOS */
+ guint64 current_offset; /* offset we're currently at */
+ gboolean reset_pts;
+#ifdef TIZEN_FEATURE_HLSDEMUX_DISCONT
+ GstClockTime sequence_pos;
+ GstClockTime last_pcr;
+#endif
+
+ /* decryption tooling */
+#if defined(HAVE_OPENSSL)
+# if OPENSSL_VERSION_NUMBER < 0x10100000L
+ EVP_CIPHER_CTX aes_ctx;
+# else
+ EVP_CIPHER_CTX *aes_ctx;
+# endif
+#elif defined(HAVE_NETTLE)
+ struct CBC_CTX (struct aes128_ctx, AES_BLOCK_SIZE) aes_ctx;
+#elif defined(HAVE_LIBGCRYPT)
+ gcry_cipher_hd_t aes_ctx;
+#endif
+
+ gchar *current_key;
+ guint8 *current_iv;
+
+ /* Accumulator for reading PAT/PMT/PCR from
+ * the stream so we can set timestamps/segments
+ * and switch cleanly */
+ GstBuffer *pending_pcr_buffer;
+#ifdef TIZEN_FEATURE_HLSDEMUX_DISCONT_SEQUENCE
+ gint failed_count;
+#endif
+ GstHLSTSReader tsreader;
+};
+
+typedef struct {
+ guint8 data[16];
+} GstHLSKey;
/**
* GstHLSDemux:
*/
struct _GstHLSDemux
{
- GstBin parent;
+ GstAdaptiveDemux parent;
- GstPad *sinkpad;
- GstPad *srcpad;
gint srcpad_counter;
- gboolean have_group_id;
- guint group_id;
+ /* Decryption key cache: url => GstHLSKey */
+ GHashTable *keys;
+ GMutex keys_lock;
- GstBuffer *playlist;
- GstCaps *input_caps;
- GstUriDownloader *downloader;
- gchar *uri; /* Original playlist URI */
- GstM3U8Client *client; /* M3U8 client */
- gboolean do_typefind; /* Whether we need to typefind the next buffer */
+ /* FIXME: check locking, protected automatically by manifest_lock already? */
+ /* The master playlist with the available variant streams */
+ GstHLSMasterPlaylist *master;
+
+ GstHLSVariantStream *current_variant;
+ /* The previous variant, used to transition streams over */
+ GstHLSVariantStream *previous_variant;
- /* Properties */
- guint fragments_cache; /* number of fragments needed to be cached to start playing */
- gfloat bitrate_limit; /* limit of the available bitrate to use */
- guint connection_speed; /* Network connection speed in kbps (0 = unknown) */
-
- /* Streaming task */
- GstTask *stream_task;
- GRecMutex stream_lock;
- gboolean stop_stream_task;
- GMutex download_lock; /* Used for protecting queue and the two conds */
- GCond download_cond; /* Signalled when something is added to the queue */
- gboolean end_of_playlist;
- gint download_failed_count;
- gint64 next_download;
-
- /* Updates task */
- GstTask *updates_task;
- GRecMutex updates_lock;
- gint64 next_update; /* Time of the next update */
- gboolean stop_updates_task;
- GMutex updates_timed_lock;
- GCond updates_timed_cond; /* Signalled when the playlist should be updated */
-
- /* Position in the stream */
- GstSegment segment;
- gboolean need_segment;
- gboolean discont;
-
- /* Cache for the last key */
- gchar *key_url;
- GstFragment *key_fragment;
-
- /* Current download rate (bps) */
- gint current_download_rate;
-
- /* fragment download tooling */
- GstElement *src;
- GMutex fragment_download_lock;
- GCond fragment_download_cond;
- GstClockTime current_timestamp;
- gboolean starting_fragment;
+ gboolean streams_aware;
};
struct _GstHLSDemuxClass
{
- GstBinClass parent_class;
+ GstAdaptiveDemuxClass parent_class;
};
+
+void gst_hlsdemux_tsreader_init (GstHLSTSReader *r);
+void gst_hlsdemux_tsreader_set_type (GstHLSTSReader *r, GstHLSTSReaderType rtype);
+
+gboolean gst_hlsdemux_tsreader_find_pcrs (GstHLSTSReader *r, GstBuffer **buffer,
+ GstClockTime *first_pcr, GstClockTime *last_pcr, GstTagList **tags);
+
GType gst_hls_demux_get_type (void);
G_END_DECLS