ext/dv/: Ueber spiffify some more, added debug category.
[platform/upstream/gst-plugins-good.git] / ext / dv / gstdvdemux.c
1 /* GStreamer
2  * Copyright (C) <1999> Erik Walthinsen <omega@cse.ogi.edu>
3  *               <2005> Wim Taymans <wim@fluendo.com>
4  *
5  * This library is free software; you can redistribute it and/or
6  * modify it under the terms of the GNU Library General Public
7  * License as published by the Free Software Foundation; either
8  * version 2 of the License, or (at your option) any later version.
9  *
10  * This library is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13  * Library General Public License for more details.
14  *
15  * You should have received a copy of the GNU Library General Public
16  * License along with this library; if not, write to the
17  * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
18  * Boston, MA 02111-1307, USA.
19  */
20
21 #ifdef HAVE_CONFIG_H
22 #include "config.h"
23 #endif
24 #include <string.h>
25 #include <math.h>
26
27 #include <gst/audio/audio.h>
28 #include "gstdvdemux.h"
29
30 /* DV output has two modes, normal and wide. The resolution is the same in both
31  * cases: 720 pixels wide by 576 pixels tall in PAL format, and 720x480 for
32  * NTSC.
33  *
34  * Each of the modes has its own pixel aspect ratio, which is fixed in practice
35  * by ITU-R BT.601 (also known as "CCIR-601" or "Rec.601"). Or so claims a
36  * reference that I culled from the reliable "internet",
37  * http://www.mir.com/DMG/aspect.html. Normal PAL is 59/54 and normal NTSC is
38  * 10/11. Because the pixel resolution is the same for both cases, we can get
39  * the pixel aspect ratio for wide recordings by multiplying by the ratio of
40  * display aspect ratios, 16/9 (for wide) divided by 4/3 (for normal):
41  *
42  * Wide NTSC: 10/11 * (16/9)/(4/3) = 40/33
43  * Wide PAL: 59/54 * (16/9)/(4/3) = 118/81
44  *
45  * However, the pixel resolution coming out of a DV source does not combine with
46  * the standard pixel aspect ratios to give a proper display aspect ratio. An
47  * image 480 pixels tall, with a 4:3 display aspect ratio, will be 768 pixels
48  * wide. But, if we take the normal PAL aspect ratio of 59/54, and multiply it
49  * with the width of the DV image (720 pixels), we get 786.666..., which is
50  * nonintegral and too wide. The camera is not outputting a 4:3 image.
51  * 
52  * If the video sink for this stream has fixed dimensions (such as for
53  * fullscreen playback, or for a java applet in a web page), you then have two
54  * choices. Either you show the whole image, but pad the image with black
55  * borders on the top and bottom (like watching a widescreen video on a 4:3
56  * device), or you crop the video to the proper ratio. Apparently the latter is
57  * the standard practice.
58  *
59  * For its part, GStreamer is concerned with accuracy and preservation of
60  * information. This element outputs the 720x576 or 720x480 video that it
61  * recieves, noting the proper aspect ratio. This should not be a problem for
62  * windowed applications, which can change size to fit the video. Applications
63  * with fixed size requirements should decide whether to crop or pad which
64  * an element such as videobox can do.
65  */
66
67 #define NTSC_HEIGHT 480
68 #define NTSC_BUFFER 120000
69 #define NTSC_FRAMERATE_NUMERATOR 30000
70 #define NTSC_FRAMERATE_DENOMINATOR 1001
71
72 #define PAL_HEIGHT 576
73 #define PAL_BUFFER 144000
74 #define PAL_FRAMERATE_NUMERATOR 25
75 #define PAL_FRAMERATE_DENOMINATOR 1
76
77 #define PAL_NORMAL_PAR_X        59
78 #define PAL_NORMAL_PAR_Y        54
79 #define PAL_WIDE_PAR_X          118
80 #define PAL_WIDE_PAR_Y          81
81
82 #define NTSC_NORMAL_PAR_X       10
83 #define NTSC_NORMAL_PAR_Y       11
84 #define NTSC_WIDE_PAR_X         40
85 #define NTSC_WIDE_PAR_Y         33
86
87 GST_DEBUG_CATEGORY (dvdemux_debug);
88 #define GST_CAT_DEFAULT dvdemux_debug
89
90 static GstElementDetails dvdemux_details =
91 GST_ELEMENT_DETAILS ("DV system stream demuxer",
92     "Codec/Demuxer",
93     "Uses libdv to separate DV audio from DV video",
94     "Erik Walthinsen <omega@cse.ogi.edu>, Wim Taymans <wim@fluendo.com>");
95
96 static GstStaticPadTemplate sink_temp = GST_STATIC_PAD_TEMPLATE ("sink",
97     GST_PAD_SINK,
98     GST_PAD_ALWAYS,
99     GST_STATIC_CAPS ("video/x-dv, systemstream = (boolean) true")
100     );
101
102 static GstStaticPadTemplate video_src_temp = GST_STATIC_PAD_TEMPLATE ("video",
103     GST_PAD_SRC,
104     GST_PAD_SOMETIMES,
105     GST_STATIC_CAPS ("video/x-dv, systemstream = (boolean) false")
106     );
107
108 static GstStaticPadTemplate audio_src_temp = GST_STATIC_PAD_TEMPLATE ("audio",
109     GST_PAD_SRC,
110     GST_PAD_SOMETIMES,
111     GST_STATIC_CAPS ("audio/x-raw-int, "
112         "depth = (int) 16, "
113         "width = (int) 16, "
114         "signed = (boolean) TRUE, "
115         "channels = (int) {2, 4}, "
116         "endianness = (int) " G_STRINGIFY (G_BYTE_ORDER) ", "
117         "rate = (int) { 32000, 44100, 48000 }")
118     );
119
120
121 GST_BOILERPLATE (GstDVDemux, gst_dvdemux, GstElement, GST_TYPE_ELEMENT);
122
123
124 static const GstQueryType *gst_dvdemux_get_src_query_types (GstPad * pad);
125 static gboolean gst_dvdemux_src_query (GstPad * pad, GstQuery * query);
126 static const GstQueryType *gst_dvdemux_get_sink_query_types (GstPad * pad);
127 static gboolean gst_dvdemux_sink_query (GstPad * pad, GstQuery * query);
128
129 static gboolean gst_dvdemux_sink_convert (GstPad * pad, GstFormat src_format,
130     gint64 src_value, GstFormat * dest_format, gint64 * dest_value);
131 static gboolean gst_dvdemux_src_convert (GstPad * pad, GstFormat src_format,
132     gint64 src_value, GstFormat * dest_format, gint64 * dest_value);
133
134 static gboolean gst_dvdemux_handle_src_event (GstPad * pad, GstEvent * event);
135 static GstFlowReturn gst_dvdemux_flush (GstDVDemux * dvdemux);
136 static GstFlowReturn gst_dvdemux_chain (GstPad * pad, GstBuffer * buffer);
137 static gboolean gst_dvdemux_handle_sink_event (GstPad * pad, GstEvent * event);
138
139 static GstStateChangeReturn gst_dvdemux_change_state (GstElement * element,
140     GstStateChange transition);
141
142
143 static void
144 gst_dvdemux_base_init (gpointer g_class)
145 {
146   GstElementClass *element_class = GST_ELEMENT_CLASS (g_class);
147
148   gst_element_class_add_pad_template (element_class,
149       gst_static_pad_template_get (&sink_temp));
150   gst_element_class_add_pad_template (element_class,
151       gst_static_pad_template_get (&video_src_temp));
152   gst_element_class_add_pad_template (element_class,
153       gst_static_pad_template_get (&audio_src_temp));
154
155   gst_element_class_set_details (element_class, &dvdemux_details);
156
157   GST_DEBUG_CATEGORY_INIT (dvdemux_debug, "dvdemux", 0, "DV demuxer element");
158 }
159
160 static void
161 gst_dvdemux_class_init (GstDVDemuxClass * klass)
162 {
163   GstElementClass *gstelement_class;
164
165   gstelement_class = (GstElementClass *) klass;
166
167   gstelement_class->change_state = gst_dvdemux_change_state;
168
169   /* table initialization, only do once */
170   dv_init (0, 0);
171 }
172
173 static void
174 gst_dvdemux_init (GstDVDemux * dvdemux, GstDVDemuxClass * g_class)
175 {
176   gint i;
177
178   dvdemux->sinkpad =
179       gst_pad_new_from_template (gst_static_pad_template_get (&sink_temp),
180       "sink");
181   gst_pad_set_chain_function (dvdemux->sinkpad, gst_dvdemux_chain);
182   gst_pad_set_event_function (dvdemux->sinkpad, gst_dvdemux_handle_sink_event);
183   gst_pad_set_query_function (dvdemux->sinkpad,
184       GST_DEBUG_FUNCPTR (gst_dvdemux_sink_query));
185   gst_pad_set_query_type_function (dvdemux->sinkpad,
186       GST_DEBUG_FUNCPTR (gst_dvdemux_get_sink_query_types));
187   gst_element_add_pad (GST_ELEMENT (dvdemux), dvdemux->sinkpad);
188
189   dvdemux->adapter = gst_adapter_new ();
190
191   for (i = 0; i < 4; i++) {
192     dvdemux->audio_buffers[i] =
193         (gint16 *) g_malloc (DV_AUDIO_MAX_SAMPLES * sizeof (gint16));
194   }
195 }
196
197 static void
198 gst_dvdemux_add_pads (GstDVDemux * dvdemux)
199 {
200   dvdemux->videosrcpad =
201       gst_pad_new_from_template (gst_static_pad_template_get (&video_src_temp),
202       "video");
203   gst_pad_set_query_function (dvdemux->videosrcpad,
204       GST_DEBUG_FUNCPTR (gst_dvdemux_src_query));
205   gst_pad_set_query_type_function (dvdemux->videosrcpad,
206       GST_DEBUG_FUNCPTR (gst_dvdemux_get_src_query_types));
207   gst_pad_set_event_function (dvdemux->videosrcpad,
208       GST_DEBUG_FUNCPTR (gst_dvdemux_handle_src_event));
209   gst_pad_use_fixed_caps (dvdemux->videosrcpad);
210   gst_element_add_pad (GST_ELEMENT (dvdemux), dvdemux->videosrcpad);
211
212   dvdemux->audiosrcpad =
213       gst_pad_new_from_template (gst_static_pad_template_get (&audio_src_temp),
214       "audio");
215   gst_pad_set_query_function (dvdemux->audiosrcpad,
216       GST_DEBUG_FUNCPTR (gst_dvdemux_src_query));
217   gst_pad_set_query_type_function (dvdemux->audiosrcpad,
218       GST_DEBUG_FUNCPTR (gst_dvdemux_get_src_query_types));
219   gst_pad_set_event_function (dvdemux->audiosrcpad,
220       GST_DEBUG_FUNCPTR (gst_dvdemux_handle_src_event));
221   gst_pad_use_fixed_caps (dvdemux->audiosrcpad);
222   gst_element_add_pad (GST_ELEMENT (dvdemux), dvdemux->audiosrcpad);
223
224   gst_element_no_more_pads (GST_ELEMENT (dvdemux));
225 }
226
227 static gboolean
228 gst_dvdemux_src_convert (GstPad * pad, GstFormat src_format, gint64 src_value,
229     GstFormat * dest_format, gint64 * dest_value)
230 {
231   gboolean res = TRUE;
232   GstDVDemux *dvdemux;
233
234   dvdemux = GST_DVDEMUX (gst_pad_get_parent (pad));
235   if (dvdemux->frame_len == -1)
236     goto error;
237
238   if (dvdemux->decoder == NULL)
239     goto error;
240
241   if (*dest_format == src_format) {
242     *dest_value = src_value;
243     goto done;
244   }
245
246   GST_INFO ("pad:%s:%s, src_value:%lld, src_format:%d, dest_format:%d",
247       GST_DEBUG_PAD_NAME (pad), src_value, src_format, *dest_format);
248
249   switch (src_format) {
250     case GST_FORMAT_BYTES:
251       switch (*dest_format) {
252         case GST_FORMAT_DEFAULT:
253           if (pad == dvdemux->videosrcpad)
254             *dest_value = src_value / dvdemux->frame_len;
255           else if (pad == dvdemux->audiosrcpad)
256             *dest_value = src_value / gst_audio_frame_byte_size (pad);
257           break;
258         case GST_FORMAT_TIME:
259           *dest_format = GST_FORMAT_TIME;
260           if (pad == dvdemux->videosrcpad)
261             *dest_value = gst_util_uint64_scale (src_value,
262                 GST_SECOND * dvdemux->framerate_denominator,
263                 dvdemux->frame_len * dvdemux->framerate_numerator);
264           else if (pad == dvdemux->audiosrcpad)
265             *dest_value = gst_util_uint64_scale_int (src_value, GST_SECOND,
266                 2 * dvdemux->frequency * dvdemux->channels);
267           break;
268         default:
269           res = FALSE;
270       }
271       break;
272     case GST_FORMAT_TIME:
273       switch (*dest_format) {
274         case GST_FORMAT_BYTES:
275           if (pad == dvdemux->videosrcpad)
276             *dest_value = gst_util_uint64_scale (src_value,
277                 dvdemux->frame_len * dvdemux->framerate_numerator,
278                 dvdemux->framerate_denominator * GST_SECOND);
279           else if (pad == dvdemux->audiosrcpad)
280             *dest_value = gst_util_uint64_scale_int (src_value,
281                 2 * dvdemux->frequency * dvdemux->channels, GST_SECOND);
282           break;
283         case GST_FORMAT_DEFAULT:
284           if (pad == dvdemux->videosrcpad) {
285             if (src_value)
286               *dest_value = gst_util_uint64_scale (src_value,
287                   dvdemux->framerate_numerator,
288                   dvdemux->framerate_denominator * GST_SECOND);
289             else
290               *dest_value = 0;
291           } else if (pad == dvdemux->audiosrcpad) {
292             *dest_value = gst_util_uint64_scale (src_value,
293                 2 * dvdemux->frequency * dvdemux->channels,
294                 GST_SECOND * gst_audio_frame_byte_size (pad));
295           }
296           break;
297         default:
298           res = FALSE;
299       }
300       break;
301     case GST_FORMAT_DEFAULT:
302       switch (*dest_format) {
303         case GST_FORMAT_TIME:
304           if (pad == dvdemux->videosrcpad) {
305             *dest_value = gst_util_uint64_scale (src_value,
306                 GST_SECOND * dvdemux->framerate_denominator,
307                 dvdemux->framerate_numerator);
308           } else if (pad == dvdemux->audiosrcpad) {
309             if (src_value)
310               *dest_value = gst_util_uint64_scale (src_value,
311                   GST_SECOND * gst_audio_frame_byte_size (pad),
312                   2 * dvdemux->frequency * dvdemux->channels);
313             else
314               *dest_value = 0;
315           }
316           break;
317         case GST_FORMAT_BYTES:
318           if (pad == dvdemux->videosrcpad) {
319             *dest_value = src_value * dvdemux->frame_len;
320           } else if (pad == dvdemux->audiosrcpad) {
321             *dest_value = src_value * gst_audio_frame_byte_size (pad);
322           }
323           break;
324         default:
325           res = FALSE;
326       }
327       break;
328     default:
329       res = FALSE;
330   }
331
332 done:
333   gst_object_unref (dvdemux);
334
335   GST_INFO ("Result : dest_format:%d, dest_value:%lld, res:%d",
336       *dest_format, *dest_value, res);
337   return res;
338
339   /* ERRORS */
340 error:
341   {
342     GST_INFO ("source conversion failed");
343     gst_object_unref (dvdemux);
344     return FALSE;
345   }
346 }
347
348 static gboolean
349 gst_dvdemux_sink_convert (GstPad * pad, GstFormat src_format, gint64 src_value,
350     GstFormat * dest_format, gint64 * dest_value)
351 {
352   gboolean res = TRUE;
353   GstDVDemux *dvdemux;
354
355   dvdemux = GST_DVDEMUX (gst_pad_get_parent (pad));
356
357   if (dvdemux->frame_len <= 0)
358     goto error;
359
360   GST_DEBUG ("%d -> %d", src_format, *dest_format);
361   GST_INFO ("pad:%s:%s, src_value:%lld, src_format:%d, dest_format:%d",
362       GST_DEBUG_PAD_NAME (pad), src_value, src_format, *dest_format);
363
364   if (*dest_format == GST_FORMAT_DEFAULT)
365     *dest_format = GST_FORMAT_TIME;
366
367   if (*dest_format == src_format) {
368     *dest_value = src_value;
369     goto done;
370   }
371
372   switch (src_format) {
373     case GST_FORMAT_BYTES:
374       switch (*dest_format) {
375         case GST_FORMAT_TIME:
376         {
377           guint64 frame;
378
379           /* get frame number */
380           frame = src_value / dvdemux->frame_len;
381
382           *dest_value = gst_util_uint64_scale (frame,
383               GST_SECOND * dvdemux->framerate_denominator,
384               dvdemux->framerate_numerator);
385           break;
386         }
387         default:
388           res = FALSE;
389       }
390       break;
391     case GST_FORMAT_TIME:
392       switch (*dest_format) {
393         case GST_FORMAT_BYTES:
394         {
395           guint64 frame;
396
397           /* calculate the frame */
398           frame =
399               gst_util_uint64_scale (src_value, dvdemux->framerate_numerator,
400               dvdemux->framerate_denominator * GST_SECOND);
401
402           /* calculate the offset */
403           *dest_value = frame * dvdemux->frame_len;
404           break;
405         }
406         default:
407           res = FALSE;
408       }
409       break;
410     default:
411       res = FALSE;
412   }
413   GST_INFO ("Result : dest_format:%d, dest_value:%lld, res:%d",
414       *dest_format, *dest_value, res);
415
416 done:
417   gst_object_unref (dvdemux);
418   return res;
419
420 error:
421   {
422     GST_INFO ("sink conversion failed");
423     gst_object_unref (dvdemux);
424     return FALSE;
425   }
426 }
427
428 static const GstQueryType *
429 gst_dvdemux_get_src_query_types (GstPad * pad)
430 {
431   static const GstQueryType src_query_types[] = {
432     GST_QUERY_POSITION,
433     GST_QUERY_DURATION,
434     GST_QUERY_CONVERT,
435     0
436   };
437
438   return src_query_types;
439 }
440
441 static gboolean
442 gst_dvdemux_src_query (GstPad * pad, GstQuery * query)
443 {
444   gboolean res = TRUE;
445   GstDVDemux *dvdemux;
446
447   dvdemux = GST_DVDEMUX (gst_pad_get_parent (pad));
448
449   switch (GST_QUERY_TYPE (query)) {
450     case GST_QUERY_POSITION:
451     {
452       GstFormat format;
453       gint64 cur;
454
455       /* get target format */
456       gst_query_parse_position (query, &format, NULL);
457
458       /* bring the position to the requested format. */
459       if (!(res = gst_pad_query_convert (pad,
460                   GST_FORMAT_TIME, dvdemux->timestamp, &format, &cur)))
461         goto error;
462       gst_query_set_position (query, format, cur);
463       break;
464     }
465     case GST_QUERY_DURATION:
466     {
467       GstFormat format;
468       GstFormat format2;
469       gint64 end;
470       GstPad *peer;
471
472       /* get target format */
473       gst_query_parse_duration (query, &format, NULL);
474
475       /* change query to bytes to perform on peer */
476       gst_query_set_duration (query, GST_FORMAT_BYTES, -1);
477
478       if ((peer = gst_pad_get_peer (dvdemux->sinkpad))) {
479         /* ask peer for total length */
480         if (!(res = gst_pad_query (peer, query))) {
481           gst_object_unref (peer);
482           goto error;
483         }
484
485         /* get peer total length */
486         gst_query_parse_duration (query, NULL, &end);
487
488         gst_object_unref (peer);
489
490         /* convert end to requested format */
491         if (end != -1) {
492           format2 = format;
493           if (!(res = gst_pad_query_convert (dvdemux->sinkpad,
494                       GST_FORMAT_BYTES, end, &format2, &end))) {
495             goto error;
496           }
497         }
498       } else {
499         end = -1;
500       }
501       gst_query_set_duration (query, format, end);
502       break;
503     }
504     case GST_QUERY_CONVERT:
505     {
506       GstFormat src_fmt, dest_fmt;
507       gint64 src_val, dest_val;
508
509       gst_query_parse_convert (query, &src_fmt, &src_val, &dest_fmt, &dest_val);
510       if (!(res =
511               gst_dvdemux_src_convert (pad, src_fmt, src_val, &dest_fmt,
512                   &dest_val)))
513         goto error;
514       gst_query_set_convert (query, src_fmt, src_val, dest_fmt, dest_val);
515       break;
516     }
517     default:
518       res = gst_pad_query_default (pad, query);
519       break;
520   }
521   gst_object_unref (dvdemux);
522
523   return res;
524
525 error:
526   {
527     gst_object_unref (dvdemux);
528     GST_DEBUG ("error source query");
529     return FALSE;
530   }
531 }
532
533 static const GstQueryType *
534 gst_dvdemux_get_sink_query_types (GstPad * pad)
535 {
536   static const GstQueryType sink_query_types[] = {
537     GST_QUERY_CONVERT,
538     0
539   };
540
541   return sink_query_types;
542 }
543
544 static gboolean
545 gst_dvdemux_sink_query (GstPad * pad, GstQuery * query)
546 {
547   gboolean res = TRUE;
548   GstDVDemux *dvdemux;
549
550   dvdemux = GST_DVDEMUX (gst_pad_get_parent (pad));
551
552   switch (GST_QUERY_TYPE (query)) {
553     case GST_QUERY_CONVERT:
554     {
555       GstFormat src_fmt, dest_fmt;
556       gint64 src_val, dest_val;
557
558       gst_query_parse_convert (query, &src_fmt, &src_val, &dest_fmt, &dest_val);
559       if (!(res =
560               gst_dvdemux_sink_convert (pad, src_fmt, src_val, &dest_fmt,
561                   &dest_val)))
562         goto error;
563       gst_query_set_convert (query, src_fmt, src_val, dest_fmt, dest_val);
564       break;
565     }
566     default:
567       res = gst_pad_query_default (pad, query);
568       break;
569   }
570   gst_object_unref (dvdemux);
571
572   return res;
573
574 error:
575   {
576     gst_object_unref (dvdemux);
577     GST_DEBUG ("error handling sink query");
578     return FALSE;
579   }
580 }
581
582 static gboolean
583 gst_dvdemux_send_event (GstDVDemux * dvdemux, GstEvent * event)
584 {
585   gboolean res = FALSE;
586
587   gst_event_ref (event);
588   if (dvdemux->videosrcpad)
589     res |= gst_pad_push_event (dvdemux->videosrcpad, event);
590   if (dvdemux->audiosrcpad)
591     res |= gst_pad_push_event (dvdemux->audiosrcpad, event);
592
593   return res;
594 }
595
596 static gboolean
597 gst_dvdemux_handle_sink_event (GstPad * pad, GstEvent * event)
598 {
599   GstDVDemux *dvdemux = GST_DVDEMUX (gst_pad_get_parent (pad));
600   gboolean res = TRUE;
601
602   switch (GST_EVENT_TYPE (event)) {
603     case GST_EVENT_FLUSH_START:
604       /* we are not blocking on anything exect the push() calls
605        * to the peer which will be unblocked by forwarding the
606        * event.*/
607       res = gst_dvdemux_send_event (dvdemux, event);
608       break;
609     case GST_EVENT_FLUSH_STOP:
610       gst_adapter_clear (dvdemux->adapter);
611       GST_DEBUG ("cleared adapter");
612       res = gst_dvdemux_send_event (dvdemux, event);
613       gst_segment_init (&dvdemux->byte_segment, GST_FORMAT_BYTES);
614       gst_segment_init (&dvdemux->time_segment, GST_FORMAT_TIME);
615       break;
616     case GST_EVENT_NEWSEGMENT:
617     {
618       gboolean update;
619       gdouble rate;
620       GstFormat format;
621       gint64 start, stop, time;
622
623       /* parse byte start and stop positions */
624       gst_event_parse_new_segment (event, &update, &rate, &format,
625           &start, &stop, &time);
626
627       switch (format) {
628         case GST_FORMAT_BYTES:
629           gst_segment_set_newsegment (&dvdemux->byte_segment, update,
630               rate, format, start, stop, time);
631
632           /* and queue a SEGMENT before sending the next set of buffers, we
633            * cannot convert to time yet as we might not know the size of the
634            * frames, etc.. */
635           dvdemux->need_segment = TRUE;
636           gst_event_unref (event);
637           break;
638         case GST_FORMAT_TIME:
639           gst_segment_set_newsegment (&dvdemux->time_segment, update,
640               rate, format, start, stop, time);
641
642           /* and we can just forward this time event */
643           res = gst_dvdemux_send_event (dvdemux, event);
644           break;
645         default:
646           gst_event_unref (event);
647           /* cannot accept this format */
648           res = FALSE;
649           break;
650       }
651       break;
652     }
653     case GST_EVENT_EOS:
654       /* flush any pending data */
655       gst_dvdemux_flush (dvdemux);
656       /* forward event */
657       res = gst_dvdemux_send_event (dvdemux, event);
658       /* and clear the adapter */
659       gst_adapter_clear (dvdemux->adapter);
660       break;
661     default:
662       res = gst_dvdemux_send_event (dvdemux, event);
663       break;
664   }
665
666   gst_object_unref (dvdemux);
667
668   return res;
669 }
670
671 static gboolean
672 gst_dvdemux_handle_src_event (GstPad * pad, GstEvent * event)
673 {
674   gboolean res = TRUE;
675   GstDVDemux *dvdemux;
676
677   dvdemux = GST_DVDEMUX (gst_pad_get_parent (pad));
678
679   switch (GST_EVENT_TYPE (event)) {
680     case GST_EVENT_SEEK:
681     {
682       GstEvent *newevent;
683       gint64 offset;
684       GstFormat format, conv;
685       gint64 cur, stop;
686       gdouble rate;
687       GstSeekType cur_type, stop_type;
688       GstSeekFlags flags;
689       gint64 start_position, end_position;
690
691       gst_event_parse_seek (event, &rate, &format, &flags,
692           &cur_type, &cur, &stop_type, &stop);
693
694       if ((offset = cur) != -1) {
695         GST_INFO ("starting conversion of cur");
696         /* bring the format to time on srcpad. */
697         conv = GST_FORMAT_TIME;
698         if (!(res = gst_pad_query_convert (pad,
699                     format, offset, &conv, &start_position))) {
700           /* could not convert seek format to time offset */
701           break;
702         }
703         /* and convert to bytes on sinkpad. */
704         conv = GST_FORMAT_BYTES;
705         if (!(res = gst_pad_query_convert (dvdemux->sinkpad,
706                     GST_FORMAT_TIME, start_position, &conv, &start_position))) {
707           /* could not convert time format to bytes offset */
708           break;
709         }
710         GST_INFO ("Finished conversion of cur, BYTES cur : %lld",
711             start_position);
712       } else {
713         start_position = -1;
714       }
715
716       if ((offset = stop) != -1) {
717         GST_INFO ("starting conversion of stop");
718         /* bring the format to time on srcpad. */
719         conv = GST_FORMAT_TIME;
720         if (!(res = gst_pad_query_convert (pad,
721                     format, offset, &conv, &end_position))) {
722           /* could not convert seek format to time offset */
723           break;
724         }
725         conv = GST_FORMAT_BYTES;
726         /* and convert to bytes on sinkpad. */
727         if (!(res = gst_pad_query_convert (dvdemux->sinkpad,
728                     GST_FORMAT_TIME, end_position, &conv, &end_position))) {
729           /* could not convert seek format to bytes offset */
730           break;
731         }
732         GST_INFO ("Finished conversion of stop, BYTES cur : %lld",
733             start_position);
734       } else {
735         end_position = -1;
736       }
737       /* now this is the updated seek event on bytes */
738       newevent = gst_event_new_seek (rate, GST_FORMAT_BYTES, flags,
739           cur_type, start_position, stop_type, end_position);
740
741       res = gst_pad_push_event (dvdemux->sinkpad, newevent);
742       break;
743     }
744     default:
745       res = FALSE;
746       break;
747   }
748   gst_event_unref (event);
749
750   gst_object_unref (dvdemux);
751
752   return res;
753 }
754
755 static GstFlowReturn
756 gst_dvdemux_demux_audio (GstDVDemux * dvdemux, const guint8 * data)
757 {
758   gint num_samples;
759   gint frequency, channels;
760   GstFlowReturn ret;
761
762   frequency = dv_get_frequency (dvdemux->decoder);
763   channels = dv_get_num_channels (dvdemux->decoder);
764
765   /* check if format changed */
766   if ((frequency != dvdemux->frequency) || (channels != dvdemux->channels)) {
767     GstCaps *caps;
768
769     dvdemux->frequency = frequency;
770     dvdemux->channels = channels;
771
772     /* and set new caps */
773     caps = gst_caps_new_simple ("audio/x-raw-int",
774         "rate", G_TYPE_INT, frequency,
775         "depth", G_TYPE_INT, 16,
776         "width", G_TYPE_INT, 16,
777         "signed", G_TYPE_BOOLEAN, TRUE,
778         "channels", G_TYPE_INT, channels,
779         "endianness", G_TYPE_INT, G_BYTE_ORDER, NULL);
780     gst_pad_set_caps (dvdemux->audiosrcpad, caps);
781     gst_caps_unref (caps);
782   }
783
784   dv_decode_full_audio (dvdemux->decoder, data, dvdemux->audio_buffers);
785
786   if ((num_samples = dv_get_num_samples (dvdemux->decoder)) > 0) {
787     gint16 *a_ptr;
788     gint i, j;
789     GstBuffer *outbuf;
790
791     outbuf = gst_buffer_new_and_alloc (num_samples *
792         sizeof (gint16) * dvdemux->channels);
793
794     a_ptr = (gint16 *) GST_BUFFER_DATA (outbuf);
795
796     for (i = 0; i < num_samples; i++) {
797       for (j = 0; j < dvdemux->channels; j++) {
798         *(a_ptr++) = dvdemux->audio_buffers[j][i];
799       }
800     }
801
802     GST_DEBUG ("pushing audio %" GST_TIME_FORMAT,
803         GST_TIME_ARGS (dvdemux->timestamp));
804
805     GST_BUFFER_TIMESTAMP (outbuf) = dvdemux->timestamp;
806     GST_BUFFER_DURATION (outbuf) = dvdemux->duration;
807     GST_BUFFER_OFFSET (outbuf) = dvdemux->audio_offset;
808     dvdemux->audio_offset += num_samples;
809     GST_BUFFER_OFFSET_END (outbuf) = dvdemux->audio_offset;
810
811     gst_buffer_set_caps (outbuf, GST_PAD_CAPS (dvdemux->audiosrcpad));
812
813     ret = gst_pad_push (dvdemux->audiosrcpad, outbuf);
814   } else {
815     /* no samples */
816     ret = GST_FLOW_OK;
817   }
818
819   return ret;
820 }
821
822 static GstFlowReturn
823 gst_dvdemux_demux_video (GstDVDemux * dvdemux, const guint8 * data)
824 {
825   GstBuffer *outbuf;
826   gint height;
827   gboolean wide;
828   GstFlowReturn ret = GST_FLOW_OK;
829
830   /* get params */
831   /* framerate is already up-to-date */
832   height = (dvdemux->PAL ? PAL_HEIGHT : NTSC_HEIGHT);
833   wide = dv_format_wide (dvdemux->decoder);
834
835   /* see if anything changed */
836   if ((dvdemux->height != height) || dvdemux->wide != wide) {
837     GstCaps *caps;
838     gint par_x, par_y;
839
840     dvdemux->height = height;
841     dvdemux->wide = wide;
842
843     if (dvdemux->PAL) {
844       if (wide) {
845         par_x = PAL_WIDE_PAR_X;
846         par_y = PAL_WIDE_PAR_Y;
847       } else {
848         par_x = PAL_NORMAL_PAR_X;
849         par_y = PAL_NORMAL_PAR_Y;
850       }
851     } else {
852       if (wide) {
853         par_x = NTSC_WIDE_PAR_X;
854         par_y = NTSC_WIDE_PAR_Y;
855       } else {
856         par_x = NTSC_NORMAL_PAR_X;
857         par_y = NTSC_NORMAL_PAR_Y;
858       }
859     }
860
861     caps = gst_caps_new_simple ("video/x-dv",
862         "systemstream", G_TYPE_BOOLEAN, FALSE,
863         "width", G_TYPE_INT, 720,
864         "height", G_TYPE_INT, height,
865         "framerate", GST_TYPE_FRACTION, dvdemux->framerate_numerator,
866         dvdemux->framerate_denominator,
867         "pixel-aspect-ratio", GST_TYPE_FRACTION, par_x, par_y, NULL);
868     gst_pad_set_caps (dvdemux->videosrcpad, caps);
869     gst_caps_unref (caps);
870   }
871
872   outbuf = gst_buffer_new ();
873
874   gst_buffer_set_data (outbuf, (guint8 *) data, dvdemux->frame_len);
875   outbuf->malloc_data = GST_BUFFER_DATA (outbuf);
876
877   GST_BUFFER_TIMESTAMP (outbuf) = dvdemux->timestamp;
878   GST_BUFFER_OFFSET (outbuf) = dvdemux->video_offset;
879   GST_BUFFER_OFFSET_END (outbuf) = dvdemux->video_offset + 1;
880   GST_BUFFER_DURATION (outbuf) = dvdemux->duration;
881
882   gst_buffer_set_caps (outbuf, GST_PAD_CAPS (dvdemux->videosrcpad));
883
884   GST_DEBUG ("pushing video %" GST_TIME_FORMAT,
885       GST_TIME_ARGS (dvdemux->timestamp));
886
887   ret = gst_pad_push (dvdemux->videosrcpad, outbuf);
888
889   dvdemux->video_offset++;
890
891   return ret;
892 }
893
894 static GstFlowReturn
895 gst_dvdemux_demux_frame (GstDVDemux * dvdemux, const guint8 * data)
896 {
897   GstClockTime next_ts;
898   GstFlowReturn aret, vret, ret;
899
900   if (dvdemux->need_segment) {
901     GstEvent *event;
902     GstFormat format;
903     gboolean res;
904
905     /* convert to time and store as start/end_timestamp */
906     format = GST_FORMAT_TIME;
907     if (!(res = gst_pad_query_convert (dvdemux->sinkpad,
908                 GST_FORMAT_BYTES, dvdemux->byte_segment.start,
909                 &format, &dvdemux->time_segment.start))) {
910       goto segment_error;
911     }
912     dvdemux->timestamp = dvdemux->time_segment.start;
913
914     /* calculate current frame number */
915     format = GST_FORMAT_DEFAULT;
916     if (!(res = gst_pad_query_convert (dvdemux->videosrcpad,
917                 GST_FORMAT_TIME, dvdemux->time_segment.start,
918                 &format, &dvdemux->total_frames))) {
919       goto segment_error;
920     }
921
922     if (dvdemux->byte_segment.stop == -1) {
923       dvdemux->time_segment.stop = -1;
924     } else {
925       format = GST_FORMAT_TIME;
926       if (!(res = gst_pad_query_convert (dvdemux->sinkpad,
927                   GST_FORMAT_BYTES, dvdemux->byte_segment.stop,
928                   &format, &dvdemux->time_segment.stop))) {
929         goto segment_error;
930       }
931     }
932
933     GST_DEBUG_OBJECT (dvdemux, "sending segment start: %" GST_TIME_FORMAT
934         ", stop: %" GST_TIME_FORMAT ", time: %" GST_TIME_FORMAT,
935         dvdemux->time_segment.start, dvdemux->time_segment.stop,
936         dvdemux->time_segment.start);
937
938     event = gst_event_new_new_segment (FALSE, 1.0, GST_FORMAT_TIME,
939         dvdemux->time_segment.start, dvdemux->time_segment.stop,
940         dvdemux->time_segment.start);
941     gst_dvdemux_send_event (dvdemux, event);
942
943     dvdemux->need_segment = FALSE;
944   }
945
946   next_ts = gst_util_uint64_scale_int (
947       (dvdemux->total_frames + 1) * GST_SECOND,
948       dvdemux->framerate_denominator, dvdemux->framerate_numerator);
949   dvdemux->duration = next_ts - dvdemux->timestamp;
950
951   dv_parse_packs (dvdemux->decoder, data);
952   if (dv_is_new_recording (dvdemux->decoder, data))
953     dvdemux->new_media = TRUE;
954
955   aret = ret = gst_dvdemux_demux_audio (dvdemux, data);
956   if (ret != GST_FLOW_OK && ret != GST_FLOW_NOT_LINKED)
957     goto done;
958
959   vret = ret = gst_dvdemux_demux_video (dvdemux, data);
960   if (ret != GST_FLOW_OK && ret != GST_FLOW_NOT_LINKED)
961     goto done;
962
963   if (aret == GST_FLOW_NOT_LINKED && vret == GST_FLOW_NOT_LINKED) {
964     ret = GST_FLOW_NOT_LINKED;
965     goto done;
966   }
967
968   ret = GST_FLOW_OK;
969   dvdemux->timestamp = next_ts;
970   dvdemux->total_frames++;
971
972 done:
973   return ret;
974
975 segment_error:
976   {
977     GST_DEBUG ("error generating new_segment event");
978     return GST_FLOW_ERROR;
979   }
980 }
981
982 /* flush any remaining data in the adapter */
983 static GstFlowReturn
984 gst_dvdemux_flush (GstDVDemux * dvdemux)
985 {
986   GstFlowReturn ret = GST_FLOW_OK;
987
988   while (gst_adapter_available (dvdemux->adapter) >= dvdemux->frame_len) {
989     const guint8 *data;
990     gint length;
991
992     /* get the accumulated bytes */
993     data = gst_adapter_peek (dvdemux->adapter, dvdemux->frame_len);
994
995     /* parse header to know the length and other params */
996     if (dv_parse_header (dvdemux->decoder, data) < 0)
997       goto parse_header_error;
998
999     dvdemux->found_header = TRUE;
1000
1001     /* after parsing the header we know the length of the data */
1002     dvdemux->PAL = dv_system_50_fields (dvdemux->decoder);
1003     length = dvdemux->frame_len = (dvdemux->PAL ? PAL_BUFFER : NTSC_BUFFER);
1004     if (dvdemux->PAL) {
1005       dvdemux->framerate_numerator = PAL_FRAMERATE_NUMERATOR;
1006       dvdemux->framerate_denominator = PAL_FRAMERATE_DENOMINATOR;
1007     } else {
1008       dvdemux->framerate_numerator = NTSC_FRAMERATE_NUMERATOR;
1009       dvdemux->framerate_denominator = NTSC_FRAMERATE_DENOMINATOR;
1010     }
1011     /* let demux_video set the height, it needs to detect when things change so
1012      * it can reset caps */
1013
1014     /* if we still have enough for a frame, start decoding */
1015     if (gst_adapter_available (dvdemux->adapter) >= length) {
1016
1017       data = gst_adapter_take (dvdemux->adapter, length);
1018
1019       /* and decode the data */
1020       ret = gst_dvdemux_demux_frame (dvdemux, data);
1021
1022       if (ret != GST_FLOW_OK)
1023         goto done;
1024     }
1025   }
1026 done:
1027   return ret;
1028
1029   /* ERRORS */
1030 parse_header_error:
1031   {
1032     GST_ELEMENT_ERROR (dvdemux, STREAM, DECODE,
1033         ("Error parsing DV header"), ("Error parsing DV header"));
1034
1035     return GST_FLOW_ERROR;
1036   }
1037 }
1038
1039 /* streaming operation: 
1040  *
1041  * accumulate data until we have a frame, then decode. 
1042  */
1043 static GstFlowReturn
1044 gst_dvdemux_chain (GstPad * pad, GstBuffer * buffer)
1045 {
1046   GstDVDemux *dvdemux;
1047   GstFlowReturn ret;
1048
1049   dvdemux = GST_DVDEMUX (gst_pad_get_parent (pad));
1050
1051   if (GST_BUFFER_FLAG_IS_SET (buffer, GST_BUFFER_FLAG_DISCONT))
1052     gst_adapter_clear (dvdemux->adapter);
1053
1054   /* temporary hack? Can't do this from the state change */
1055   if (!dvdemux->videosrcpad)
1056     gst_dvdemux_add_pads (dvdemux);
1057
1058   gst_adapter_push (dvdemux->adapter, buffer);
1059
1060   /* Apparently dv_parse_header can read from the body of the frame
1061    * too, so it needs more than header_size bytes. Wacky!
1062    */
1063   if (dvdemux->frame_len == -1) {
1064     /* if we don't know the length of a frame, we assume it is
1065      * the NTSC_BUFFER length, as this is enough to figure out 
1066      * if this is PAL or NTSC */
1067     dvdemux->frame_len = NTSC_BUFFER;
1068   }
1069
1070   /* and try to flush pending frames */
1071   ret = gst_dvdemux_flush (dvdemux);
1072
1073   gst_object_unref (dvdemux);
1074
1075   return ret;
1076 }
1077
1078 static GstStateChangeReturn
1079 gst_dvdemux_change_state (GstElement * element, GstStateChange transition)
1080 {
1081   GstDVDemux *dvdemux = GST_DVDEMUX (element);
1082   GstStateChangeReturn ret;
1083
1084
1085   switch (transition) {
1086     case GST_STATE_CHANGE_NULL_TO_READY:
1087       break;
1088     case GST_STATE_CHANGE_READY_TO_PAUSED:
1089       dvdemux->decoder = dv_decoder_new (0, FALSE, FALSE);
1090       dv_set_error_log (dvdemux->decoder, NULL);
1091       dvdemux->audio_offset = 0;
1092       dvdemux->video_offset = 0;
1093       dvdemux->framecount = 0;
1094       dvdemux->found_header = FALSE;
1095       dvdemux->frame_len = -1;
1096       dvdemux->timestamp = 0LL;
1097       dvdemux->need_segment = FALSE;
1098       dvdemux->new_media = FALSE;
1099       dvdemux->framerate_numerator = 0;
1100       dvdemux->framerate_denominator = 0;
1101       dvdemux->total_frames = 0;
1102       dvdemux->height = 0;
1103       dvdemux->frequency = 0;
1104       dvdemux->channels = 0;
1105       dvdemux->wide = FALSE;
1106       gst_segment_init (&dvdemux->byte_segment, GST_FORMAT_BYTES);
1107       gst_segment_init (&dvdemux->time_segment, GST_FORMAT_TIME);
1108       break;
1109     case GST_STATE_CHANGE_PAUSED_TO_PLAYING:
1110       break;
1111     default:
1112       break;
1113   }
1114
1115   ret = parent_class->change_state (element, transition);
1116
1117   switch (transition) {
1118     case GST_STATE_CHANGE_PLAYING_TO_PAUSED:
1119       break;
1120     case GST_STATE_CHANGE_PAUSED_TO_READY:
1121       gst_adapter_clear (dvdemux->adapter);
1122       dv_decoder_free (dvdemux->decoder);
1123       dvdemux->decoder = NULL;
1124       break;
1125     case GST_STATE_CHANGE_READY_TO_NULL:
1126       break;
1127     default:
1128       break;
1129   }
1130   return ret;
1131 }