gstqtmux.h 9.46 KB
Newer Older
1
/* Quicktime muxer plugin for GStreamer
2
 * Copyright (C) 2008-2010 Thiago Santos <thiagoss@embedded.ufcg.edu.br>
3 4 5 6 7 8 9 10 11 12 13 14 15
 *
 * 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
Tim-Philipp Müller's avatar
Tim-Philipp Müller committed
16 17
 * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
 * Boston, MA 02110-1301, USA.
18
 */
19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41
/*
 * Unless otherwise indicated, Source Code is licensed under MIT license.
 * See further explanation attached in License Statement (distributed in the file
 * LICENSE).
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy of
 * this software and associated documentation files (the "Software"), to deal in
 * the Software without restriction, including without limitation the rights to
 * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
 * of the Software, and to permit persons to whom the Software is furnished to do
 * so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in all
 * copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
 * SOFTWARE.
 */
42 43 44 45 46

#ifndef __GST_QT_MUX_H__
#define __GST_QT_MUX_H__

#include <gst/gst.h>
47
#include <gst/base/gstcollectpads.h>
48 49 50

#include "fourcc.h"
#include "atoms.h"
51
#include "atomsrecovery.h"
52 53 54 55 56 57 58 59 60 61 62 63 64 65
#include "gstqtmuxmap.h"

G_BEGIN_DECLS

#define GST_TYPE_QT_MUX (gst_qt_mux_get_type())
#define GST_QT_MUX(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj),GST_TYPE_QT_MUX, GstQTMux))
#define GST_QT_MUX_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass),GST_TYPE_QT_MUX, GstQTMux))
#define GST_IS_QT_MUX(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj),GST_TYPE_QT_MUX))
#define GST_IS_QT_MUX_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass),GST_TYPE_QT_MUX))
#define GST_QT_MUX_CAST(obj) ((GstQTMux*)(obj))


typedef struct _GstQTMux GstQTMux;
typedef struct _GstQTMuxClass GstQTMuxClass;
Thiago Santos's avatar
Thiago Santos committed
66
typedef struct _GstQTPad GstQTPad;
67

Thiago Santos's avatar
Thiago Santos committed
68 69 70 71 72 73 74 75 76 77 78 79 80
/*
 * GstQTPadPrepareBufferFunc
 *
 * Receives a buffer (takes ref) and returns a new buffer that should
 * replace the passed one.
 *
 * Useful for when the pad/datatype needs some manipulation before
 * being muxed. (Originally added for image/x-jpc support, for which buffers
 * need to be wrapped into a isom box)
 */
typedef GstBuffer * (*GstQTPadPrepareBufferFunc) (GstQTPad * pad,
    GstBuffer * buf, GstQTMux * qtmux);

81
typedef gboolean (*GstQTPadSetCapsFunc) (GstQTPad * pad, GstCaps * caps);
82
typedef GstBuffer * (*GstQTPadCreateEmptyBufferFunc) (GstQTPad * pad, gint64 duration);
83

84 85
#define QTMUX_NO_OF_TS   10

Thiago Santos's avatar
Thiago Santos committed
86
struct _GstQTPad
87
{
88
  GstCollectData collect;       /* we extend the CollectData */
89 90 91 92 93 94 95 96 97

  /* fourcc id of stream */
  guint32 fourcc;
  /* whether using format that have out of order buffers */
  gboolean is_out_of_order;
  /* if not 0, track with constant sized samples, e.g. raw audio */
  guint sample_size;
  /* make sync table entry */
  gboolean sync;
98 99 100
  /* if it is a sparse stream
   * (meaning we can't use PTS differences to compute duration) */
  gboolean sparse;
101 102
  /* bitrates */
  guint32 avg_bitrate, max_bitrate;
103

104 105 106 107
  /* for avg bitrate calculation */
  guint64 total_bytes;
  guint64 total_duration;

108 109 110 111
  GstBuffer *last_buf;
  /* dts of last_buf */
  GstClockTime last_dts;

112 113 114
  /* This is compensate for CTTS */
  GstClockTime dts_adjustment;

Thiago Santos's avatar
Thiago Santos committed
115 116 117
  /* store the first timestamp for comparing with other streams and
   * know if there are late streams */
  GstClockTime first_ts;
118 119
  GstClockTime first_dts;

120 121 122
  /* all the atom and chunk book-keeping is delegated here
   * unowned/uncounted reference, parent MOOV owns */
  AtomTRAK *trak;
123
  AtomTRAK *tc_trak;
124
  SampleTableEntry *trak_ste;
125 126 127 128 129 130 131
  /* fragmented support */
  /* meta data book-keeping delegated here */
  AtomTRAF *traf;
  /* fragment buffers */
  ATOM_ARRAY (GstBuffer *) fragment_buffers;
  /* running fragment duration */
  gint64 fragment_duration;
132 133
  /* optional fragment index book-keeping */
  AtomTFRA *tfra;
Thiago Santos's avatar
Thiago Santos committed
134

135 136 137
  /* Set when tags are received, cleared when written to moov */
  gboolean tags_changed;

138 139
  GstTagList *tags;

Thiago Santos's avatar
Thiago Santos committed
140 141
  /* if nothing is set, it won't be called */
  GstQTPadPrepareBufferFunc prepare_buf_func;
142
  GstQTPadSetCapsFunc set_caps;
143
  GstQTPadCreateEmptyBufferFunc create_empty_buffer;
144 145 146 147 148

  /* SMPTE timecode */
  GstVideoTimeCode *first_tc;
  GstClockTime first_pts;
  guint64 tc_pos;
Thiago Santos's avatar
Thiago Santos committed
149
};
150 151 152 153 154 155 156 157 158

typedef enum _GstQTMuxState
{
  GST_QT_MUX_STATE_NONE,
  GST_QT_MUX_STATE_STARTED,
  GST_QT_MUX_STATE_DATA,
  GST_QT_MUX_STATE_EOS
} GstQTMuxState;

159 160 161 162
typedef enum _GstQtMuxMode {
    GST_QT_MUX_MODE_MOOV_AT_END,
    GST_QT_MUX_MODE_FRAGMENTED,
    GST_QT_MUX_MODE_FRAGMENTED_STREAMABLE,
163 164
    GST_QT_MUX_MODE_FAST_START,
    GST_QT_MUX_MODE_ROBUST_RECORDING
165 166
} GstQtMuxMode;

167 168 169 170 171
struct _GstQTMux
{
  GstElement element;

  GstPad *srcpad;
172
  GstCollectPads *collect;
173
  GSList *sinkpads;
174 175 176 177

  /* state */
  GstQTMuxState state;

178 179 180 181 182
  /* Mux mode, inferred from property
   * set in gst_qt_mux_start_file() */
  GstQtMuxMode mux_mode;

  /* size of header (prefix, atoms (ftyp, possibly moov, mdat header)) */
183
  guint64 header_size;
184
  /* accumulated size of raw media data (not including mdat header) */
185
  guint64 mdat_size;
186 187 188 189 190
  /* position of the moov (for fragmented mode) or reserved moov atom
   * area (for robust-muxing mode) */
  guint64 moov_pos;
  /* position of mdat atom header (for later updating of size) in
   * moov-at-end, fragmented and robust-muxing modes */
191 192
  guint64 mdat_pos;

Thiago Santos's avatar
Thiago Santos committed
193 194 195
  /* keep track of the largest chunk to fine-tune brands */
  GstClockTime longest_chunk;

196 197 198 199 200
  /* Earliest timestamp across all pads/traks */
  GstClockTime first_ts;
  /* Last DTS across all pads (= duration) */
  GstClockTime last_dts;

201 202 203 204 205 206
  /* Last pad we used for writing the current chunk */
  GstQTPad *current_pad;
  guint64 current_chunk_size;
  GstClockTime current_chunk_duration;
  guint64 current_chunk_offset;

207 208 209 210
  /* atom helper objects */
  AtomsContext *context;
  AtomFTYP *ftyp;
  AtomMOOV *moov;
211 212
  GSList *extra_atoms; /* list of extra top-level atoms (e.g. UUID for xmp)
                        * Stored as AtomInfo structs */
213

214 215 216
  /* Set when tags are received, cleared when written to moov */
  gboolean tags_changed;

217 218 219
  /* fragmented file index */
  AtomMFRA *mfra;

220 221 222
  /* fast start */
  FILE *fast_start_file;

223 224 225
  /* moov recovery */
  FILE *moov_recov_file;

226 227 228
  /* fragment sequence */
  guint32 fragment_sequence;

229 230
  /* properties */
  guint32 timescale;
231
  guint32 trak_timescale;
232 233
  AtomsTreeFlavor flavor;
  gboolean fast_start;
234
  gboolean guess_pts;
235
#ifndef GST_REMOVE_DEPRECATED
236
  gint dts_method;
237
#endif
238
  gchar *fast_start_file_path;
239
  gchar *moov_recov_file_path;
240
  guint32 fragment_duration;
241 242 243
  /* Whether or not to work in 'streamable' mode and not
   * seek to rewrite headers - only valid for fragmented
   * mode. */
244
  gboolean streamable;
245

246 247 248 249 250 251 252
  /* Requested target maximum duration */
  GstClockTime reserved_max_duration;
  /* Estimate of remaining reserved header space (in ns of recording) */
  GstClockTime reserved_duration_remaining;
  /* Multiplier for conversion from reserved_max_duration to bytes */
  guint reserved_bytes_per_sec_per_trak;

253 254 255 256
  guint64 interleave_bytes;
  GstClockTime interleave_time;
  gboolean interleave_bytes_set, interleave_time_set;

257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273
  /* Reserved minimum MOOV size in bytes
   * This is converted from reserved_max_duration
   * using the bytes/trak/sec estimate */
  guint32 reserved_moov_size;
  /* Basic size of the moov (static headers + tags) */
  guint32 base_moov_size;
  /* Size of the most recently generated moov header */
  guint32 last_moov_size;
  /* True if the first moov in the ping-pong buffers
   * is the active one. See gst_qt_mux_robust_recording_rewrite_moov() */
  gboolean reserved_moov_first_active;

  /* Tracking of periodic MOOV updates */
  GstClockTime last_moov_update;
  GstClockTime reserved_moov_update_period;
  GstClockTime muxed_since_last_update;

274
  /* for request pad naming */
275
  guint video_pads, audio_pads, subtitle_pads;
276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291
};

struct _GstQTMuxClass
{
  GstElementClass parent_class;

  GstQTMuxFormat format;
};

/* type register helper struct */
typedef struct _GstQTMuxClassParams
{
  GstQTMuxFormatProp *prop;
  GstCaps *src_caps;
  GstCaps *video_sink_caps;
  GstCaps *audio_sink_caps;
292
  GstCaps *subtitle_sink_caps;
293 294 295 296 297
} GstQTMuxClassParams;

#define GST_QT_MUX_PARAMS_QDATA g_quark_from_static_string("qt-mux-params")

GType gst_qt_mux_get_type (void);
298
gboolean gst_qt_mux_register (GstPlugin * plugin);
299

300 301 302 303 304 305 306 307
/* FIXME: ideally classification tag should be added and
 * registered in gstreamer core gsttaglist
 *
 * this tag is a string in the format: entityfourcc://table_num/content
 * FIXME Shouldn't we add a field for 'language'?
 */
#define GST_TAG_3GP_CLASSIFICATION "classification"

308 309 310
G_END_DECLS

#endif /* __GST_QT_MUX_H__ */