diff --git a/gst/isomp4/atoms.c b/gst/isomp4/atoms.c index 5aebd6b69d..9aca106aad 100644 --- a/gst/isomp4/atoms.c +++ b/gst/isomp4/atoms.c @@ -2742,6 +2742,56 @@ atom_moov_chunks_add_offset (AtomMOOV * moov, guint32 offset) } } +void +atom_trak_update_bitrates (AtomTRAK * trak, guint32 avg_bitrate, + guint32 max_bitrate) +{ + AtomESDS *esds = NULL; + AtomSTSD *stsd; + GList *iter; + GList *extensioniter = NULL; + + g_return_if_fail (trak != NULL); + + if (avg_bitrate == 0 && max_bitrate == 0) + return; + + stsd = &trak->mdia.minf.stbl.stsd; + for (iter = stsd->entries; iter; iter = g_list_next (iter)) { + SampleTableEntry *entry = iter->data; + + switch (entry->kind) { + case AUDIO:{ + SampleTableEntryMP4A *audioentry = (SampleTableEntryMP4A *) entry; + extensioniter = audioentry->extension_atoms; + break; + } + case VIDEO:{ + SampleTableEntryMP4V *videoentry = (SampleTableEntryMP4V *) entry; + extensioniter = videoentry->extension_atoms; + break; + } + default: + break; + } + } + + for (; extensioniter; extensioniter = g_list_next (extensioniter)) { + AtomInfo *atominfo = extensioniter->data; + if (atominfo->atom->type == FOURCC_esds) { + esds = (AtomESDS *) atominfo->atom; + break; + } + } + + if (esds) { + if (avg_bitrate && esds->es.dec_conf_desc.avg_bitrate == 0) + esds->es.dec_conf_desc.avg_bitrate = avg_bitrate; + if (max_bitrate && esds->es.dec_conf_desc.max_bitrate == 0) + esds->es.dec_conf_desc.max_bitrate = max_bitrate; + } +} + /* * Meta tags functions */ diff --git a/gst/isomp4/atoms.h b/gst/isomp4/atoms.h index 5aeb5f8f65..20ea141723 100644 --- a/gst/isomp4/atoms.h +++ b/gst/isomp4/atoms.h @@ -906,6 +906,9 @@ void atom_trak_set_video_type (AtomTRAK * trak, AtomsContext * context, VisualSampleEntry * entry, guint32 rate, GList * ext_atoms_list); +void atom_trak_update_bitrates (AtomTRAK * trak, guint32 avg_bitrate, + guint32 max_bitrate); + AtomInfo * build_codec_data_extension (guint32 fourcc, const GstBuffer * codec_data); AtomInfo * build_mov_aac_extension (AtomTRAK * trak, const GstBuffer * codec_data, guint32 avg_bitrate, guint32 max_bitrate); diff --git a/gst/isomp4/gstqtmux.c b/gst/isomp4/gstqtmux.c index fe6bf85429..769578d703 100644 --- a/gst/isomp4/gstqtmux.c +++ b/gst/isomp4/gstqtmux.c @@ -367,6 +367,8 @@ gst_qt_mux_pad_reset (GstQTPad * qtpad) qtpad->avg_bitrate = 0; qtpad->max_bitrate = 0; qtpad->ts_n_entries = 0; + qtpad->total_duration = 0; + qtpad->total_bytes = 0; qtpad->buf_head = 0; qtpad->buf_tail = 0; @@ -1769,6 +1771,20 @@ gst_qt_mux_stop_file (GstQTMux * qtmux) qtpad->last_dts > first_ts)) { first_ts = qtpad->last_dts; } + + /* update average bitrate of streams if needed */ + { + guint32 avgbitrate = 0; + guint32 maxbitrate = qtpad->max_bitrate; + + if (qtpad->avg_bitrate) + avgbitrate = qtpad->avg_bitrate; + else if (qtpad->total_duration > 0) + avgbitrate = (guint32) gst_util_uint64_scale_round (qtpad->total_bytes, + 8 * GST_SECOND, qtpad->total_duration); + + atom_trak_update_bitrates (qtpad->trak, avgbitrate, maxbitrate); + } } if (qtmux->fragment_sequence) { @@ -2291,6 +2307,12 @@ again: duration = MAX (duration, ts); } + /* for computing the avg bitrate */ + if (G_LIKELY (last_buf)) { + pad->total_bytes += GST_BUFFER_SIZE (last_buf); + pad->total_duration += duration; + } + gst_buffer_replace (&pad->last_buf, buf); last_dts = gst_util_uint64_scale_round (pad->last_dts, diff --git a/gst/isomp4/gstqtmux.h b/gst/isomp4/gstqtmux.h index 3a2cb492fe..1851973e56 100644 --- a/gst/isomp4/gstqtmux.h +++ b/gst/isomp4/gstqtmux.h @@ -97,6 +97,10 @@ struct _GstQTPad /* bitrates */ guint32 avg_bitrate, max_bitrate; + /* for avg bitrate calculation */ + guint64 total_bytes; + guint64 total_duration; + GstBuffer *last_buf; /* dts of last_buf */ GstClockTime last_dts;