h264parse: remove a check made useless by the last commit
[gstreamer-omap:gst-plugins-bad.git] / sys / avc / gstavcsrc.cpp
1 /* GStreamer
2  * Copyright (C) 2011 David Schleef <ds@entropywave.com>
3  *
4  * This library is free software; you can redistribute it and/or
5  * modify it under the terms of the GNU Library General Public
6  * License as published by the Free Software Foundation; either
7  * version 2 of the License, or (at your option) any later version.
8  *
9  * This library is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
12  * Library General Public License for more details.
13  *
14  * You should have received a copy of the GNU Library General Public
15  * License along with this library; if not, write to the
16  * Free Software Foundation, Inc., 51 Franklin Street, Suite 500,
17  * Boston, MA 02110-1335, USA.
18  */
19 /**
20  * SECTION:element-gstavcsrc
21  *
22  * The avcsrc element captures video from an OS/X AVC Video Services
23  * devices, typically a FireWire camera.
24  *
25  * <refsect2>
26  * <title>Example launch line</title>
27  * |[
28  * gst-launch -v avcsrc ! decodebin ! osxvideosink
29  * ]|
30  *
31  * This pipeline captures from an AVC source, decodes the stream (either
32  * DV or HDV), and displays the video.
33  * </refsect2>
34  */
35
36 #ifdef HAVE_CONFIG_H
37 #include "config.h"
38 #endif
39
40 #include <AVCVideoServices/AVCVideoServices.h>
41 using namespace AVS;
42
43 #include <gst/gst.h>
44 #include <gst/base/gstbasesrc.h>
45 #include "gstavcsrc.h"
46
47 GST_DEBUG_CATEGORY_STATIC (gst_avc_src_debug_category);
48 #define GST_CAT_DEFAULT gst_avc_src_debug_category
49
50 /* prototypes */
51
52
53 static void gst_avc_src_set_property (GObject * object,
54     guint property_id, const GValue * value, GParamSpec * pspec);
55 static void gst_avc_src_get_property (GObject * object,
56     guint property_id, GValue * value, GParamSpec * pspec);
57 static void gst_avc_src_dispose (GObject * object);
58 static void gst_avc_src_finalize (GObject * object);
59
60 static GstCaps *gst_avc_src_get_caps (GstBaseSrc * src);
61 static gboolean gst_avc_src_start (GstBaseSrc * src);
62 static gboolean gst_avc_src_stop (GstBaseSrc * src);
63 static gboolean gst_avc_src_is_seekable (GstBaseSrc * src);
64 static gboolean gst_avc_src_unlock (GstBaseSrc * src);
65 static gboolean gst_avc_src_event (GstBaseSrc * src, GstEvent * event);
66 static GstFlowReturn
67 gst_avc_src_create (GstBaseSrc * src, guint64 offset, guint size,
68     GstBuffer ** buf);
69 static gboolean gst_avc_src_query (GstBaseSrc * src, GstQuery * query);
70 static gboolean gst_avc_src_unlock_stop (GstBaseSrc * src);
71
72 enum
73 {
74   PROP_0
75 };
76
77 /* pad templates */
78
79 static GstStaticPadTemplate gst_avc_src_src_template =
80     GST_STATIC_PAD_TEMPLATE ("src",
81     GST_PAD_SRC,
82     GST_PAD_ALWAYS,
83     GST_STATIC_CAPS
84     ("video/dv,systemstream=true;video/mpegts,systemstream=true,packetsize=188")
85     );
86
87
88 /* class initialization */
89
90 #define DEBUG_INIT(bla) \
91   GST_DEBUG_CATEGORY_INIT (gst_avc_src_debug_category, "avcsrc", 0, \
92       "debug category for avcsrc element");
93
94 GST_BOILERPLATE_FULL (GstAVCSrc, gst_avc_src, GstBaseSrc,
95     GST_TYPE_BASE_SRC, DEBUG_INIT);
96
97 static void
98 gst_avc_src_base_init (gpointer g_class)
99 {
100   GstElementClass *element_class = GST_ELEMENT_CLASS (g_class);
101
102   gst_element_class_add_pad_template (element_class,
103       gst_static_pad_template_get (&gst_avc_src_src_template));
104
105   gst_element_class_set_details_simple (element_class,
106       "AVC Video Services Source", "Video/Source",
107       "Captures DV or HDV video from Firewire port",
108       "David Schleef <ds@entropywave.com>");
109 }
110
111 static void
112 gst_avc_src_class_init (GstAVCSrcClass * klass)
113 {
114   GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
115   GstBaseSrcClass *base_src_class = GST_BASE_SRC_CLASS (klass);
116
117   gobject_class->set_property = gst_avc_src_set_property;
118   gobject_class->get_property = gst_avc_src_get_property;
119   gobject_class->dispose = gst_avc_src_dispose;
120   gobject_class->finalize = gst_avc_src_finalize;
121   base_src_class->get_caps = GST_DEBUG_FUNCPTR (gst_avc_src_get_caps);
122   base_src_class->start = GST_DEBUG_FUNCPTR (gst_avc_src_start);
123   base_src_class->stop = GST_DEBUG_FUNCPTR (gst_avc_src_stop);
124   base_src_class->is_seekable = GST_DEBUG_FUNCPTR (gst_avc_src_is_seekable);
125   base_src_class->unlock = GST_DEBUG_FUNCPTR (gst_avc_src_unlock);
126   base_src_class->event = GST_DEBUG_FUNCPTR (gst_avc_src_event);
127   base_src_class->create = GST_DEBUG_FUNCPTR (gst_avc_src_create);
128   if (0)
129     base_src_class->query = GST_DEBUG_FUNCPTR (gst_avc_src_query);
130   if (0)
131     base_src_class->unlock_stop = GST_DEBUG_FUNCPTR (gst_avc_src_unlock_stop);
132
133 }
134
135 static void
136 gst_avc_src_init (GstAVCSrc * avcsrc, GstAVCSrcClass * avcsrc_class)
137 {
138   gst_base_src_set_live (GST_BASE_SRC (avcsrc), TRUE);
139
140   avcsrc->srcpad = gst_pad_new_from_static_template (&gst_avc_src_src_template,
141       "src");
142
143   avcsrc->queue = gst_atomic_queue_new (16);
144   avcsrc->cond = g_cond_new ();
145   avcsrc->queue_lock = g_mutex_new ();
146 }
147
148 void
149 gst_avc_src_set_property (GObject * object, guint property_id,
150     const GValue * value, GParamSpec * pspec)
151 {
152   /* GstAVCSrc *avcsrc = GST_AVC_SRC (object); */
153
154   switch (property_id) {
155     default:
156       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
157       break;
158   }
159 }
160
161 void
162 gst_avc_src_get_property (GObject * object, guint property_id,
163     GValue * value, GParamSpec * pspec)
164 {
165   /* GstAVCSrc *avcsrc = GST_AVC_SRC (object); */
166
167   switch (property_id) {
168     default:
169       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
170       break;
171   }
172 }
173
174 void
175 gst_avc_src_dispose (GObject * object)
176 {
177   /* GstAVCSrc *avcsrc = GST_AVC_SRC (object); */
178
179   /* clean up as possible.  may be called multiple times */
180
181   G_OBJECT_CLASS (parent_class)->dispose (object);
182 }
183
184 void
185 gst_avc_src_finalize (GObject * object)
186 {
187   GstAVCSrc *avcsrc = GST_AVC_SRC (object);
188
189   /* clean up object here */
190   gst_atomic_queue_unref (avcsrc->queue);
191   g_cond_free (avcsrc->cond);
192   g_mutex_free (avcsrc->queue_lock);
193
194   G_OBJECT_CLASS (parent_class)->finalize (object);
195 }
196
197
198 static GstCaps *
199 gst_avc_src_get_caps (GstBaseSrc * src)
200 {
201   /* GstAVCSrc *avcsrc = GST_AVC_SRC (src); */
202
203   return gst_caps_from_string ("video/mpegts,systemstream=true,packetsize=188");
204 }
205
206 #define kNumCyclesInMPEGReceiverSegment 200
207 #define kNumSegmentsInMPEGReceiverProgram 10
208
209 void
210 MPEGReceiverMessageReceivedProc (UInt32 msg, UInt32 param1, UInt32 param2,
211     void *pRefCon)
212 {
213
214 }
215
216 IOReturn
217 MyStructuredDataPushProc (UInt32 CycleDataCount,
218     MPEGReceiveCycleData * pCycleData, void *pRefCon)
219 {
220   GstAVCSrc *avcsrc = GST_AVC_SRC (pRefCon);
221
222   if (avcsrc) {
223     UInt32 numPackets = 0;
224     for (UInt32 cycle = 0; cycle < CycleDataCount; cycle++)
225       numPackets += pCycleData[cycle].tsPacketCount;
226     GstBuffer *buffer;
227
228     buffer = gst_buffer_new_and_alloc (numPackets*kMPEG2TSPacketSize);
229
230     guint8 *data = GST_BUFFER_DATA (buffer);
231
232     for (UInt32 cycle = 0; cycle < CycleDataCount; cycle++) {
233       GST_LOG("Received cycle %lu of %lu - %lu packets (fw time %lx)",
234               cycle, CycleDataCount, pCycleData[cycle].tsPacketCount,
235               pCycleData[cycle].fireWireTimeStamp);
236       for (UInt32 sourcePacket = 0; sourcePacket < pCycleData[cycle].tsPacketCount;
237           sourcePacket++) {
238         memcpy (data,
239             pCycleData[cycle].pBuf[sourcePacket], kMPEG2TSPacketSize);
240         data += kMPEG2TSPacketSize;
241
242         avcsrc->packets_enqueued++;
243       }
244     }
245
246     gst_atomic_queue_push (avcsrc->queue, buffer);
247
248     g_mutex_lock (avcsrc->queue_lock);
249     g_cond_signal (avcsrc->cond);
250     g_mutex_unlock (avcsrc->queue_lock);
251   }
252
253   return 0;
254 }
255
256 static gboolean
257 gst_avc_src_start (GstBaseSrc * src)
258 {
259   GstAVCSrc *avcsrc = GST_AVC_SRC (src);
260
261   GST_DEBUG_OBJECT (avcsrc, "start");
262
263   avcsrc->unlock = FALSE;
264
265   // Create a AVCDeviceController
266   if (!avcsrc->pAVCDeviceController)
267     CreateAVCDeviceController (&avcsrc->pAVCDeviceController);
268   if (!avcsrc->pAVCDeviceController) {
269     // TODO: This should never happen (unless we've run out of memory), but we should handle it cleanly anyway
270     GST_ERROR ("Failed to create AVC device controller.");
271     return FALSE;
272   }
273
274   GST_INFO ("Created AVC device controller.");
275
276   if (avcsrc->deviceIndex >= CFArrayGetCount (avcsrc->pAVCDeviceController->avcDeviceArray)) {
277     GST_ERROR ("Failed to find AVC device %d", avcsrc->deviceIndex);
278     return FALSE;
279   }
280
281   avcsrc->pAVCDevice = (AVCDevice *)
282       CFArrayGetValueAtIndex (avcsrc->pAVCDeviceController->avcDeviceArray,
283       avcsrc->deviceIndex);
284
285   if (!avcsrc->pAVCDevice) {
286     GST_ERROR ("Failed to find AVC device %d", avcsrc->deviceIndex);
287     return FALSE;
288   }
289
290   GST_INFO ("Found device with GUID 0x%016llX\n", avcsrc->pAVCDevice->guid);
291
292   avcsrc->pAVCDevice->openDevice (nil, nil);
293
294   avcsrc->pAVCDeviceStream = avcsrc->pAVCDevice->CreateMPEGReceiverForDevicePlug (0, nil,       // We'll install the structured callback later (MyStructuredDataPushProc),
295       nil,
296       MPEGReceiverMessageReceivedProc,
297       nil,
298       nil, kNumCyclesInMPEGReceiverSegment, kNumSegmentsInMPEGReceiverProgram);
299
300   avcsrc->pAVCDeviceStream->pMPEGReceiver->registerStructuredDataPushCallback
301       (MyStructuredDataPushProc,
302       kNumCyclesInMPEGReceiverSegment, (void *) avcsrc);
303
304   avcsrc->pAVCDevice->StartAVCDeviceStream (avcsrc->pAVCDeviceStream);
305
306   return TRUE;
307 }
308
309 static gboolean
310 gst_avc_src_stop (GstBaseSrc * src)
311 {
312   GstAVCSrc *avcsrc = GST_AVC_SRC (src);
313   GstBuffer *buffer;
314
315   GST_DEBUG_OBJECT (avcsrc, "stop");
316
317   // Stop the stream
318   avcsrc->pAVCDevice->StopAVCDeviceStream(avcsrc->pAVCDeviceStream);
319   // Destroy the stream
320   avcsrc->pAVCDevice->DestroyAVCDeviceStream(avcsrc->pAVCDeviceStream);
321   avcsrc->pAVCDeviceStream = nil;
322
323   // Forget about the device (don't destroy it; pAVCDeviceController manages it)
324   avcsrc->pAVCDevice = nil;
325
326   GST_DEBUG("Packets enqueued = %llu", avcsrc->packets_enqueued);
327   GST_DEBUG("Packets dequeued = %llu", avcsrc->packets_dequeued);
328
329   while ((buffer = GST_BUFFER (gst_atomic_queue_pop (avcsrc->queue))) != NULL) {
330     gst_buffer_unref (buffer);
331   }
332
333   return TRUE;
334 }
335
336 static gboolean
337 gst_avc_src_is_seekable (GstBaseSrc * src)
338 {
339   GstAVCSrc *avcsrc = GST_AVC_SRC (src);
340
341   GST_DEBUG_OBJECT (avcsrc, "is_seekable");
342
343   return FALSE;
344 }
345
346 static gboolean
347 gst_avc_src_unlock (GstBaseSrc * src)
348 {
349   GstAVCSrc *avcsrc = GST_AVC_SRC (src);
350
351   GST_DEBUG_OBJECT (avcsrc, "unlock");
352
353   g_mutex_lock (avcsrc->queue_lock);
354   avcsrc->unlock = TRUE;
355   g_cond_signal (avcsrc->cond);
356   g_mutex_unlock (avcsrc->queue_lock);
357
358   return TRUE;
359 }
360
361 static gboolean
362 gst_avc_src_event (GstBaseSrc * src, GstEvent * event)
363 {
364   GstAVCSrc *avcsrc = GST_AVC_SRC (src);
365
366   GST_DEBUG_OBJECT (avcsrc, "event of type '%s'", GST_EVENT_TYPE_NAME(event));
367
368   GST_DEBUG("Packets enqueued = %llu, dequeued = %llu",
369             avcsrc->packets_enqueued, avcsrc->packets_dequeued);
370
371   return TRUE;
372 }
373
374 static GstFlowReturn
375 gst_avc_src_create (GstBaseSrc * src, guint64 offset, guint size,
376     GstBuffer ** buf)
377 {
378   GstAVCSrc *avcsrc = GST_AVC_SRC (src);
379   GstBuffer *buffer;
380
381   GST_DEBUG_OBJECT (avcsrc, "create");
382
383   g_mutex_lock (avcsrc->queue_lock);
384   buffer = GST_BUFFER (gst_atomic_queue_pop (avcsrc->queue));
385   while (buffer == NULL && !avcsrc->unlock) {
386     g_cond_wait (avcsrc->cond, avcsrc->queue_lock);
387     buffer = GST_BUFFER (gst_atomic_queue_pop (avcsrc->queue));
388   }
389   g_mutex_unlock (avcsrc->queue_lock);
390
391   if (avcsrc->unlock) {
392     if (buffer)
393       gst_buffer_unref (buffer);
394     return GST_FLOW_WRONG_STATE;
395   }
396
397   gst_buffer_set_caps (buffer, GST_PAD_CAPS (avcsrc->srcpad));
398
399   *buf = buffer;
400
401   avcsrc->packets_dequeued++;
402
403   return GST_FLOW_OK;
404 }
405
406 static gboolean
407 gst_avc_src_query (GstBaseSrc * src, GstQuery * query)
408 {
409   GstAVCSrc *avcsrc = GST_AVC_SRC (src);
410
411   GST_DEBUG_OBJECT (avcsrc, "query");
412
413   return TRUE;
414 }
415
416 static gboolean
417 gst_avc_src_unlock_stop (GstBaseSrc * src)
418 {
419   GstAVCSrc *avcsrc = GST_AVC_SRC (src);
420
421   GST_DEBUG_OBJECT (avcsrc, "stop");
422
423   return TRUE;
424 }