avc: Save AVC objects in the GstAVCSrc object
[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 //#define ENABLE
41 #ifdef ENABLE
42 #include <AVCVideoServices/AVCVideoServices.h>
43 using namespace AVS;
44 #endif
45
46 #include <gst/gst.h>
47 #include <gst/base/gstbasesrc.h>
48 #include "gstavcsrc.h"
49
50 GST_DEBUG_CATEGORY_STATIC (gst_avc_src_debug_category);
51 #define GST_CAT_DEFAULT gst_avc_src_debug_category
52
53 /* prototypes */
54
55
56 static void gst_avc_src_set_property (GObject * object,
57     guint property_id, const GValue * value, GParamSpec * pspec);
58 static void gst_avc_src_get_property (GObject * object,
59     guint property_id, GValue * value, GParamSpec * pspec);
60 static void gst_avc_src_dispose (GObject * object);
61 static void gst_avc_src_finalize (GObject * object);
62
63 static GstCaps *gst_avc_src_get_caps (GstBaseSrc * src);
64 static gboolean gst_avc_src_start (GstBaseSrc * src);
65 static gboolean gst_avc_src_stop (GstBaseSrc * src);
66 static gboolean gst_avc_src_is_seekable (GstBaseSrc * src);
67 static gboolean gst_avc_src_unlock (GstBaseSrc * src);
68 static gboolean gst_avc_src_event (GstBaseSrc * src, GstEvent * event);
69 static GstFlowReturn
70 gst_avc_src_create (GstBaseSrc * src, guint64 offset, guint size,
71     GstBuffer ** buf);
72 static gboolean gst_avc_src_query (GstBaseSrc * src, GstQuery * query);
73 static gboolean gst_avc_src_unlock_stop (GstBaseSrc * src);
74
75 enum
76 {
77   PROP_0
78 };
79
80 /* pad templates */
81
82 static GstStaticPadTemplate gst_avc_src_src_template =
83     GST_STATIC_PAD_TEMPLATE ("src",
84     GST_PAD_SRC,
85     GST_PAD_ALWAYS,
86     GST_STATIC_CAPS
87     ("video/dv,systemstream=true;video/mpegts,systemstream=true,packetsize=188")
88     );
89
90
91 /* class initialization */
92
93 #define DEBUG_INIT(bla) \
94   GST_DEBUG_CATEGORY_INIT (gst_avc_src_debug_category, "avcsrc", 0, \
95       "debug category for avcsrc element");
96
97 GST_BOILERPLATE_FULL (GstAVCSrc, gst_avc_src, GstBaseSrc,
98     GST_TYPE_BASE_SRC, DEBUG_INIT);
99
100 static void
101 gst_avc_src_base_init (gpointer g_class)
102 {
103   GstElementClass *element_class = GST_ELEMENT_CLASS (g_class);
104
105   gst_element_class_add_pad_template (element_class,
106       gst_static_pad_template_get (&gst_avc_src_src_template));
107
108   gst_element_class_set_details_simple (element_class,
109       "AVC Video Services Source", "Video/Source",
110       "Captures DV or HDV video from Firewire port",
111       "David Schleef <ds@entropywave.com>");
112 }
113
114 static void
115 gst_avc_src_class_init (GstAVCSrcClass * klass)
116 {
117   GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
118   GstBaseSrcClass *base_src_class = GST_BASE_SRC_CLASS (klass);
119
120   gobject_class->set_property = gst_avc_src_set_property;
121   gobject_class->get_property = gst_avc_src_get_property;
122   gobject_class->dispose = gst_avc_src_dispose;
123   gobject_class->finalize = gst_avc_src_finalize;
124   base_src_class->get_caps = GST_DEBUG_FUNCPTR (gst_avc_src_get_caps);
125   base_src_class->start = GST_DEBUG_FUNCPTR (gst_avc_src_start);
126   base_src_class->stop = GST_DEBUG_FUNCPTR (gst_avc_src_stop);
127   base_src_class->is_seekable = GST_DEBUG_FUNCPTR (gst_avc_src_is_seekable);
128   base_src_class->unlock = GST_DEBUG_FUNCPTR (gst_avc_src_unlock);
129   base_src_class->event = GST_DEBUG_FUNCPTR (gst_avc_src_event);
130   base_src_class->create = GST_DEBUG_FUNCPTR (gst_avc_src_create);
131   if (0)
132     base_src_class->query = GST_DEBUG_FUNCPTR (gst_avc_src_query);
133   if (0)
134     base_src_class->unlock_stop = GST_DEBUG_FUNCPTR (gst_avc_src_unlock_stop);
135
136 }
137
138 static void
139 gst_avc_src_init (GstAVCSrc * avcsrc, GstAVCSrcClass * avcsrc_class)
140 {
141   gst_base_src_set_live (GST_BASE_SRC (avcsrc), TRUE);
142
143   avcsrc->srcpad = gst_pad_new_from_static_template (&gst_avc_src_src_template,
144       "src");
145
146   avcsrc->queue = gst_atomic_queue_new (16);
147   avcsrc->cond = g_cond_new ();
148   avcsrc->queue_lock = g_mutex_new ();
149 }
150
151 void
152 gst_avc_src_set_property (GObject * object, guint property_id,
153     const GValue * value, GParamSpec * pspec)
154 {
155   /* GstAVCSrc *avcsrc = GST_AVC_SRC (object); */
156
157   switch (property_id) {
158     default:
159       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
160       break;
161   }
162 }
163
164 void
165 gst_avc_src_get_property (GObject * object, guint property_id,
166     GValue * value, GParamSpec * pspec)
167 {
168   /* GstAVCSrc *avcsrc = GST_AVC_SRC (object); */
169
170   switch (property_id) {
171     default:
172       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
173       break;
174   }
175 }
176
177 void
178 gst_avc_src_dispose (GObject * object)
179 {
180   /* GstAVCSrc *avcsrc = GST_AVC_SRC (object); */
181
182   /* clean up as possible.  may be called multiple times */
183
184   G_OBJECT_CLASS (parent_class)->dispose (object);
185 }
186
187 void
188 gst_avc_src_finalize (GObject * object)
189 {
190   GstAVCSrc *avcsrc = GST_AVC_SRC (object);
191
192   /* clean up object here */
193   gst_atomic_queue_unref (avcsrc->queue);
194   g_cond_free (avcsrc->cond);
195   g_mutex_free (avcsrc->queue_lock);
196
197   G_OBJECT_CLASS (parent_class)->finalize (object);
198 }
199
200
201 static GstCaps *
202 gst_avc_src_get_caps (GstBaseSrc * src)
203 {
204   /* GstAVCSrc *avcsrc = GST_AVC_SRC (src); */
205
206   return gst_caps_from_string ("video/mpegts,systemstream=true,packetsize=188");
207 }
208
209 #define kNumCyclesInMPEGReceiverSegment 20
210 #define kNumSegmentsInMPEGReceiverProgram 100
211
212 #ifdef ENABLE
213 void
214 MPEGReceiverMessageReceivedProc (UInt32 msg, UInt32 param1, UInt32 param2,
215     void *pRefCon)
216 {
217
218 }
219
220 IOReturn
221 MyStructuredDataPushProc (UInt32 CycleDataCount,
222     MPEGReceiveCycleData * pCycleData, void *pRefCon)
223 {
224   GstAVCSrc *avcsrc = GST_AVC_SRC (pRefCon);
225
226   if (avcsrc) {
227     for (UInt32 cycle = 0; cycle < CycleDataCount; cycle++) {
228       for (UInt32 sourcePacket = 0; sourcePacket < pCycleData[cycle].tsPacketCount;
229           sourcePacket++) {
230         GstBuffer *buffer;
231
232         buffer = gst_buffer_new_and_alloc (kMPEG2TSPacketSize);
233         memcpy (GST_BUFFER_DATA (buffer),
234             pCycleData[cycle].pBuf[sourcePacket], kMPEG2TSPacketSize);
235
236         gst_atomic_queue_push (avcsrc->queue, buffer);
237       }
238     }
239
240     g_mutex_lock (avcsrc->queue_lock);
241     g_cond_signal (avcsrc->cond);
242     g_mutex_unlock (avcsrc->queue_lock);
243   }
244
245   return 0;
246 }
247 #endif
248
249 static gboolean
250 gst_avc_src_start (GstBaseSrc * src)
251 {
252   GstAVCSrc *avcsrc = GST_AVC_SRC (src);
253
254   GST_DEBUG_OBJECT (avcsrc, "start");
255
256   avcsrc->unlock = FALSE;
257
258 #ifdef ENABLE
259   // Create a AVCDeviceController
260   if (!avcsrc->pAVCDeviceController)
261     CreateAVCDeviceController (&avcsrc->pAVCDeviceController);
262   if (!avcsrc->pAVCDeviceController) {
263     // TODO: This should never happen (unless we've run out of memory), but we should handle it cleanly anyway
264     GST_ERROR ("Failed to create AVC device controller.");
265     return FALSE;
266   }
267
268   GST_INFO ("Created AVC device controller.");
269
270   if (avcsrc->deviceIndex >= CFArrayGetCount (avcsrc->pAVCDeviceController->avcDeviceArray)) {
271     GST_ERROR ("Failed to find AVC device %d", avcsrc->deviceIndex);
272     return FALSE;
273   }
274
275   avcsrc->pAVCDevice = (AVCDevice *)
276       CFArrayGetValueAtIndex (avcsrc->pAVCDeviceController->avcDeviceArray,
277       avcsrc->deviceIndex);
278
279   if (!avcsrc->pAVCDevice) {
280     GST_ERROR ("Failed to find AVC device %d", avcsrc->deviceIndex);
281     return FALSE;
282   }
283
284   GST_INFO ("Found device with GUID 0x%016llX\n", avcsrc->pAVCDevice->guid);
285
286   avcsrc->pAVCDevice->openDevice (nil, nil);
287
288   avcsrc->pAVCDeviceStream = avcsrc->pAVCDevice->CreateMPEGReceiverForDevicePlug (0, nil,       // We'll install the structured callback later (MyStructuredDataPushProc),
289       nil,
290       MPEGReceiverMessageReceivedProc,
291       nil,
292       nil, kNumCyclesInMPEGReceiverSegment, kNumSegmentsInMPEGReceiverProgram);
293
294   avcsrc->pAVCDeviceStream->pMPEGReceiver->registerStructuredDataPushCallback
295       (MyStructuredDataPushProc,
296       kNumCyclesInMPEGReceiverSegment, (void *) avcsrc);
297
298   avcsrc->pAVCDevice->StartAVCDeviceStream (avcsrc->pAVCDeviceStream);
299 #endif
300
301   return TRUE;
302 }
303
304 static gboolean
305 gst_avc_src_stop (GstBaseSrc * src)
306 {
307   GstAVCSrc *avcsrc = GST_AVC_SRC (src);
308   GstBuffer *buffer;
309
310   GST_DEBUG_OBJECT (avcsrc, "stop");
311
312   // Stop the stream
313   avcsrc->pAVCDevice->StopAVCDeviceStream(avcsrc->pAVCDeviceStream);
314   // Destroy the stream
315   avcsrc->pAVCDevice->DestroyAVCDeviceStream(avcsrc->pAVCDeviceStream);
316   avcsrc->pAVCDeviceStream = nil;
317
318   // Forget about the device (don't destroy it; pAVCDeviceController manages it)
319   avcsrc->pAVCDevice = nil;
320
321   while ((buffer = GST_BUFFER (gst_atomic_queue_pop (avcsrc->queue))) != NULL) {
322     gst_buffer_unref (buffer);
323   }
324
325   return TRUE;
326 }
327
328 static gboolean
329 gst_avc_src_is_seekable (GstBaseSrc * src)
330 {
331   GstAVCSrc *avcsrc = GST_AVC_SRC (src);
332
333   GST_DEBUG_OBJECT (avcsrc, "is_seekable");
334
335   return FALSE;
336 }
337
338 static gboolean
339 gst_avc_src_unlock (GstBaseSrc * src)
340 {
341   GstAVCSrc *avcsrc = GST_AVC_SRC (src);
342
343   GST_DEBUG_OBJECT (avcsrc, "unlock");
344
345   g_mutex_lock (avcsrc->queue_lock);
346   avcsrc->unlock = TRUE;
347   g_cond_signal (avcsrc->cond);
348   g_mutex_unlock (avcsrc->queue_lock);
349
350   return TRUE;
351 }
352
353 static gboolean
354 gst_avc_src_event (GstBaseSrc * src, GstEvent * event)
355 {
356   GstAVCSrc *avcsrc = GST_AVC_SRC (src);
357
358   GST_DEBUG_OBJECT (avcsrc, "event");
359
360   return TRUE;
361 }
362
363 static GstFlowReturn
364 gst_avc_src_create (GstBaseSrc * src, guint64 offset, guint size,
365     GstBuffer ** buf)
366 {
367   GstAVCSrc *avcsrc = GST_AVC_SRC (src);
368   GstBuffer *buffer;
369
370   GST_DEBUG_OBJECT (avcsrc, "create");
371
372   g_mutex_lock (avcsrc->queue_lock);
373   buffer = GST_BUFFER (gst_atomic_queue_pop (avcsrc->queue));
374   while (buffer == NULL && !avcsrc->unlock) {
375     g_cond_wait (avcsrc->cond, avcsrc->queue_lock);
376     buffer = GST_BUFFER (gst_atomic_queue_pop (avcsrc->queue));
377   }
378   g_mutex_unlock (avcsrc->queue_lock);
379
380   if (avcsrc->unlock) {
381     if (buffer)
382       gst_buffer_unref (buffer);
383     return GST_FLOW_WRONG_STATE;
384   }
385
386   gst_buffer_set_caps (buffer, GST_PAD_CAPS (avcsrc->srcpad));
387
388   *buf = buffer;
389
390   return GST_FLOW_OK;
391 }
392
393 static gboolean
394 gst_avc_src_query (GstBaseSrc * src, GstQuery * query)
395 {
396   GstAVCSrc *avcsrc = GST_AVC_SRC (src);
397
398   GST_DEBUG_OBJECT (avcsrc, "query");
399
400   return TRUE;
401 }
402
403 static gboolean
404 gst_avc_src_unlock_stop (GstBaseSrc * src)
405 {
406   GstAVCSrc *avcsrc = GST_AVC_SRC (src);
407
408   GST_DEBUG_OBJECT (avcsrc, "stop");
409
410   return TRUE;
411 }