1 /*
2     Copyright (C) 2012 Harald Sitter <sitter@kde.org>
3 
4     This library is free software; you can redistribute it and/or
5     modify it under the terms of the GNU Lesser General Public
6     License as published by the Free Software Foundation; either
7     version 2.1 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     Lesser General Public License for more details.
13 
14     You should have received a copy of the GNU Lesser General Public
15     License along with this library.  If not, see <http://www.gnu.org/licenses/>.
16 */
17 
18 #include "videomemorystream.h"
19 
20 #include "mediaplayer.h"
21 
22 namespace Phonon {
23 namespace VLC {
24 
p_this(void * opaque)25 static inline VideoMemoryStream *p_this(void *opaque) { return static_cast<VideoMemoryStream *>(opaque); }
p_this(void ** opaque)26 static inline VideoMemoryStream *p_this(void **opaque) { return static_cast<VideoMemoryStream *>(*opaque); }
27 #define P_THIS p_this(opaque)
28 
VideoMemoryStream()29 VideoMemoryStream::VideoMemoryStream()
30 {
31 }
32 
~VideoMemoryStream()33 VideoMemoryStream::~VideoMemoryStream()
34 {
35 }
36 
gcd(qint64 a,qint64 b)37 static inline qint64 gcd(qint64 a, qint64 b)
38 {
39     while( b )
40     {
41         qint64 c = a % b;
42         a = b;
43         b = c;
44     }
45     return a;
46 }
47 
lcm(int a,int b)48 static int lcm(int a, int b)
49 {
50     return a * b / GCD( a, b );
51 }
52 
setPitchAndLines(const vlc_chroma_description_t * desc,unsigned width,unsigned height,unsigned * pitches,unsigned * lines,unsigned * visiblePitches,unsigned * visibleLines)53 unsigned VideoMemoryStream::setPitchAndLines(const vlc_chroma_description_t *desc,
54                                              unsigned width, unsigned height,
55                                              unsigned *pitches, unsigned *lines,
56                                              unsigned *visiblePitches, unsigned *visibleLines)
57 {
58     // Mostly taken from vlc/src/misc/picture.c
59     // Simple alignment would be an option but I trust the VLC guys they know what they are doing.
60     int i_modulo_w = 1;
61     int i_modulo_h = 1;
62     unsigned int i_ratio_h  = 1;
63     for( unsigned i = 0; i < desc->plane_count; i++ )
64     {
65         i_modulo_w = lcm( i_modulo_w, 8 * desc->p[i].w.den );
66         i_modulo_h = lcm( i_modulo_h, 8 * desc->p[i].h.den );
67         if( i_ratio_h < desc->p[i].h.den )
68             i_ratio_h = desc->p[i].h.den;
69 
70     }
71     i_modulo_h = lcm( i_modulo_h, 32 );
72 
73     const int i_width_aligned  = ( width  + i_modulo_w - 1 ) / i_modulo_w * i_modulo_w;
74     const int i_height_aligned = ( height + i_modulo_h - 1 ) / i_modulo_h * i_modulo_h;
75     const int i_height_extra   = 2 * i_ratio_h; /* This one is a hack for some ASM functions */
76 
77     unsigned int bufferSize = 0;
78     for(unsigned i = 0; i < desc->plane_count; ++i)
79     {
80         pitches[i] = i_width_aligned * desc->p[i].w.num / desc->p[i].w.den * desc->pixel_size;
81         if (visiblePitches)
82             visiblePitches[i] = width * desc->p[i].w.num / desc->p[i].w.den * desc->pixel_size;
83 
84         lines[i] = (i_height_aligned + i_height_extra ) * desc->p[i].h.num / desc->p[i].h.den;
85         if (visibleLines)
86             visibleLines[i] = height * desc->p[i].h.num / desc->p[i].h.den;
87 
88         bufferSize += pitches[i] * lines[i];
89     }
90 
91     return bufferSize;
92 }
93 
setCallbacks(MediaPlayer * player)94 void VideoMemoryStream::setCallbacks(MediaPlayer *player)
95 {
96     libvlc_video_set_callbacks(player->libvlc_media_player(),
97                                lockCallbackInternal,
98                                unlockCallbackInternal,
99                                displayCallbackInternal,
100                                this);
101     libvlc_video_set_format_callbacks(player->libvlc_media_player(),
102                                       formatCallbackInternal,
103                                       formatCleanUpCallbackInternal);
104 }
105 
unsetCallbacks(MediaPlayer * player)106 void VideoMemoryStream::unsetCallbacks(MediaPlayer *player)
107 {
108     libvlc_video_set_callbacks(player->libvlc_media_player(),
109                                0,
110                                0,
111                                0,
112                                0);
113     libvlc_video_set_format_callbacks(player->libvlc_media_player(),
114                                       0,
115                                       0);
116 }
117 
118 
lockCallbackInternal(void * opaque,void ** planes)119 void *VideoMemoryStream::lockCallbackInternal(void *opaque, void **planes)
120 {
121     return P_THIS->lockCallback(planes);
122 }
123 
unlockCallbackInternal(void * opaque,void * picture,void * const * planes)124 void VideoMemoryStream::unlockCallbackInternal(void *opaque, void *picture, void *const*planes)
125 {
126     P_THIS->unlockCallback(picture, planes);
127 }
128 
displayCallbackInternal(void * opaque,void * picture)129 void VideoMemoryStream::displayCallbackInternal(void *opaque, void *picture)
130 {
131     P_THIS->displayCallback(picture);
132 }
133 
formatCallbackInternal(void ** opaque,char * chroma,unsigned * width,unsigned * height,unsigned * pitches,unsigned * lines)134 unsigned VideoMemoryStream::formatCallbackInternal(void **opaque, char *chroma,
135                                                    unsigned *width, unsigned *height,
136                                                    unsigned *pitches, unsigned *lines)
137 {
138     return P_THIS->formatCallback(chroma, width, height, pitches, lines);
139 }
140 
formatCleanUpCallbackInternal(void * opaque)141 void VideoMemoryStream::formatCleanUpCallbackInternal(void *opaque)
142 {
143     P_THIS->formatCleanUpCallback();
144 }
145 
146 } // namespace VLC
147 } // namespace Phonon
148