This fixes avimux largely. Sound playback still isn't optimal, but at least we're getting somewhere

Original commit message from CVS:
This fixes avimux largely. Sound playback still isn't optimal, but at least we're getting somewhere
This commit is contained in:
Ronald S. Bultje 2003-06-01 12:23:46 +00:00
parent f11e5be82f
commit 8bad3bd4ac
2 changed files with 65 additions and 78 deletions

View file

@ -248,19 +248,12 @@ gst_avimux_class_init (GstAviMuxClass *klass)
static const GstEventMask * static const GstEventMask *
gst_avimux_get_event_masks (GstPad *pad) gst_avimux_get_event_masks (GstPad *pad)
{ {
static const GstEventMask gst_avimux_src_event_masks[] = {
{ GST_EVENT_NEW_MEDIA, 0 },
{ 0, }
};
static const GstEventMask gst_avimux_sink_event_masks[] = { static const GstEventMask gst_avimux_sink_event_masks[] = {
{ GST_EVENT_EOS, 0 }, { GST_EVENT_EOS, 0 },
{ 0, } { 0, }
}; };
if (GST_PAD_IS_SRC(pad)) return gst_avimux_sink_event_masks;
return gst_avimux_src_event_masks;
else
return gst_avimux_sink_event_masks;
} }
static void static void
@ -271,8 +264,6 @@ gst_avimux_init (GstAviMux *avimux)
gst_element_add_pad (GST_ELEMENT (avimux), avimux->srcpad); gst_element_add_pad (GST_ELEMENT (avimux), avimux->srcpad);
GST_FLAG_SET (GST_ELEMENT(avimux), GST_ELEMENT_EVENT_AWARE); GST_FLAG_SET (GST_ELEMENT(avimux), GST_ELEMENT_EVENT_AWARE);
gst_pad_set_event_function(avimux->srcpad, gst_avimux_handle_event);
gst_pad_set_event_mask_function(avimux->srcpad, gst_avimux_get_event_masks);
avimux->audiosinkpad = NULL; avimux->audiosinkpad = NULL;
avimux->audio_pad_connected = FALSE; avimux->audio_pad_connected = FALSE;
@ -293,6 +284,8 @@ gst_avimux_init (GstAviMux *avimux)
avimux->vids_hdr.type = GST_MAKE_FOURCC('v','i','d','s'); avimux->vids_hdr.type = GST_MAKE_FOURCC('v','i','d','s');
avimux->vids_hdr.rate = 1000000; avimux->vids_hdr.rate = 1000000;
avimux->auds_hdr.type = GST_MAKE_FOURCC('a','u','d','s'); avimux->auds_hdr.type = GST_MAKE_FOURCC('a','u','d','s');
avimux->vids_hdr.quality = 0xFFFFFFFF;
avimux->auds_hdr.quality = 0xFFFFFFFF;
avimux->idx = NULL; avimux->idx = NULL;
@ -300,8 +293,6 @@ gst_avimux_init (GstAviMux *avimux)
avimux->enable_large_avi = TRUE; avimux->enable_large_avi = TRUE;
avimux->framerate = 0;
gst_element_set_loop_function(GST_ELEMENT(avimux), gst_avimux_loop); gst_element_set_loop_function(GST_ELEMENT(avimux), gst_avimux_loop);
} }
@ -453,15 +444,27 @@ gst_avimux_sinkconnect (GstPad *pad, GstCaps *vscaps)
avimux->auds.format = (layer == 3? avimux->auds.format = (layer == 3?
GST_RIFF_WAVE_FORMAT_MPEGL3 : GST_RIFF_WAVE_FORMAT_MPEGL3 :
GST_RIFF_WAVE_FORMAT_MPEGL12); GST_RIFF_WAVE_FORMAT_MPEGL12);
avimux->auds_hdr.scale = avimux->auds_hdr.samplesize = 1; avimux->auds_hdr.scale = avimux->auds_hdr.samplesize =
avimux->auds.blockalign = 1;
avimux->auds_hdr.rate = avimux->auds.av_bps = 0; avimux->auds_hdr.rate = avimux->auds.av_bps = 0;
avimux->auds.size = 16;
/* nobody cares about this valus, but is has to be set (regardless of
* whether the value is correct) */
avimux->auds.channels = 1;
/* we'll request this later on from the earlier pads */
avimux->auds.rate = 0;
goto done; goto done;
} }
else if (!strcmp (mimetype, "application/x-ogg")) else if (!strcmp (mimetype, "application/x-ogg"))
{ {
avimux->auds.format = GST_RIFF_WAVE_FORMAT_VORBIS1; avimux->auds.format = GST_RIFF_WAVE_FORMAT_VORBIS1;
avimux->auds_hdr.scale = avimux->auds_hdr.samplesize = 1; avimux->auds_hdr.scale = avimux->auds_hdr.samplesize =
avimux->auds.blockalign = 1;
avimux->auds_hdr.rate = avimux->auds.av_bps = 0; avimux->auds_hdr.rate = avimux->auds.av_bps = 0;
avimux->auds.size = 16;
/* see above */
avimux->auds.channels = 1;
avimux->auds.rate = 0;
goto done; goto done;
} }
} }
@ -970,6 +973,7 @@ gst_avimux_stop_file (GstAviMux *avimux)
{ {
GstEvent *event; GstEvent *event;
GstBuffer *header; GstBuffer *header;
gdouble framerate = 0.;
/* if bigfile, rewrite header, else write indexes */ /* if bigfile, rewrite header, else write indexes */
if (avimux->video_pad_connected) if (avimux->video_pad_connected)
@ -987,39 +991,50 @@ gst_avimux_stop_file (GstAviMux *avimux)
/* statistics/total_frames/... */ /* statistics/total_frames/... */
avimux->avi_hdr.tot_frames = avimux->num_frames; avimux->avi_hdr.tot_frames = avimux->num_frames;
if (avimux->video_pad_connected) if (avimux->video_pad_connected) {
avimux->vids_hdr.length = avimux->num_frames; avimux->vids_hdr.length = avimux->num_frames;
/* get fps */
framerate = gst_video_frame_rate(GST_PAD_PEER(avimux->videosinkpad));
avimux->vids_hdr.scale = 1000000 / framerate;
}
if (avimux->audio_pad_connected) if (avimux->audio_pad_connected)
{ {
if (avimux->auds_hdr.scale) if (avimux->auds_hdr.scale)
avimux->auds_hdr.length = avimux->audio_size/avimux->auds_hdr.scale; avimux->auds_hdr.length = avimux->audio_size/(avimux->auds.size/8);
else else
avimux->auds_hdr.length = 0; /* urm...? FIXME! ;-) */ avimux->auds_hdr.length = 0; /* urm...? FIXME! ;-) */
/* sampling rate, if known - yes this is a hack */
if (!avimux->auds.rate)
avimux->auds.rate = gst_video_frame_rate(GST_PAD_PEER(avimux->audiosinkpad));
} }
/* set rate and everything having to do with that */ /* set rate and everything having to do with that */
avimux->avi_hdr.us_frame = avimux->vids_hdr.scale = 1000000/avimux->framerate; avimux->avi_hdr.us_frame = avimux->vids_hdr.scale;
avimux->avi_hdr.max_bps = 0; avimux->avi_hdr.max_bps = 0;
if (avimux->audio_pad_connected) { if (avimux->audio_pad_connected) {
/* calculate bps if needed */ /* calculate bps if needed */
if (!avimux->auds.av_bps) { if (!avimux->auds.av_bps) {
avimux->auds.av_bps = GST_SECOND * ((1. * avimux->audio_size) / avimux->audio_time); avimux->auds_hdr.rate = (GST_SECOND * avimux->audio_size) / avimux->audio_time;
avimux->auds_hdr.rate = avimux->auds.av_bps * avimux->auds_hdr.scale; avimux->auds.av_bps = avimux->auds_hdr.rate * avimux->auds_hdr.scale;
} }
avimux->avi_hdr.max_bps += avimux->auds.av_bps; avimux->avi_hdr.max_bps += avimux->auds.av_bps;
} }
if (avimux->video_pad_connected) if (avimux->video_pad_connected) {
avimux->avi_hdr.max_bps += ((avimux->vids.bit_cnt+7)/8) * avimux->avi_hdr.max_bps += ((avimux->vids.bit_cnt+7)/8) *
avimux->framerate * framerate *
avimux->vids.image_size; avimux->vids.image_size;
}
/* seek and rewrite the header */ /* seek and rewrite the header */
header = gst_avimux_riff_get_avi_header(avimux); header = gst_avimux_riff_get_avi_header(avimux);
event = gst_event_new_seek (GST_FORMAT_BYTES | event = gst_event_new_seek (GST_FORMAT_BYTES |
GST_SEEK_METHOD_SET | GST_SEEK_METHOD_SET, 0);
GST_SEEK_FLAG_FLUSH, 0);
gst_pad_send_event(GST_PAD_PEER(avimux->srcpad), event); gst_pad_send_event(GST_PAD_PEER(avimux->srcpad), event);
gst_pad_push(avimux->srcpad, header); gst_pad_push(avimux->srcpad, header);
event = gst_event_new_seek (GST_FORMAT_BYTES |
GST_SEEK_METHOD_SET, avimux->total_data);
avimux->write_header = TRUE; avimux->write_header = TRUE;
} }
@ -1031,7 +1046,7 @@ gst_avimux_restart_file (GstAviMux *avimux)
gst_avimux_stop_file(avimux); gst_avimux_stop_file(avimux);
event = gst_event_new(GST_EVENT_NEW_MEDIA); event = gst_event_new(GST_EVENT_EOS);
gst_pad_send_event(avimux->srcpad, event); gst_pad_send_event(avimux->srcpad, event);
gst_avimux_start_file(avimux); gst_avimux_start_file(avimux);
@ -1049,17 +1064,15 @@ gst_avimux_handle_event (GstPad *pad, GstEvent *event)
type = event ? GST_EVENT_TYPE (event) : GST_EVENT_UNKNOWN; type = event ? GST_EVENT_TYPE (event) : GST_EVENT_UNKNOWN;
switch (type) { switch (type) {
case GST_EVENT_NEW_MEDIA:
avimux->restart = TRUE;
break;
case GST_EVENT_EOS: case GST_EVENT_EOS:
/* is this allright? */ /* is this allright? */
if (pad == avimux->videosinkpad) if (pad == avimux->videosinkpad) {
avimux->video_pad_eos = TRUE; avimux->video_pad_eos = TRUE;
else if (pad == avimux->audiosinkpad) } else if (pad == avimux->audiosinkpad) {
avimux->audio_pad_eos = TRUE; avimux->audio_pad_eos = TRUE;
else } else {
g_warning("Unknown pad for EOS!"); g_warning("Unknown pad for EOS!");
}
break; break;
default: default:
break; break;
@ -1075,47 +1088,33 @@ gst_avimux_fill_queue (GstAviMux *avimux)
{ {
GstBuffer *buffer; GstBuffer *buffer;
if (!avimux->audio_buffer_queue && while (!avimux->audio_buffer_queue &&
avimux->audiosinkpad && avimux->audiosinkpad &&
avimux->audio_pad_connected && avimux->audio_pad_connected &&
GST_PAD_IS_USABLE(avimux->audiosinkpad) && GST_PAD_IS_USABLE(avimux->audiosinkpad) &&
!avimux->audio_pad_eos) !avimux->audio_pad_eos)
{ {
while (1) buffer = gst_pad_pull(avimux->audiosinkpad);
{ if (GST_IS_EVENT(buffer)) {
buffer = gst_pad_pull(avimux->audiosinkpad); gst_avimux_handle_event(avimux->audiosinkpad, GST_EVENT(buffer));
if (GST_IS_EVENT(buffer)) } else {
{ avimux->audio_buffer_queue = buffer;
gst_avimux_handle_event(avimux->audiosinkpad, GST_EVENT(buffer)); break;
}
else
{
avimux->audio_buffer_queue = buffer;
break;
}
} }
} }
if (!avimux->video_buffer_queue && while (!avimux->video_buffer_queue &&
avimux->videosinkpad && avimux->videosinkpad &&
avimux->video_pad_connected && avimux->video_pad_connected &&
GST_PAD_IS_USABLE(avimux->videosinkpad) && GST_PAD_IS_USABLE(avimux->videosinkpad) &&
!avimux->video_pad_eos) !avimux->video_pad_eos)
{ {
while (1) buffer = gst_pad_pull(avimux->videosinkpad);
{ if (GST_IS_EVENT(buffer)) {
buffer = gst_pad_pull(avimux->videosinkpad); gst_avimux_handle_event(avimux->videosinkpad, GST_EVENT(buffer));
if (GST_IS_EVENT(buffer)) } else {
{ avimux->video_buffer_queue = buffer;
gst_avimux_handle_event(avimux->videosinkpad, GST_EVENT(buffer)); break;
}
else
{
avimux->video_buffer_queue = buffer;
if (avimux->framerate < 0)
avimux->framerate = gst_video_frame_rate(GST_PAD_PEER(avimux->videosinkpad));
break;
}
} }
} }
} }
@ -1334,18 +1333,9 @@ gst_avimux_change_state (GstElement *element)
avimux = GST_AVIMUX(element); avimux = GST_AVIMUX(element);
switch (transition) { switch (transition) {
case GST_STATE_READY_TO_PAUSED:
break;
case GST_STATE_PAUSED_TO_PLAYING: case GST_STATE_PAUSED_TO_PLAYING:
avimux->framerate = -1; /* means that we fill it in later */
avimux->video_pad_eos = avimux->audio_pad_eos = FALSE; avimux->video_pad_eos = avimux->audio_pad_eos = FALSE;
break; break;
case GST_STATE_PLAYING_TO_PAUSED:
/* this function returns TRUE while it handles buffers */
while (gst_avimux_do_one_buffer(avimux));
break;
case GST_STATE_PAUSED_TO_READY:
break;
} }
if (GST_ELEMENT_CLASS (parent_class)->change_state) if (GST_ELEMENT_CLASS (parent_class)->change_state)

View file

@ -56,9 +56,6 @@ struct _GstAviMux {
GstPad *videosinkpad; GstPad *videosinkpad;
gboolean video_pad_connected, video_pad_eos; gboolean video_pad_connected, video_pad_eos;
/* timestamps of first and current frame + num_frames for fps calculation */
gdouble framerate;
/* the AVI header */ /* the AVI header */
gst_riff_avih avi_hdr; gst_riff_avih avi_hdr;
guint32 total_frames; /* total number of frames */ guint32 total_frames; /* total number of frames */