1 /*
2  * THEORA Plugin codec for OpenH323/OPAL
3  *
4  * Copyright (C) Matthias Schneider, All Rights Reserved
5  *
6  * This code is based on the file h261codec.cxx from the OPAL project released
7  * under the MPL 1.0 license which contains the following:
8  *
9  * Copyright (c) 1998-2000 Equivalence Pty. Ltd.
10  *
11  * The contents of this file are subject to the Mozilla Public License
12  * Version 1.0 (the "License"); you may not use this file except in
13  * compliance with the License. You may obtain a copy of the License at
14  * http://www.mozilla.org/MPL/
15  *
16  * Software distributed under the License is distributed on an "AS IS"
17  * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
18  * the License for the specific language governing rights and limitations
19  * under the License.
20  *
21  * The Original Code is Open H323 Library.
22  *
23  * The Initial Developer of the Original Code is Equivalence Pty. Ltd.
24  *
25  * Contributor(s): Matthias Schneider (ma30002000@yahoo.de)
26  *                 Michele Piccini (michele@piccini.com)
27  *                 Derek Smithies (derek@indranet.co.nz)
28  *
29  *
30  */
31 
32 /*
33   Notes
34   -----
35 
36  */
37 
38 #ifndef __THEORA_PLUGIN_H__
39 #define __THEORA_PLUGIN_H__ 1
40 
41 #include "plugin-config.h"
42 #include <stdarg.h>
43 #include <stdint.h>
44 #include <codec/opalplugin.h>
45 #include "theora_frame.h"
46 #include "critsect.h"
47 
48 extern "C" {
49   #include <theora/theora.h>
50 };
51 
52 #define CIF4_WIDTH 704
53 #define CIF4_HEIGHT 576
54 #define CIF_WIDTH 352
55 #define CIF_HEIGHT 288
56 #define QCIF_WIDTH 176
57 #define QCIF_HEIGHT 144
58 #define IT_QCIF 0
59 #define IT_CIF 1
60 
61 typedef unsigned char u_char;
62 
63 class theoraEncoderContext
64 {
65   public:
66     theoraEncoderContext ();
67     ~theoraEncoderContext ();
68 
69     void SetMaxRTPFrameSize (unsigned size);
70     void SetMaxKeyFramePeriod (unsigned period);
71     void SetTargetBitrate (unsigned rate);
72     void SetFrameRate (unsigned rate);
73     void SetFrameWidth (unsigned width);
74     void SetFrameHeight (unsigned height);
75     void ApplyOptions ();
76     void Lock ();
77     void Unlock ();
78 
79     int EncodeFrames (const u_char * src, unsigned & srcLen, u_char * dst, unsigned & dstLen, unsigned int & flags);
80 
81   protected:
82     void ApplyOptionsInternal ();
83     CriticalSection _mutex;
84 
85     theora_info _theoraInfo;
86     theora_state _theoraState;
87 
88     int _frameCounter;
89     theoraFrame* _txTheoraFrame;
90 };
91 
92 class theoraDecoderContext
93 {
94   public:
95     theoraDecoderContext();
96     ~theoraDecoderContext();
97     int DecodeFrames(const u_char * src, unsigned & srcLen, u_char * dst, unsigned & dstLen, unsigned int & flags);
98 
99   protected:
100     CriticalSection _mutex;
101 
102     theora_info _theoraInfo;
103     theora_state _theoraState;
104     theoraFrame* _rxTheoraFrame;
105 
106     bool _gotIFrame;
107     bool _gotAGoodFrame;
108     bool _gotHeader;
109     bool _gotTable;
110     int _frameCounter;
111 };
112 
113 const char* theoraErrorMessage(int code);
114 
115 static int valid_for_protocol    ( const struct PluginCodec_Definition *, void *, const char *,
116                                    void * parm, unsigned * parmLen);
117 static int get_codec_options     ( const struct PluginCodec_Definition * codec, void *, const char *,
118                                    void * parm, unsigned * parmLen);
119 static int free_codec_options    ( const struct PluginCodec_Definition *, void *, const char *,
120                                    void * parm, unsigned * parmLen);
121 
122 
123 static void * create_encoder     ( const struct PluginCodec_Definition *);
124 static void destroy_encoder      ( const struct PluginCodec_Definition *, void * _context);
125 static int codec_encoder         ( const struct PluginCodec_Definition *, void * _context,
126                                    const void * from, unsigned * fromLen,
127                                    void * to, unsigned * toLen,
128                                    unsigned int * flag);
129 static int to_normalised_options ( const struct PluginCodec_Definition *, void *, const char *,
130                                    void * parm, unsigned * parmLen);
131 static int to_customised_options ( const struct PluginCodec_Definition *, void *, const char *,
132                                    void * parm, unsigned * parmLen);
133 static int encoder_set_options   ( const struct PluginCodec_Definition *, void * _context, const char *,
134                                    void * parm, unsigned * parmLen);
135 static int encoder_get_output_data_size ( const PluginCodec_Definition *, void *, const char *,
136                                    void *, unsigned *);
137 
138 static void * create_decoder     ( const struct PluginCodec_Definition *);
139 static void destroy_decoder      ( const struct PluginCodec_Definition *, void * _context);
140 static int codec_decoder         ( const struct PluginCodec_Definition *, void * _context,
141                                    const void * from, unsigned * fromLen,
142                                    void * to, unsigned * toLen,
143                                    unsigned int * flag);
144 static int decoder_get_output_data_size ( const PluginCodec_Definition * codec, void *, const char *,
145                                    void *, unsigned *);
146 
147 ///////////////////////////////////////////////////////////////////////////////
148 
149 
150 static struct PluginCodec_information licenseInfo = {
151   1143692893,                                                   // timestamp = Thu 30 Mar 2006 04:28:13 AM UTC
152 
153   "Matthias Schneider",                                         // source code author
154   "1.0",                                                        // source code version
155   "ma30002000@yahoo.de",                                        // source code email
156   "",                                                           // source code URL
157   "Copyright (C) 2007 by Matthias Schneider",                   // source code copyright
158   "MPL 1.0",                                                    // source code license
159   PluginCodec_License_MPL,                                      // source code license
160 
161   "libtheora",                                                  // codec description
162   "",                                                           // codec author
163   "1.0 alpha7", 					        // codec version
164   "theora@xiph.org",                                            // codec email
165   "http://www.theora.org/", 		      		        // codec URL
166   "Xiph.Org Foundation http://www.xiph.org",                    // codec copyright information
167   "BSD-style",                                                  // codec license
168   PluginCodec_License_BSD                                       // codec license code
169 };
170 
171 /////////////////////////////////////////////////////////////////////////////
172 
173 static const char YUV420PDesc[]  = { "YUV420P" };
174 static const char theoraDesc[]   = { "theora" };
175 static const char sdpTHEORA[]    = { "theora" };
176 #define THEORA_CLOCKRATE        90000
177 #define THEORA_BITRATE         768000
178 #define THEORA_PAYLOAD_SIZE      1400
179 #define THEORA_FRAME_RATE          25
180 #define THEORA_KEY_FRAME_INTERVAL 125
181 
182 /////////////////////////////////////////////////////////////////////////////
183 
184 PLUGINCODEC_CONTROL_LOG_FUNCTION_DEF
185 
186 static PluginCodec_ControlDefn EncoderControls[] = {
187   { PLUGINCODEC_CONTROL_VALID_FOR_PROTOCOL,    valid_for_protocol },
188   { PLUGINCODEC_CONTROL_GET_CODEC_OPTIONS,     get_codec_options },
189   { PLUGINCODEC_CONTROL_FREE_CODEC_OPTIONS,    free_codec_options },
190   { PLUGINCODEC_CONTROL_TO_NORMALISED_OPTIONS, to_normalised_options },
191   { PLUGINCODEC_CONTROL_TO_CUSTOMISED_OPTIONS, to_customised_options },
192   { PLUGINCODEC_CONTROL_SET_CODEC_OPTIONS,     encoder_set_options },
193   { PLUGINCODEC_CONTROL_GET_OUTPUT_DATA_SIZE,  encoder_get_output_data_size },
194   PLUGINCODEC_CONTROL_LOG_FUNCTION_INC
195   { NULL }
196 };
197 
198 static PluginCodec_ControlDefn DecoderControls[] = {
199   { PLUGINCODEC_CONTROL_GET_CODEC_OPTIONS,     get_codec_options },
200   { PLUGINCODEC_CONTROL_GET_OUTPUT_DATA_SIZE,  decoder_get_output_data_size },
201   { NULL }
202 };
203 
204 static struct PluginCodec_Option const samplingOption =
205   { PluginCodec_StringOption, "CAP Sampling",  false, PluginCodec_EqualMerge, "YCbCr-4:2:0", "sampling", "YCbCr-4:2:0"};
206 
207 static struct PluginCodec_Option const widthOption =
208   { PluginCodec_IntegerOption, "CAP Width", false, PluginCodec_MinMerge, "704", "width", "15", 0, "15", "1280" };
209 
210 static struct PluginCodec_Option const heightOption =
211   { PluginCodec_IntegerOption, "CAP Height",  false, PluginCodec_MinMerge, "576", "height",  "15", 0, "15", "720" };
212 
213 static struct PluginCodec_Option const deliveryOption =
214   { PluginCodec_StringOption, "CAP Delivery",  false, PluginCodec_EqualMerge, "in_band", "delivery-method",  "in_band"};
215 
216 static struct PluginCodec_Option const minRxFrameWidth =
217   { PluginCodec_IntegerOption, PLUGINCODEC_OPTION_MIN_RX_FRAME_WIDTH,  true, PluginCodec_NoMerge, "176", NULL, NULL, 0, "16", "1280" };
218 static struct PluginCodec_Option const minRxFrameHeight =
219   { PluginCodec_IntegerOption, PLUGINCODEC_OPTION_MIN_RX_FRAME_HEIGHT, true, PluginCodec_NoMerge, "144", NULL, NULL, 0, "16", "720"  };
220 static struct PluginCodec_Option const maxRxFrameWidth =
221   { PluginCodec_IntegerOption, PLUGINCODEC_OPTION_MAX_RX_FRAME_WIDTH,  true, PluginCodec_NoMerge, "1280", NULL, NULL, 0, "16", "1280"  };
222 static struct PluginCodec_Option const maxRxFrameHeight =
223   { PluginCodec_IntegerOption, PLUGINCODEC_OPTION_MAX_RX_FRAME_HEIGHT, true, PluginCodec_NoMerge, "720", NULL, NULL, 0, "16", "720"  };
224 
225 
226 //configuration
227 
228 static struct PluginCodec_Option const * const optionTable[] = {
229   &samplingOption,
230   &widthOption,
231   &heightOption,
232   &deliveryOption,
233   &minRxFrameWidth,
234   &minRxFrameHeight,
235   &maxRxFrameWidth,
236   &maxRxFrameHeight,
237   NULL
238 };
239 
240 /////////////////////////////////////////////////////////////////////////////
241 
242 static struct PluginCodec_Definition theoraCodecDefn[2] = {
243 {
244   // SIP encoder#define NUM_DEFNS   (sizeof(theoraCodecDefn) / sizeof(struct PluginCodec_Definition))
245   PLUGIN_CODEC_VERSION_OPTIONS,       // codec API version
246   &licenseInfo,                       // license information
247 
248   PluginCodec_MediaTypeVideo |        // audio codec
249   PluginCodec_RTPTypeShared |         // specified RTP type
250   PluginCodec_RTPTypeDynamic,         // specified RTP type
251 
252   theoraDesc,                         // text decription
253   YUV420PDesc,                        // source format
254   theoraDesc,                         // destination format
255 
256   optionTable,                        // user data
257 
258   THEORA_CLOCKRATE,                   // samples per second
259   THEORA_BITRATE,                     // raw bits per second
260   20000,                              // nanoseconds per frame
261 
262   {{
263     CIF4_WIDTH,                       // frame width
264     CIF4_HEIGHT,                      // frame height
265     10,                               // recommended frame rate
266     60,                               // maximum frame rate
267   }},
268 
269   0,                                  // IANA RTP payload code
270   sdpTHEORA,                          // RTP payload name
271 
272   create_encoder,                     // create codec function
273   destroy_encoder,                    // destroy codec
274   codec_encoder,                      // encode/decode
275   EncoderControls,                    // codec controls
276 
277   PluginCodec_H323Codec_NoH323,       // h323CapabilityType
278   NULL                                // h323CapabilityData
279 },
280 {
281   // SIP decoder
282   PLUGIN_CODEC_VERSION_OPTIONS,       // codec API version
283   &licenseInfo,                       // license information
284 
285   PluginCodec_MediaTypeVideo |        // audio codec
286   PluginCodec_RTPTypeShared |         // specified RTP type
287   PluginCodec_RTPTypeDynamic,         // specified RTP type
288 
289   theoraDesc,                         // text decription
290   theoraDesc,                         // source format
291   YUV420PDesc,                        // destination format
292 
293   optionTable,                        // user data
294 
295   THEORA_CLOCKRATE,                   // samples per second
296   THEORA_BITRATE,                     // raw bits per second
297   20000,                              // nanoseconds per frame
298 
299 {{
300   CIF4_WIDTH,                         // frame width
301   CIF4_HEIGHT,                        // frame height
302   10,                                 // recommended frame rate
303   60,                                 // maximum frame rate
304 }},
305   0,                                  // IANA RTP payload code
306   sdpTHEORA,                          // RTP payload name
307 
308   create_decoder,                     // create codec function
309   destroy_decoder,                    // destroy codec
310   codec_decoder,                      // encode/decode
311   DecoderControls,                    // codec controls
312 
313   PluginCodec_H323Codec_NoH323,    // h323CapabilityType
314   NULL                                // h323CapabilityData
315 },
316 };
317 
318 #endif /* __THEORA_H__ */
319