avimux: fix indx duration for PCM audio

GstBuffers for PCM audio usually contains more than
1 sample, we need to get the total number of samples to set
the indx duration.
This commit is contained in:
Thiago Santos 2009-11-04 16:10:23 -03:00
parent 8dd78015f1
commit 831b1e958a
2 changed files with 49 additions and 6 deletions

View file

@ -342,6 +342,8 @@ gst_avi_mux_pad_reset (GstAviPad * avipad, gboolean free)
} else { } else {
GstAviAudioPad *audpad = (GstAviAudioPad *) avipad; GstAviAudioPad *audpad = (GstAviAudioPad *) avipad;
audpad->samples = 0;
avipad->hdr.type = GST_MAKE_FOURCC ('a', 'u', 'd', 's'); avipad->hdr.type = GST_MAKE_FOURCC ('a', 'u', 'd', 's');
if (audpad->auds_codec_data) { if (audpad->auds_codec_data) {
gst_buffer_unref (audpad->auds_codec_data); gst_buffer_unref (audpad->auds_codec_data);
@ -1467,8 +1469,8 @@ gst_avi_mux_riff_get_header (GstAviPad * avipad, guint32 video_frame_size)
/* write an odml index chunk in the movi list */ /* write an odml index chunk in the movi list */
static GstFlowReturn static GstFlowReturn
gst_avi_mux_write_avix_index (GstAviMux * avimux, gchar * code, gst_avi_mux_write_avix_index (GstAviMux * avimux, GstAviPad * avipad,
gchar * chunk, gst_avi_superindex_entry * super_index, gchar * code, gchar * chunk, gst_avi_superindex_entry * super_index,
gint * super_index_count) gint * super_index_count)
{ {
GstFlowReturn res; GstFlowReturn res;
@ -1477,6 +1479,17 @@ gst_avi_mux_write_avix_index (GstAviMux * avimux, gchar * code,
gst_riff_index_entry *entry; gst_riff_index_entry *entry;
gint i; gint i;
guint32 size, entry_count; guint32 size, entry_count;
gboolean is_pcm = FALSE;
guint32 pcm_samples = 0;
/* check if it is pcm */
if (avipad && !avipad->is_video) {
GstAviAudioPad *audiopad = (GstAviAudioPad *) avipad;
if (audiopad->auds.format == GST_RIFF_WAVE_FORMAT_PCM) {
pcm_samples = audiopad->samples;
is_pcm = TRUE;
}
}
/* allocate the maximum possible */ /* allocate the maximum possible */
buffer = gst_buffer_new_and_alloc (32 + 8 * avimux->idx_index); buffer = gst_buffer_new_and_alloc (32 + 8 * avimux->idx_index);
@ -1528,7 +1541,11 @@ gst_avi_mux_write_avix_index (GstAviMux * avimux, gchar * code,
i = *super_index_count; i = *super_index_count;
super_index[i].offset = GUINT64_TO_LE (avimux->total_data); super_index[i].offset = GUINT64_TO_LE (avimux->total_data);
super_index[i].size = GUINT32_TO_LE (size); super_index[i].size = GUINT32_TO_LE (size);
if (is_pcm) {
super_index[i].duration = GUINT32_TO_LE (pcm_samples);
} else {
super_index[i].duration = GUINT32_TO_LE (entry_count); super_index[i].duration = GUINT32_TO_LE (entry_count);
}
(*super_index_count)++; (*super_index_count)++;
} else } else
GST_WARNING_OBJECT (avimux, "No more room in superindex of stream %s", GST_WARNING_OBJECT (avimux, "No more room in superindex of stream %s",
@ -1547,15 +1564,26 @@ gst_avi_mux_write_avix_index (GstAviMux * avimux, gchar * code,
/* some other usable functions (thankyou xawtv ;-) ) */ /* some other usable functions (thankyou xawtv ;-) ) */
static void static void
gst_avi_mux_add_index (GstAviMux * avimux, gchar * code, guint32 flags, gst_avi_mux_add_index (GstAviMux * avimux, GstAviPad * avipad, guint32 flags,
guint32 size) guint32 size)
{ {
gchar *code = avipad->tag;
if (avimux->idx_index == avimux->idx_count) { if (avimux->idx_index == avimux->idx_count) {
avimux->idx_count += 256; avimux->idx_count += 256;
avimux->idx = avimux->idx =
g_realloc (avimux->idx, g_realloc (avimux->idx,
avimux->idx_count * sizeof (gst_riff_index_entry)); avimux->idx_count * sizeof (gst_riff_index_entry));
} }
/* in case of pcm audio, we need to count the number of samples for
* putting in the indx entries */
if (!avipad->is_video) {
GstAviAudioPad *audiopad = (GstAviAudioPad *) avipad;
if (audiopad->auds.format == GST_RIFF_WAVE_FORMAT_PCM) {
audiopad->samples += size / audiopad->auds.blockalign;
}
}
memcpy (&(avimux->idx[avimux->idx_index].id), code, 4); memcpy (&(avimux->idx[avimux->idx_index].id), code, 4);
avimux->idx[avimux->idx_index].flags = GUINT32_TO_LE (flags); avimux->idx[avimux->idx_index].flags = GUINT32_TO_LE (flags);
avimux->idx[avimux->idx_index].offset = GUINT32_TO_LE (avimux->idx_offset); avimux->idx[avimux->idx_index].offset = GUINT32_TO_LE (avimux->idx_offset);
@ -1615,7 +1643,7 @@ gst_avi_mux_bigfile (GstAviMux * avimux, gboolean last)
node = node->next; node = node->next;
res = gst_avi_mux_write_avix_index (avimux, avipad->tag, res = gst_avi_mux_write_avix_index (avimux, avipad, avipad->tag,
avipad->idx_tag, avipad->idx, &avipad->idx_index); avipad->idx_tag, avipad->idx, &avipad->idx_index);
if (res != GST_FLOW_OK) if (res != GST_FLOW_OK)
return res; return res;
@ -1657,6 +1685,15 @@ gst_avi_mux_bigfile (GstAviMux * avimux, gboolean last)
avimux->numx_frames = 0; avimux->numx_frames = 0;
avimux->datax_size = 4; /* movi tag */ avimux->datax_size = 4; /* movi tag */
avimux->idx_index = 0; avimux->idx_index = 0;
node = avimux->sinkpads;
while (node) {
GstAviPad *avipad = (GstAviPad *) node->data;
node = node->next;
if (!avipad->is_video) {
GstAviAudioPad *audiopad = (GstAviAudioPad *) avipad;
audiopad->samples = 0;
}
}
header = gst_avi_mux_riff_get_avix_header (0); header = gst_avi_mux_riff_get_avix_header (0);
avimux->total_data += GST_BUFFER_SIZE (header); avimux->total_data += GST_BUFFER_SIZE (header);
@ -1946,7 +1983,7 @@ gst_avi_mux_do_buffer (GstAviMux * avimux, GstAviPad * avipad)
audpad->audio_time += GST_BUFFER_DURATION (data); audpad->audio_time += GST_BUFFER_DURATION (data);
} }
gst_avi_mux_add_index (avimux, avipad->tag, flags, GST_BUFFER_SIZE (data)); gst_avi_mux_add_index (avimux, avipad, flags, GST_BUFFER_SIZE (data));
/* prepare buffers for sending */ /* prepare buffers for sending */
gst_buffer_set_caps (header, GST_PAD_CAPS (avimux->srcpad)); gst_buffer_set_caps (header, GST_PAD_CAPS (avimux->srcpad));

View file

@ -115,6 +115,12 @@ typedef struct _GstAviAudioPad {
/* audio info for bps calculation */ /* audio info for bps calculation */
guint32 audio_size; guint32 audio_size;
guint64 audio_time; guint64 audio_time;
/* counts the number of samples to put in indx chunk
* useful for raw audio where usually there are more than
* 1 sample in each GstBuffer */
gint samples;
/* extra data */ /* extra data */
GstBuffer *auds_codec_data; GstBuffer *auds_codec_data;
} GstAviAudioPad; } GstAviAudioPad;