gstreamer/ext/dash/gstdashdemux.h

161 lines
4.7 KiB
C
Raw Normal View History

2013-05-08 14:13:32 +00:00
/*
* DASH demux plugin for GStreamer
*
* gstdashdemux.h
*
* Copyright (C) 2012 Orange
* Authors:
* David Corvoysier <david.corvoysier@orange.com>
* Hamid Zakari <hamid.zakari@gmail.com>
*
* Copyright (C) 2013 Smart TV Alliance
* Author: Thiago Sousa Santos <thiago.sousa.santos@collabora.com>, Collabora Ltd.
*
2013-05-08 14:13:32 +00:00
* 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.1 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
2012-09-28 10:55:27 +00:00
* License along with this library (COPYING); if not, write to the
2013-05-08 14:13:32 +00:00
* Free Software Foundation, Inc., 59 Temple Place - Suite 330,
* Boston, MA 02111-1307, USA.
*/
#ifndef __GST_DASH_DEMUX_H__
#define __GST_DASH_DEMUX_H__
#include <gst/gst.h>
2014-08-26 19:45:46 +00:00
#include <gst/adaptivedemux/gstadaptivedemux.h>
2013-05-08 14:13:32 +00:00
#include <gst/base/gstadapter.h>
#include <gst/base/gstdataqueue.h>
2013-05-08 14:13:32 +00:00
#include "gstmpdparser.h"
#include <gst/isoff/gstisoff.h>
#include <gst/uridownloader/gsturidownloader.h>
2013-05-08 14:13:32 +00:00
G_BEGIN_DECLS
#define GST_TYPE_DASH_DEMUX \
(gst_dash_demux_get_type())
#define GST_DASH_DEMUX(obj) \
(G_TYPE_CHECK_INSTANCE_CAST((obj),GST_TYPE_DASH_DEMUX,GstDashDemux))
#define GST_DASH_DEMUX_CLASS(klass) \
(G_TYPE_CHECK_CLASS_CAST((klass),GST_TYPE_DASH_DEMUX,GstDashDemuxClass))
#define GST_IS_DASH_DEMUX(obj) \
(G_TYPE_CHECK_INSTANCE_TYPE((obj),GST_TYPE_DASH_DEMUX))
#define GST_IS_DASH_DEMUX_CLASS(klass) \
(G_TYPE_CHECK_CLASS_TYPE((klass),GST_TYPE_DASH_DEMUX))
#define GST_DASH_DEMUX_CAST(obj) \
((GstDashDemux *)obj)
dashdemux: add support for UTCTiming elements for clock drift compensation Unless the DASH client can compensate for the difference between its clock and the clock used by the server, the client might request fragments that either not yet on the server or fragments that have already been expired from the server. This is an issue because these requests can propagate all the way back to the origin ISO/IEC 23009-1:2014/Amd 1 [PDAM1] defines a new UTCTiming element to allow a DASH client to track the clock used by the server generating the DASH stream. Multiple UTCTiming elements might be present, to indicate support for multiple methods of UTC time gathering. Each element can contain a white space separated list of URLs that can be contacted to discover the UTC time from the server's perspective. This commit provides parsing of UTCTiming elements, unit tests of this parsing and a function to poll a time server. This function supports the following methods: urn:mpeg:dash:utc:ntp:2014 urn:mpeg:dash:utc:http-xsdate:2014 urn:mpeg:dash:utc:http-iso:2014 urn:mpeg:dash:utc:http-ntp:2014 The manifest update task is used to poll the clock time server, to save having to create a new thread. When choosing the starting fragment number and when waiting for a fragment to become available, the difference between the server's idea of UTC and the client's idea of UTC is taken into account. For example, if the server's time is behind the client's idea of UTC, we wait for longer before requesting a fragment [PDAM1]: http://www.iso.org/iso/home/store/catalogue_tc/catalogue_detail.htm?csnumber=66068 dashdemux: support NTP time servers in UTCTiming elements Use the gst_ntp_clock to support the use of an NTP server. https://bugzilla.gnome.org/show_bug.cgi?id=752413
2015-07-15 10:56:13 +00:00
typedef struct _GstDashDemuxClockDrift GstDashDemuxClockDrift;
typedef struct _GstDashDemuxStream GstDashDemuxStream;
2013-05-08 14:13:32 +00:00
typedef struct _GstDashDemux GstDashDemux;
typedef struct _GstDashDemuxClass GstDashDemuxClass;
struct _GstDashDemuxStream
{
2014-08-26 19:45:46 +00:00
GstAdaptiveDemuxStream parent;
gint index;
GstActiveStream *active_stream;
GstMediaFragmentInfo current_fragment;
/* index parsing */
GstSidxParser sidx_parser;
GstClockTime sidx_position;
gint64 sidx_base_offset;
gboolean allow_sidx;
GstClockTime pending_seek_ts;
GstAdapter *adapter;
/* current offset of the first byte in the adapter / last byte we pushed or
* dropped*/
guint64 current_offset;
/* index = 1, header = 2, data = 3 */
guint current_index_header_or_data;
/* ISOBMFF box parsing */
gboolean is_isobmff;
struct {
/* index = 1, header = 2, data = 3 */
guint32 current_fourcc;
guint64 current_start_offset;
guint64 current_size;
} isobmff_parser;
GstMoofBox *moof;
guint64 moof_offset, moof_size;
GArray *moof_sync_samples;
guint current_sync_sample;
guint64 moof_average_size;
guint64 keyframe_average_size;
guint64 keyframe_average_distance;
gboolean first_sync_sample_after_moof, first_sync_sample_always_after_moof;
dashdemux: Improve key-unit trick mode downloading When dealing with key-unit trick mode downloads, the goal is to provide the best "Quality of Experience". This is achieved by: 1) maximizing the number of frames displayed per second 2) avoiding "stalling" as much as possible (i.e. not downloading and decoding frames fast enough) This implementation achives this by: 1) Knowing very precisely the current keyframe being download (i.e more accurate than at the fragment level which might contain more than one keyfram). This is the new "actual_position" variable introduced by this commit 2) Knowing the position of downstream (provided by QoS and stored in the adaptivedemuxstream qos_earliest_time variable) 3) Knowing how long it takes to request and fully download a keyframe (the average_download_time variable) Taking those 3 variables into account, whenever a keyframe has been pushed downstream we calculate a "target time" (target_time variable) which is the ideal next keyframe time to request so that: 1) It will be requested/downloaded/demuxed/decoded in time to be displayed without being too late 2) It will not be too far ahead that it would cause too few frames per second to be displayed. How far ahead we will request is inversily proportional to how close the actual position (actual_position) is from the downstream position (qos_earliest_time). The more is buffered between the source and the sink, the "closer" the target time will be, and therefore the more frames per seconds will be displayed (up to the limit of keyframes_per_second * absolute_rate).
2017-01-12 14:54:37 +00:00
/* Internal position value, at the keyframe/entry level */
GstClockTime actual_position;
/* Timestamp of the beginning of the current fragment */
GstClockTime current_fragment_timestamp;
GstClockTime current_fragment_duration;
GstClockTime current_fragment_keyframe_distance;
dashdemux: Improve key-unit trick mode downloading When dealing with key-unit trick mode downloads, the goal is to provide the best "Quality of Experience". This is achieved by: 1) maximizing the number of frames displayed per second 2) avoiding "stalling" as much as possible (i.e. not downloading and decoding frames fast enough) This implementation achives this by: 1) Knowing very precisely the current keyframe being download (i.e more accurate than at the fragment level which might contain more than one keyfram). This is the new "actual_position" variable introduced by this commit 2) Knowing the position of downstream (provided by QoS and stored in the adaptivedemuxstream qos_earliest_time variable) 3) Knowing how long it takes to request and fully download a keyframe (the average_download_time variable) Taking those 3 variables into account, whenever a keyframe has been pushed downstream we calculate a "target time" (target_time variable) which is the ideal next keyframe time to request so that: 1) It will be requested/downloaded/demuxed/decoded in time to be displayed without being too late 2) It will not be too far ahead that it would cause too few frames per second to be displayed. How far ahead we will request is inversily proportional to how close the actual position (actual_position) is from the downstream position (qos_earliest_time). The more is buffered between the source and the sink, the "closer" the target time will be, and therefore the more frames per seconds will be displayed (up to the limit of keyframes_per_second * absolute_rate).
2017-01-12 14:54:37 +00:00
/* Average keyframe download time (only in trickmode-key-units) */
GstClockTime average_download_time;
dashdemux: Improve key-unit trick mode downloading When dealing with key-unit trick mode downloads, the goal is to provide the best "Quality of Experience". This is achieved by: 1) maximizing the number of frames displayed per second 2) avoiding "stalling" as much as possible (i.e. not downloading and decoding frames fast enough) This implementation achives this by: 1) Knowing very precisely the current keyframe being download (i.e more accurate than at the fragment level which might contain more than one keyfram). This is the new "actual_position" variable introduced by this commit 2) Knowing the position of downstream (provided by QoS and stored in the adaptivedemuxstream qos_earliest_time variable) 3) Knowing how long it takes to request and fully download a keyframe (the average_download_time variable) Taking those 3 variables into account, whenever a keyframe has been pushed downstream we calculate a "target time" (target_time variable) which is the ideal next keyframe time to request so that: 1) It will be requested/downloaded/demuxed/decoded in time to be displayed without being too late 2) It will not be too far ahead that it would cause too few frames per second to be displayed. How far ahead we will request is inversily proportional to how close the actual position (actual_position) is from the downstream position (qos_earliest_time). The more is buffered between the source and the sink, the "closer" the target time will be, and therefore the more frames per seconds will be displayed (up to the limit of keyframes_per_second * absolute_rate).
2017-01-12 14:54:37 +00:00
/* Cached target time (only in trickmode-key-units) */
GstClockTime target_time;
/* Average skip-ahead time (only in trickmode-key-units) */
GstClockTime average_skip_size;
};
2013-05-08 14:13:32 +00:00
/**
* GstDashDemux:
*
* Opaque #GstDashDemux data structure.
*/
struct _GstDashDemux
{
2014-08-26 19:45:46 +00:00
GstAdaptiveDemux parent;
GSList *next_periods;
2013-05-08 14:13:32 +00:00
GstMpdClient *client; /* MPD client */
GMutex client_lock;
dashdemux: add support for UTCTiming elements for clock drift compensation Unless the DASH client can compensate for the difference between its clock and the clock used by the server, the client might request fragments that either not yet on the server or fragments that have already been expired from the server. This is an issue because these requests can propagate all the way back to the origin ISO/IEC 23009-1:2014/Amd 1 [PDAM1] defines a new UTCTiming element to allow a DASH client to track the clock used by the server generating the DASH stream. Multiple UTCTiming elements might be present, to indicate support for multiple methods of UTC time gathering. Each element can contain a white space separated list of URLs that can be contacted to discover the UTC time from the server's perspective. This commit provides parsing of UTCTiming elements, unit tests of this parsing and a function to poll a time server. This function supports the following methods: urn:mpeg:dash:utc:ntp:2014 urn:mpeg:dash:utc:http-xsdate:2014 urn:mpeg:dash:utc:http-iso:2014 urn:mpeg:dash:utc:http-ntp:2014 The manifest update task is used to poll the clock time server, to save having to create a new thread. When choosing the starting fragment number and when waiting for a fragment to become available, the difference between the server's idea of UTC and the client's idea of UTC is taken into account. For example, if the server's time is behind the client's idea of UTC, we wait for longer before requesting a fragment [PDAM1]: http://www.iso.org/iso/home/store/catalogue_tc/catalogue_detail.htm?csnumber=66068 dashdemux: support NTP time servers in UTCTiming elements Use the gst_ntp_clock to support the use of an NTP server. https://bugzilla.gnome.org/show_bug.cgi?id=752413
2015-07-15 10:56:13 +00:00
GstDashDemuxClockDrift *clock_drift;
gboolean end_of_period;
gboolean end_of_manifest;
2013-05-08 14:13:32 +00:00
/* Properties */
GstClockTime max_buffering_time; /* Maximum buffering time accumulated during playback */
guint max_bitrate; /* max of bitrate supported by target decoder */
gint max_video_width, max_video_height;
gint max_video_framerate_n, max_video_framerate_d;
gchar* default_presentation_delay; /* presentation time delay if MPD@suggestedPresentationDelay is not present */
gint n_audio_streams;
gint n_video_streams;
gint n_subtitle_streams;
gboolean trickmode_no_audio;
gboolean allow_trickmode_key_units;
2013-05-08 14:13:32 +00:00
};
struct _GstDashDemuxClass
{
2014-08-26 19:45:46 +00:00
GstAdaptiveDemuxClass parent_class;
2013-05-08 14:13:32 +00:00
};
GType gst_dash_demux_get_type (void);
G_END_DECLS
#endif /* __GST_DASH_DEMUX_H__ */