1 #ifndef __EMOTION_GSTREAMER_H__
2 #define __EMOTION_GSTREAMER_H__
3 
4 #include <glib.h>
5 #include <gst/gst.h>
6 #include <glib-object.h>
7 #include <gst/video/gstvideosink.h>
8 #include <gst/video/video.h>
9 #include <gst/video/navigation.h>
10 #include <gst/audio/audio.h>
11 #include <gst/tag/tag.h>
12 #include <gst/pbutils/pbutils.h>
13 
14 #include <unistd.h>
15 #include <fcntl.h>
16 
17 #include <Eina.h>
18 #include <Evas.h>
19 #include <Ecore.h>
20 
21 #include "emotion_modules.h"
22 
23 typedef struct _Emotion_Convert_Info Emotion_Convert_Info;
24 
25 typedef void (*Evas_Video_Convert_Cb)(unsigned char *evas_data,
26                                       const unsigned char *gst_data,
27                                       unsigned int w,
28                                       unsigned int h,
29                                       unsigned int output_height,
30                                       Emotion_Convert_Info *info);
31 
32 typedef struct _EmotionVideoSinkPrivate EmotionVideoSinkPrivate;
33 typedef struct _EmotionVideoSink        EmotionVideoSink;
34 typedef struct _EmotionVideoSinkClass   EmotionVideoSinkClass;
35 typedef struct _Emotion_Gstreamer Emotion_Gstreamer;
36 typedef struct _Emotion_Gstreamer_Metadata Emotion_Gstreamer_Metadata;
37 typedef struct _Emotion_Gstreamer_Buffer Emotion_Gstreamer_Buffer;
38 typedef struct _Emotion_Gstreamer_Message Emotion_Gstreamer_Message;
39 
40 struct _Emotion_Convert_Info
41 {
42    unsigned int bpp[4];
43    unsigned int stride[4];
44    unsigned char *plane_ptr[4];
45 };
46 
47 struct _Emotion_Gstreamer_Metadata
48 {
49    char *title;
50    char *album;
51    char *artist;
52    char *genre;
53    char *comment;
54    char *year;
55    char *count;
56    char *disc_id;
57 };
58 
59 struct _Emotion_Gstreamer
60 {
61    const Emotion_Engine *api;
62 
63    volatile int     ref_count;
64 
65    const char       *subtitle;
66    /* Gstreamer elements */
67    GstElement       *pipeline;
68    GstElement       *vsink;
69 
70    Eina_List        *threads;
71 
72    /* Evas object */
73    Evas_Object      *obj;
74 
75    gulong            audio_buffer_probe;
76    GstPad           *audio_buffer_probe_pad;
77    gint              audio_buffer_probe_pending;
78 
79    /* Characteristics of stream */
80    double            position;
81    double            volume;
82 
83    Emotion_Gstreamer_Metadata *metadata;
84 
85    Emotion_Vis       vis;
86 
87    Eina_Bool         play         : 1;
88    Eina_Bool         video_mute   : 1;
89    Eina_Bool         audio_mute   : 1;
90    Eina_Bool         ready        : 1;
91    Eina_Bool         live         : 1;
92    Eina_Bool         buffering    : 1;
93    Eina_Bool         shutdown     : 1;
94 };
95 
96 struct _EmotionVideoSink {
97     /*< private >*/
98     GstVideoSink parent;
99     EmotionVideoSinkPrivate *priv;
100 };
101 
102 struct _EmotionVideoSinkClass {
103     /*< private >*/
104     GstVideoSinkClass parent_class;
105 };
106 
107 struct _EmotionVideoSinkPrivate {
108    Evas_Object *emotion_object;
109    Evas_Object *evas_object;
110 
111    GstVideoInfo info;
112    unsigned int eheight;
113    Evas_Colorspace eformat;
114    Evas_Video_Convert_Cb func;
115 
116    Eina_Lock m;
117    Eina_Condition c;
118 
119    Emotion_Gstreamer_Buffer *send;
120 
121     /* We need to keep a copy of the last inserted buffer as evas doesn't copy YUV data around */
122    GstBuffer        *last_buffer;
123    GstMapInfo        map_info;
124 
125    GstVideoFrame last_vframe;
126 
127    int frames;
128    int flapse;
129    double rtime;
130    double rlapse;
131 
132    // If this is TRUE all processing should finish ASAP
133    // This is necessary because there could be a race between
134    // unlock() and render(), where unlock() wins, signals the
135    // GCond, then render() tries to render a frame although
136    // everything else isn't running anymore. This will lead
137    // to deadlocks because render() holds the stream lock.
138    //
139    // Protected by the buffer mutex
140    Eina_Bool unlocked : 1;
141    Eina_Bool mapped : 1;
142    Eina_Bool vfmapped : 1;
143 };
144 
145 struct _Emotion_Gstreamer_Buffer
146 {
147    GstVideoFrame vframe;
148    EmotionVideoSink *sink;
149    GstBuffer *frame;
150    GstVideoInfo info;
151    Evas_Video_Convert_Cb func;
152    Evas_Colorspace eformat;
153    int eheight;
154    Eina_Bool vfmapped : 1;
155 };
156 
157 struct _Emotion_Gstreamer_Message
158 {
159    Emotion_Gstreamer *ev;
160 
161    GstMessage *msg;
162 };
163 
164 extern int _emotion_gstreamer_log_domain;
165 extern Eina_Bool debug_fps;
166 
167 #ifdef DBG
168 #undef DBG
169 #endif
170 #define DBG(...) EINA_LOG_DOM_DBG(_emotion_gstreamer_log_domain, __VA_ARGS__)
171 
172 #ifdef INF
173 #undef INF
174 #endif
175 #define INF(...) EINA_LOG_DOM_INFO(_emotion_gstreamer_log_domain, __VA_ARGS__)
176 
177 #ifdef WRN
178 #undef WRN
179 #endif
180 #define WRN(...) EINA_LOG_DOM_WARN(_emotion_gstreamer_log_domain, __VA_ARGS__)
181 
182 #ifdef ERR
183 #undef ERR
184 #endif
185 #define ERR(...) EINA_LOG_DOM_ERR(_emotion_gstreamer_log_domain, __VA_ARGS__)
186 
187 #ifdef CRI
188 #undef CRI
189 #endif
190 #define CRI(...) EINA_LOG_DOM_CRIT(_emotion_gstreamer_log_domain, __VA_ARGS__)
191 
192 #define EMOTION_TYPE_VIDEO_SINK emotion_video_sink_get_type()
193 
194 #define EMOTION_VIDEO_SINK(obj) \
195     (G_TYPE_CHECK_INSTANCE_CAST((obj), \
196     EMOTION_TYPE_VIDEO_SINK, EmotionVideoSink))
197 
198 #define EMOTION_VIDEO_SINK_CLASS(klass) \
199     (G_TYPE_CHECK_CLASS_CAST((klass), \
200     EMOTION_TYPE_VIDEO_SINK, EmotionVideoSinkClass))
201 
202 #define EMOTION_IS_VIDEO_SINK(obj) \
203     (G_TYPE_CHECK_INSTANCE_TYPE((obj), \
204     EMOTION_TYPE_VIDEO_SINK))
205 
206 #define EMOTION_IS_VIDEO_SINK_CLASS(klass) \
207     (G_TYPE_CHECK_CLASS_TYPE((klass), \
208     EMOTION_TYPE_VIDEO_SINK))
209 
210 #define EMOTION_VIDEO_SINK_GET_CLASS(obj) \
211     (G_TYPE_INSTANCE_GET_CLASS((obj), \
212     EMOTION_TYPE_VIDEO_SINK, EmotionVideoSinkClass))
213 
214 gboolean    gstreamer_plugin_init(GstPlugin *plugin);
215 
216 Emotion_Gstreamer_Buffer *emotion_gstreamer_buffer_alloc(EmotionVideoSink *sink,
217                                                          GstBuffer *buffer,
218                                                          GstVideoInfo *info,
219                                                          Evas_Colorspace eformat,
220                                                          int eheight,
221                                                          Evas_Video_Convert_Cb func);
222 void emotion_gstreamer_buffer_free(Emotion_Gstreamer_Buffer *send);
223 
224 Emotion_Gstreamer_Message *emotion_gstreamer_message_alloc(Emotion_Gstreamer *ev,
225                                                            GstMessage *msg);
226 void emotion_gstreamer_message_free(Emotion_Gstreamer_Message *send);
227 
228 Emotion_Gstreamer * emotion_gstreamer_ref (Emotion_Gstreamer *ev);
229 void emotion_gstreamer_unref (Emotion_Gstreamer *ev);
230 
231 typedef struct _ColorSpace_Format_Convertion ColorSpace_Format_Convertion;
232 
233 struct _ColorSpace_Format_Convertion
234 {
235    const char *name;
236    GstVideoFormat format;
237    GstVideoColorMatrix colormatrix;
238    Evas_Colorspace eformat;
239    Evas_Video_Convert_Cb func;
240    Eina_Bool force_height;
241 };
242 
243 extern const ColorSpace_Format_Convertion colorspace_format_convertion[];
244 
245 /* From gst-plugins-base/gst/playback */
246 typedef enum {
247   GST_PLAY_FLAG_VIDEO         = (1 << 0),
248   GST_PLAY_FLAG_AUDIO         = (1 << 1),
249   GST_PLAY_FLAG_TEXT          = (1 << 2),
250   GST_PLAY_FLAG_VIS           = (1 << 3),
251   GST_PLAY_FLAG_SOFT_VOLUME   = (1 << 4),
252   GST_PLAY_FLAG_NATIVE_AUDIO  = (1 << 5),
253   GST_PLAY_FLAG_NATIVE_VIDEO  = (1 << 6),
254   GST_PLAY_FLAG_DOWNLOAD      = (1 << 7),
255   GST_PLAY_FLAG_BUFFERING     = (1 << 8),
256   GST_PLAY_FLAG_DEINTERLACE   = (1 << 9),
257   GST_PLAY_FLAG_SOFT_COLORBALANCE = (1 << 10)
258 } GstPlayFlags;
259 
260 #endif /* __EMOTION_GSTREAMER_H__ */
261