static void dxr3audiosink_chain_ac3 (GstPad * pad, GstData * _data) { Dxr3AudioSink *sink; gint bytes_written = 0; GstBuffer *buf; g_return_if_fail (pad != NULL); g_return_if_fail (GST_IS_PAD (pad)); g_return_if_fail (_data != NULL); sink = DXR3AUDIOSINK (gst_pad_get_parent (pad)); if (GST_IS_EVENT (_data)) { dxr3audiosink_handle_event (pad, GST_EVENT (_data)); return; } buf = GST_BUFFER (_data); if (sink->mode != DXR3AUDIOSINK_MODE_AC3) { /* Switch to AC3 mode. */ dxr3audiosink_set_mode_ac3 (sink); } if (GST_OBJECT_FLAG_IS_SET (sink, DXR3AUDIOSINK_OPEN)) { int event; if (GST_BUFFER_TIMESTAMP (buf) != GST_CLOCK_TIME_NONE) { /* We have a new scr value. */ /* fprintf (stderr, "------ Audio Time %.04f\n", */ /* (double) GST_BUFFER_TIMESTAMP (buf) / GST_SECOND); */ sink->scr = GSTTIME_TO_MPEGTIME (GST_BUFFER_TIMESTAMP (buf)); } /* Push the new data into the padder. */ ac3p_push_data (sink->padder, GST_BUFFER_DATA (buf), GST_BUFFER_SIZE (buf)); /* Parse the data. */ event = ac3p_parse (sink->padder); while (event != AC3P_EVENT_PUSH) { switch (event) { case AC3P_EVENT_FRAME: /* We have a new frame: */ /* Update the system reference clock (SCR) in the card. */ { unsigned in, out, odelay; unsigned diff; ioctl (sink->control_fd, EM8300_IOCTL_SCR_GET, &out); ioctl (sink->audio_fd, SNDCTL_DSP_GETODELAY, &odelay); /* 192000 bytes/sec */ in = MPEGTIME_TO_DXRTIME (sink->scr - (odelay * 90) / 192); diff = in > out ? in - out : out - in; if (diff > 1800) { dxr3audiosink_set_scr (sink, in); } } /* Update our SCR value. */ sink->scr += TIME_FOR_BYTES (ac3p_frame_size (sink->padder)); /* Write the frame to the sound device. */ bytes_written = write (sink->audio_fd, ac3p_frame (sink->padder), AC3P_IEC_FRAME_SIZE); if (bytes_written < AC3P_IEC_FRAME_SIZE) { fprintf (stderr, "dxr3audiosink: Warning: %d bytes should be " "written, only %d bytes written\n", AC3P_IEC_FRAME_SIZE, bytes_written); } break; } event = ac3p_parse (sink->padder); } } gst_buffer_unref (buf); }
static gboolean dxr3videosink_handle_event (GstPad * pad, GstEvent * event) { GstEventType type; Dxr3VideoSink *sink; sink = DXR3VIDEOSINK (gst_pad_get_parent (pad)); type = event ? GST_EVENT_TYPE (event) : GST_EVENT_UNKNOWN; switch (type) { case GST_EVENT_EMPTY: //fprintf (stderr, "++++++ Video empty event\n"); { /* FIXME: Handle this with a discontinuity or something. */ /* Write an MPEG2 sequence end code, to ensure that the card actually displays the last picture. Apparently some DVDs are encoded without proper sequence end codes. */ static const guint8 sec[4] = { 0x00, 0x00, 0x01, 0xb7 }; if (sink->cur_buf != NULL) { dxr3videosink_write_data (sink, 0); } write (sink->video_fd, &sec, 4); } break; case GST_EVENT_DISCONTINUOUS: //fprintf (stderr, "++++++ Video discont event\n"); { gint64 time; gboolean has_time; unsigned cur_scr, mpeg_scr, diff; has_time = gst_event_discont_get_value (event, GST_FORMAT_TIME, &time); if (has_time) { /* fprintf (stderr, "^^^^^^ Discontinuous event has time %.4f\n", */ /* (double) time / GST_SECOND); */ /* If the SCR in the card is way off, fix it. */ ioctl (sink->control_fd, EM8300_IOCTL_SCR_GET, &cur_scr); mpeg_scr = MPEGTIME_TO_DXRTIME (GSTTIME_TO_MPEGTIME (time)); diff = cur_scr > mpeg_scr ? cur_scr - mpeg_scr : mpeg_scr - cur_scr; if (diff > 1800) { unsigned zero = 0; /* fprintf (stderr, "====== Adjusting SCR from video\n"); */ ioctl (sink->control_fd, EM8300_IOCTL_SCR_SET, &zero); ioctl (sink->control_fd, EM8300_IOCTL_SCR_SET, &mpeg_scr); } } else { /* fprintf (stderr, "^^^^^^ Discontinuous event has no time\n"); */ } } break; case GST_EVENT_FLUSH: dxr3videosink_reset_parser (sink); break; default: gst_pad_event_default (pad, event); break; } return TRUE; }
static void dxr3audiosink_chain_pcm (GstPad * pad, GstData * _data) { Dxr3AudioSink *sink; gint bytes_written = 0; GstBuffer *buf; g_return_if_fail (pad != NULL); g_return_if_fail (GST_IS_PAD (pad)); g_return_if_fail (_data != NULL); sink = DXR3AUDIOSINK (gst_pad_get_parent (pad)); if (GST_IS_EVENT (_data)) { dxr3audiosink_handle_event (pad, GST_EVENT (_data)); return; } buf = GST_BUFFER (_data); if (sink->mode != DXR3AUDIOSINK_MODE_PCM) { /* Switch to PCM mode. */ dxr3audiosink_set_mode_pcm (sink); } if (GST_OBJECT_FLAG_IS_SET (sink, DXR3AUDIOSINK_OPEN)) { if (GST_BUFFER_TIMESTAMP (buf) != GST_CLOCK_TIME_NONE) { /* We have a new scr value. */ sink->scr = GSTTIME_TO_MPEGTIME (GST_BUFFER_TIMESTAMP (buf)); } /* Update the system reference clock (SCR) in the card. */ { unsigned in, out, odelay; unsigned diff; ioctl (sink->control_fd, EM8300_IOCTL_SCR_GET, &out); ioctl (sink->audio_fd, SNDCTL_DSP_GETODELAY, &odelay); in = MPEGTIME_TO_DXRTIME (sink->scr - (odelay * 90) / 192); diff = in > out ? in - out : out - in; if (diff > 1800) { dxr3audiosink_set_scr (sink, in); } } /* Update our SCR value. */ sink->scr += (unsigned) (GST_BUFFER_SIZE (buf) * (90000.0 / ((float) sink->rate * 4))); /* Write the buffer to the sound device. */ bytes_written = write (sink->audio_fd, GST_BUFFER_DATA (buf), GST_BUFFER_SIZE (buf)); if (bytes_written < GST_BUFFER_SIZE (buf)) { fprintf (stderr, "dxr3audiosink: Warning: %d bytes should be " "written, only %d bytes written\n", GST_BUFFER_SIZE (buf), bytes_written); } } gst_buffer_unref (buf); }