1 /*
2  * MPEG4 Plugin codec for OpenH323/OPAL
3  * This code is based on the H.263 plugin implementation in OPAL.
4  *
5  * The original files, and this version of the original code, are released under the same
6  * MPL 1.0 license. Substantial portions of the original code were contributed
7  * by Salyens and March Networks and their right to be identified as copyright holders
8  * of the original code portions and any parts now included in this new copy is asserted through
9  * their inclusion in the copyright notices below.
10  *
11  * Copyright (C) 2007 Canadian Bank Note, Limited
12  * Copyright (C) 2006 Post Increment
13  * Copyright (C) 2005 Salyens
14  * Copyright (C) 2001 March Networks Corporation
15  * Copyright (C) 1999-2000 Equivalence Pty. Ltd.
16  *
17  * The contents of this file are subject to the Mozilla Public License
18  * Version 1.0 (the "License"); you may not use this file except in
19  * compliance with the License. You may obtain a copy of the License at
20  * http://www.mozilla.org/MPL/
21  *
22  * Software distributed under the License is distributed on an "AS IS"
23  * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
24  * the License for the specific language governing rights and limitations
25  * under the License.
26  *
27  * The Original Code is Open H323 Library.
28  *
29  * The Initial Developer of the Original Code is Equivalence Pty. Ltd.
30  *
31  * Contributor(s): Josh Mahonin (jmahonin@cbnco.com)
32  *                 Michael Smith (msmith@cbnco.com)
33  *                 Guilhem Tardy (gtardy@salyens.com)
34  *                 Craig Southeren (craigs@postincrement.com)
35  *                 Matthias Schneider (ma30002000@yahoo.de)
36  *
37  * NOTES:
38  * Initial implementation of MPEG4 codec plugin using ffmpeg.
39  * Untested under Windows or H.323
40  *
41  * $Revision: 28116 $
42  * $Author: rjongbloed $
43  * $Date: 2012-07-30 22:59:39 -0500 (Mon, 30 Jul 2012) $
44  */
45 
46 /*
47   Notes
48   -----
49 
50   This codec implements an MPEG4 encoder/decoder using the ffmpeg library
51   (http://ffmpeg.mplayerhq.hu/).  Plugin infrastructure is based off of the
52   H.263 plugin and MPEG4 codec functions originally created by Michael Smith.
53 
54  */
55 
56 // Plugin specific
57 #define _CRT_SECURE_NO_DEPRECATE
58 
59 #ifndef _MSC_VER
60 #include "plugin-config.h"
61 #endif
62 
63 #include "dyna.h"
64 #include "rtpframe.h"
65 
66 #include <codec/opalplugin.hpp>
67 
68 extern "C" {
69 PLUGIN_CODEC_IMPLEMENT(FFMPEG_MPEG4)
70 };
71 
72 
73 typedef unsigned char BYTE;
74 
75 // Needed C++ headers
76 #include <string.h>
77 #include <stdint.h>             // for uint8_t
78 #include <math.h>               // for rint() in dsputil.h
79 #include <assert.h>
80 #include <stdio.h>
81 #include <iostream>
82 #include <deque>
83 
84 using namespace std;
85 
86 // FFMPEG specific headers
87 extern "C" {
88 
89 // Public ffmpeg headers.
90 // We'll pull them in from their locations in the ffmpeg source tree,
91 // but it would be possible to get them all from /usr/include/ffmpeg
92 // with #include <ffmpeg/...h>.
93 #ifdef LIBAVCODEC_HAVE_SOURCE_DIR
94 #include <libavutil/common.h>
95 #include <libavcodec/avcodec.h>
96 #include <libavutil/avutil.h>
97 #include <libavutil/log.h>
98 
99 // Private headers from the ffmpeg source tree.
100 #include <libavutil/intreadwrite.h>
101 #include <libavutil/bswap.h>
102 #include <libavcodec/mpegvideo.h>
103 
104 #else /* LIBAVCODEC_HAVE_SOURCE_DIR */
105 #include "../common/ffmpeg.h"
106 #include <libavutil/opt.h>
107 #endif /* LIBAVCODEC_HAVE_SOURCE_DIR */
108 }
109 
110 #define RTP_DYNAMIC_PAYLOAD  96
111 
112 #define MPEG4_CLOCKRATE     90000
113 #define MPEG4_BITRATE       3000000
114 
115 #define CIF_WIDTH       352
116 #define CIF_HEIGHT      288
117 
118 #define CIF4_WIDTH      (CIF_WIDTH*2)
119 #define CIF4_HEIGHT     (CIF_HEIGHT*2)
120 
121 #define CIF16_WIDTH     (CIF_WIDTH*4)
122 #define CIF16_HEIGHT    (CIF_HEIGHT*4)
123 
124 #define QCIF_WIDTH     (CIF_WIDTH/2)
125 #define QCIF_HEIGHT    (CIF_HEIGHT/2)
126 
127 #define SQCIF_WIDTH     128
128 #define SQCIF_HEIGHT    96
129 
130 #define MAX_MPEG4_PACKET_SIZE     2048
131 
132 static const char ProfileAndLevel[] = "Profile & Level";
133 
134 const static struct mpeg4_profile_level {
135     unsigned profileLevel;
136     const char* profileName;
137     unsigned profileNumber;
138     unsigned level;
139     unsigned maxQuantTables;       /* Max. unique quant. tables */
140     unsigned maxVMVBufferSize;     /* max. VMV buffer size(MB units) */
141     unsigned frame_size;           /* max. VCV buffer size (MB) */
142     unsigned mbps;                 /* VCV decoder rate (MB/s) 4 */
143     unsigned boundaryMbps;         /* VCV boundary MB decoder rate (MB/s)9 */
144     unsigned maxBufferSize;        /* max. total VBV buffer size (units of 16384 bits) */
145     unsigned maxVOLBufferSize;     /* max. VOL VBV buffer size (units of 16384 bits) */
146     unsigned maxVideoPacketLength; /* max. video packet length (bits) */
147     long unsigned bitrate;
148 } mpeg4_profile_levels[] = {
149     {   1, "Simple",                     1, 1, 1,   198,    99,   1485,      0,  10,  10,  2048,    64000 },
150     {   2, "Simple",                     1, 2, 1,   792,   396,   5940,      0,  40,  40,  4096,   128000 },
151     {   3, "Simple",                     1, 3, 1,   792,   396,  11880,      0,  40,  40,  8192,   384000 },
152     {   4, "Simple",                     1, 4, 1,  2400,  1200,  36000,      0,  80,  80, 16384,  4000000 }, // is really 4a
153     {   5, "Simple",                     1, 5, 1,  3240,  1620,  40500,      0, 112, 112, 16384,  8000000 },
154     {   8, "Simple",                     1, 0, 1,   198,    99,   1485,      0,  10,  10,  2048,    64000 },
155     {   9, "Simple",                     1, 0, 1,   198,    99,   1485,      0,  20,  20,  2048,   128000 }, // 0b
156     {  17, "Simple Scalable",            2, 1, 1,  1782,   495,   7425,      0,  40,  40,  2048,   128000 },
157     {  18, "Simple Scalable",            2, 2, 1,  3168,   792,  23760,      0,  40,  40,  4096,   256000 },
158     {  33, "Core",                       3, 1, 4,   594,   198,   5940,   2970,  16,  16,  4096,   384000 },
159     {  34, "Core",                       3, 2, 4,  2376,   792,  23760,  11880,  80,  80,  8192,  2000000 },
160     {  50, "Main",                       4, 2, 4,  3960,  1188,  23760,  11880,  80,  80,  8192,  2000000 },
161     {  51, "Main",                       4, 3, 4, 11304,  3240,  97200,  48600, 320, 320, 16384, 15000000 },
162     {  52, "Main",                       4, 4, 4, 65344, 16320, 489600, 244800, 760, 760, 16384, 38400000 },
163     {  66, "N-Bit",                      5, 2, 4,  2376,   792,  23760,  11880,  80,  80,  8192,  2000000 },
164     { 145, "Advanced Real Time Simple",  6, 1, 1,   198,    99,   1485,      0,  10,  10,  8192,    64000 },
165     { 146, "Advanced Real Time Simple",  6, 2, 1,   792,   396,   5940,      0,  40,  40, 16384,   128000 },
166     { 147, "Advanced Real Time Simple",  6, 3, 1,   792,   396,  11880,      0,  40,  40, 16384,   384000 },
167     { 148, "Advanced Real Time Simple",  6, 4, 1,   792,   396,  11880,      0,  80,  80, 16384,  2000000 },
168     { 161, "Core Scalable",              7, 1, 4,  2376,   792,  14850,   7425,  64,  64,  4096,   768000 },
169     { 162, "Core Scalable",              7, 2, 4,  2970,   990,  29700,  14850,  80,  80,  4096,  1500000 },
170     { 163, "Core Scalable",              7, 3, 4, 12906,  4032, 120960,  60480,  80,  80, 16384,  4000000 },
171     { 177, "Advanced Coding Efficiency", 8, 1, 4,  1188,   792,  11880,   5940,  40,  40,  8192,   384000 },
172     { 178, "Advanced Coding Efficiency", 8, 2, 4,  2376,  1188,  23760,  11880,  80,  80,  8192,  2000000 },
173     { 179, "Advanced Coding Efficiency", 8, 3, 4,  9720,  3240,  97200,  48600, 320, 320, 16384, 15000000 },
174     { 180, "Advanced Coding Efficiency", 8, 4, 4, 48960, 16320, 489600, 244800, 760, 760, 16384, 38400000 },
175     { 193, "Advanced Core",              9, 1, 4,   594,   198,   5940,   2970,  16,   8,  4096,   384000 },
176     { 194, "Advanced Core",              9, 2, 4,  2376,   792,  23760,  11880,  80,  40,  8192,  2000000 },
177     { 240, "Advanced Simple",           10, 0, 1,   297,    99,   2970,    100,  10,  10,  2048,   128000 },
178     { 241, "Advanced Simple",           10, 1, 1,   297,    99,   2970,    100,  10,  10,  2048,   128000 },
179     { 242, "Advanced Simple",           10, 2, 1,  1188,   396,   5940,    100,  40,  40,  4096,   384000 },
180     { 243, "Advanced Simple",           10, 3, 1,  1188,   396,  11880,    100,  40,  40,  4096,   768000 },
181     { 244, "Advanced Simple",           10, 4, 1,  2376,   792,  23760,     50,  80,  80,  8192,  3000000 },
182     { 245, "Advanced Simple",           10, 5, 1,  4860,  1620,  48600,     25, 112, 112, 16384,  8000000 },
183     { 0 }
184 };
185 
186 // This table is used in order to select a different resolution if the desired one
187 // consists of more macroblocks than the level limit
188 const static struct mpeg4_resolution {
189     unsigned width;
190     unsigned height;
191     unsigned macroblocks;
192 } mpeg4_resolutions[] = {
193     { 1920, 1088, 8160 },
194     { 1600, 1200, 7500 },
195     { 1408, 1152, 6336 },
196     { 1280, 1024, 5120 },
197     { 1280,  720, 3600 },
198     { 1024,  768, 3072 },
199     {  800,  600, 1900 },
200     {  704,  576, 1584 },
201     {  640,  480, 1200 },
202     {  352,  288,  396 },
203     {  320,  240,  300 },
204     {  176,  144,   99 },
205     {  128,   96,   48 },
206     { 0 }
207 };
208 
209 FFMPEGLibrary FFMPEGLibraryInstance(AV_CODEC_ID_MPEG4);
210 
211 
mpeg4IsIframe(BYTE * frameBuffer,unsigned int frameLen)212 static bool mpeg4IsIframe (BYTE * frameBuffer, unsigned int frameLen )
213 {
214   bool isIFrame = false;
215   unsigned i = 0;
216   while ((i+4)<= frameLen) {
217     if ((frameBuffer[i] == 0) && (frameBuffer[i+1] == 0) && (frameBuffer[i+2] == 1)) {
218       if (frameBuffer[i+3] == 0xb0)
219         PTRACE(4, "MPEG4", "Found visual_object_sequence_start_code, Profile/Level is " << (unsigned) frameBuffer[i+4]);
220       if (frameBuffer[i+3] == 0xb6) {
221         unsigned vop_coding_type = (unsigned) ((frameBuffer[i+4] & 0xC0) >> 6);
222         PTRACE(4, "MPEG4", "Found vop_start_code, is vop_coding_type is " << vop_coding_type );
223         if (vop_coding_type == 0)
224           isIFrame = true;
225         return isIFrame;
226       }
227     }
228     i++;
229   }
230   return isIFrame;
231 }
232 
233 /////////////////////////////////////////////////////////////////////////////
234 //
235 // define the encoding context
236 //
237 
238 class MPEG4EncoderContext
239 {
240   public:
241 
242     MPEG4EncoderContext();
243     ~MPEG4EncoderContext();
244 
245     int EncodeFrames(const BYTE * src, unsigned & srcLen,
246                      BYTE * dst, unsigned & dstLen, unsigned int & flags);
247     static void RtpCallback(AVCodecContext *ctx, void *data, int data_size,
248                             int num_mb);
249 
250     void SetIQuantFactor(float newFactor);
251     void SetKeyframeUpdatePeriod(int interval);
252     void SetMaxBitrate(int max);
253     void SetFPS(int frameTime);
254     void SetFrameHeight(int height);
255     void SetFrameWidth(int width);
256     void SetQMin(int qmin);
257     void SetTSTO(unsigned tsto);
258     void SetProfileLevel (unsigned profileLevel);
259     int GetFrameBytes();
260 
261   protected:
262     bool OpenCodec();
263     void CloseCodec();
264 
265     // sets encoding paramters
266     void SetDynamicEncodingParams(bool restartOnResize);
267     void SetStaticEncodingParams();
268     void ResizeEncodingFrame(bool restartCodec);
269 
270     // reset libavcodec rate control
271     void ResetBitCounter(int spread);
272 
273     // Modifiable quantization factor.  Defaults to -0.8
274     float m_iQuantFactor;
275 
276     // Max VBV buffer size in bits.
277     unsigned m_maxBufferSize;
278 
279     // Interval in seconds between forced IFrame updates if enabled
280     int m_keyframeUpdatePeriod;
281 
282 
283     // Modifiable upper limit for bits/s transferred
284     int m_bitRateHighLimit;
285 
286     // Frames per second.  Defaults to 24.
287     int m_targetFPS;
288 
289     // packet sizes generating in RtpCallback
290     deque<unsigned> m_packetSizes;
291     unsigned m_lastPktOffset;
292 
293     // raw and encoded frame buffers
294     BYTE * m_encFrameBuffer;
295     unsigned int m_encFrameLen;
296     BYTE * m_rawFrameBuffer;
297     unsigned int m_rawFrameLen;
298 
299     // codec, context and picture
300     AVCodec        * m_avcodec;
301     AVCodecContext * m_avcontext;
302     AVFrame        * m_avpicture;
303 
304     // encoding and frame settings
305     unsigned m_videoTSTO;
306     int m_videoQMin; // dynamic video quality min/max limits, 1..31
307 
308     int m_frameNum;
309     unsigned int m_frameWidth;
310     unsigned int m_frameHeight;
311 
312     unsigned long m_lastTimeStamp;
313     bool m_isIFrame;
314 
315     enum StdSize {
316       SQCIF,
317       QCIF,
318       CIF,
319       CIF4,
320       CIF16,
321       NumStdSizes,
322       UnknownStdSize = NumStdSizes
323     };
324 
GetStdSize(int width,int height)325     static int GetStdSize(int width, int height)
326     {
327       static struct {
328         int width;
329         int height;
330       } StandardVideoSizes[NumStdSizes] = {
331         {  128,   96}, // SQCIF
332         {  176,  144}, // QCIF
333         {  352,  288}, // CIF
334         {  704,  576}, // 4CIF
335         { 1408, 1152}, // 16CIF
336       };
337 
338       int sizeIndex;
339       for (sizeIndex = 0; sizeIndex < NumStdSizes; ++sizeIndex )
340         if (StandardVideoSizes[sizeIndex].width == width
341             && StandardVideoSizes[sizeIndex].height == height)
342           return sizeIndex;
343       return UnknownStdSize;
344     }
345 };
346 
347 /////////////////////////////////////////////////////////////////////////////
348 //
349 //  Encoding context constructor.  Sets some encoding parameters, registers the
350 //  codec and allocates the context and frame.
351 //
352 
MPEG4EncoderContext()353 MPEG4EncoderContext::MPEG4EncoderContext()
354 :   m_encFrameBuffer(NULL),
355     m_rawFrameBuffer(NULL),
356     m_avcodec(NULL),
357     m_avcontext(NULL),
358     m_avpicture(NULL)
359 {
360 
361   // Some sane default video settings
362   m_targetFPS = 24;
363   m_videoQMin = 2;
364   m_videoTSTO = 10;
365   m_iQuantFactor = -0.8f;
366   m_maxBufferSize = 112 * 16384;
367 
368   m_keyframeUpdatePeriod = 0;
369 
370   m_frameNum = 0;
371   m_lastPktOffset = 0;
372 
373   m_isIFrame = false;
374 
375   // Default frame size.  These may change after encoder_set_options
376   m_frameWidth  = CIF_WIDTH;
377   m_frameHeight = CIF_HEIGHT;
378   m_rawFrameLen = (m_frameWidth * m_frameHeight * 3) / 2;
379 
380   FFMPEGLibraryInstance.Load();
381 }
382 
383 /////////////////////////////////////////////////////////////////////////////
384 //
385 //  Close the codec and free our pointers
386 //
387 
~MPEG4EncoderContext()388 MPEG4EncoderContext::~MPEG4EncoderContext()
389 {
390   CloseCodec();
391 
392   if (m_rawFrameBuffer) {
393     delete[] m_rawFrameBuffer;
394     m_rawFrameBuffer = NULL;
395   }
396   if (m_encFrameBuffer) {
397     delete[] m_encFrameBuffer;
398     m_encFrameBuffer = NULL;
399   }
400 }
401 
402 /////////////////////////////////////////////////////////////////////////////
403 //
404 // Returns the number of bytes / frame.  This is called from
405 // encoder_get_output_data_size to get an accurate frame size
406 //
407 
GetFrameBytes()408 int MPEG4EncoderContext::GetFrameBytes() {
409     return m_frameWidth * m_frameHeight;
410 }
411 
412 
413 /////////////////////////////////////////////////////////////////////////////
414 //
415 // Setter function for m_iQuantFactor.  This may be called from
416 // encoder_set_options if the "IQuantFactor" real option has been passed
417 //
418 
SetIQuantFactor(float newFactor)419 void MPEG4EncoderContext::SetIQuantFactor(float newFactor) {
420     m_iQuantFactor = newFactor;
421 }
422 
423 /////////////////////////////////////////////////////////////////////////////
424 //
425 // Setter function for m_keyframeUpdatePeriod.  This is called from
426 // encoder_set_options if the "Keyframe Update Period" integer option is passed
427 
SetKeyframeUpdatePeriod(int interval)428 void MPEG4EncoderContext::SetKeyframeUpdatePeriod(int interval) {
429     m_keyframeUpdatePeriod = interval;
430 }
431 
432 /////////////////////////////////////////////////////////////////////////////
433 //
434 // Setter function for m_maxBitRateLimit. This is called from encoder_set_options
435 // if the "MaxBitrate" integer option is passed
436 
SetMaxBitrate(int max)437 void MPEG4EncoderContext::SetMaxBitrate(int max) {
438     m_bitRateHighLimit = max;
439 }
440 
441 /////////////////////////////////////////////////////////////////////////////
442 //
443 // Setter function for m_targetFPS. This is called from encoder_set_options
444 // if the "FPS" integer option is passed
445 
SetFPS(int frameTime)446 void MPEG4EncoderContext::SetFPS(int frameTime) {
447     m_targetFPS = (MPEG4_CLOCKRATE / frameTime);
448 }
449 
450 
451 /////////////////////////////////////////////////////////////////////////////
452 //
453 // Setter function for m_frameWidth. This is called from encoder_set_options
454 // when the "Frame Width" integer option is passed
455 
SetFrameWidth(int width)456 void MPEG4EncoderContext::SetFrameWidth(int width) {
457     m_frameWidth = width;
458 }
459 
460 /////////////////////////////////////////////////////////////////////////////
461 //
462 // Setter function for m_frameHeight. This is called from encoder_set_options
463 // when the "Frame Height" integer option is passed
464 
SetFrameHeight(int height)465 void MPEG4EncoderContext::SetFrameHeight(int height) {
466     m_frameHeight = height;
467 }
468 
469 /////////////////////////////////////////////////////////////////////////////
470 //
471 // Setter function for m_videoQMin. This is called from encoder_set_options
472 // when the "Minimum Quality" integer option is passed
473 
SetQMin(int qmin)474 void MPEG4EncoderContext::SetQMin(int qmin) {
475     m_videoQMin = qmin;
476 }
477 
478 /////////////////////////////////////////////////////////////////////////////
479 //
480 // Setter function for m_videoQMax. This is called from encoder_set_options
481 // when the "Maximum Quality" integer option is passed
482 
SetTSTO(unsigned tsto)483 void MPEG4EncoderContext::SetTSTO(unsigned tsto) {
484     m_videoTSTO = tsto;
485 }
486 
487 /////////////////////////////////////////////////////////////////////////////
488 //
489 // Setter function for m_frameHeight. This is called from encoder_set_options
490 // when the "Encoding Quality" integer option is passed
491 
SetProfileLevel(unsigned profileLevel)492 void MPEG4EncoderContext::SetProfileLevel (unsigned profileLevel) {
493   int i = 0;
494   while (mpeg4_profile_levels[i].profileLevel) {
495     if (mpeg4_profile_levels[i].profileLevel == profileLevel)
496       break;
497     i++;
498   }
499 
500   if (!mpeg4_profile_levels[i].profileLevel) {
501     PTRACE(1, "MPEG4", "Illegal Profle-Level negotiated");
502     return;
503   }
504   m_maxBufferSize = mpeg4_profile_levels[i].maxBufferSize * 16384;
505 
506 
507 }
508 
509 /////////////////////////////////////////////////////////////////////////////
510 //
511 //  The ffmpeg rate control averages bit usage over an entire file.
512 //  We're only interested in instantaneous usage. Past periods of
513 //  over-bandwidth or under-bandwidth shouldn't affect the next
514 //  frame. So we reset the total_bits counter toward what it should be,
515 //  picture_number * bit_rate / fps,
516 //  bit by bit as we go.
517 //
518 //  We also reset the vbv buffer toward the value where it doesn't
519 //  affect quantization - rc_buffer_size/2.
520 //
521 
522 #ifdef LIBAVCODEC_HAVE_SOURCE_DIR
ResetBitCounter(int spread)523 void MPEG4EncoderContext::ResetBitCounter(int spread) {
524     MpegEncContext *s = (MpegEncContext *) m_avcontext->priv_data;
525     int64_t wanted_bits
526         = int64_t(s->bit_rate * double(s->picture_number)
527                   * av_q2d(m_avcontext->time_base));
528     s->total_bits += (wanted_bits - s->total_bits) / int64_t(spread);
529 
530     double want_buffer = double(m_avcontext->rc_buffer_size / 2);
531     s->rc_context.buffer_index
532         += (want_buffer - s->rc_context.buffer_index) / double(spread);
533 }
534 #endif
535 
536 /////////////////////////////////////////////////////////////////////////////
537 //
538 // Set static encoding parameters.  These should be values that remain
539 // unchanged through the duration of the encoding context.
540 //
541 
SetStaticEncodingParams()542 void MPEG4EncoderContext::SetStaticEncodingParams(){
543     m_avcontext->pix_fmt = AV_PIX_FMT_YUV420P;
544     m_avcontext->mb_decision = FF_MB_DECISION_SIMPLE;    // high quality off
545     m_avcontext->rtp_payload_size = 750;                 // ffh263 uses 750
546     m_avcontext->rtp_callback = &MPEG4EncoderContext::RtpCallback;
547 
548     // Reduce the difference in quantization between frames.
549     m_avcontext->qblur = 0.3f;
550     // default is tex^qComp; 1 is constant bitrate
551     av_opt_set(m_avcontext->priv_data, "rc_eq", (char*) "1", 0);
552     //av_opt_set(m_avcontext->priv_data, "rc_eq", "tex^qComp", 0);
553     // These ones technically could be dynamic, I think
554     m_avcontext->rc_min_rate = 0;
555     // This is set to 0 in ffmpeg.c, the command-line utility.
556     av_opt_set_double(m_avcontext->priv_data, "rc_init_cplx", 0.0f, 0);
557 
558     // And this is set to 1.
559     // It seems to affect how aggressively the library will raise and lower
560     // quantization to keep bandwidth constant. Except it's in reference to
561     // the "vbv buffer", not bits per second, so nobody really knows how
562     // it works.
563     av_opt_set_double(m_avcontext->priv_data, "rc_buf_aggressivity", 1.0f, 0);
564 
565     // Ratecontrol buffer size, in bits. Usually 0.5-1 second worth.
566     // 224 kbyte is what VLC uses, and it seems to fix the quantization pulse (at Level 5)
567     m_avcontext->rc_buffer_size = m_maxBufferSize;
568 
569     // In MEncoder this defaults to 1/4 buffer size, but in ffmpeg.c it
570     // defaults to 3/4. I think the buffer is supposed to stabilize at
571     // about half full. Note that setting this after avcodec_open() has
572     // no effect.
573     m_avcontext->rc_initial_buffer_occupancy = m_avcontext->rc_buffer_size * 1/2;
574 
575     // Defaults to -0.8, which is good for high bandwidth and not negative
576     // enough for low bandwidth.
577     m_avcontext->i_quant_factor = m_iQuantFactor;
578     m_avcontext->i_quant_offset = 0.0;
579 
580     // Set our initial target FPS, gop_size and create throttler
581     m_avcontext->time_base.num = 1;
582     m_avcontext->time_base.den = m_targetFPS;
583 
584     // Number of frames for a group of pictures
585     if (m_keyframeUpdatePeriod == 0)
586       m_avcontext->gop_size = m_targetFPS * 8;
587     else
588       m_avcontext->gop_size = m_keyframeUpdatePeriod;
589 
590     m_avpicture->quality = m_videoQMin;
591 
592 #ifdef USE_ORIG
593     av_opt_set_int(m_avcontext->priv_data, "data_partitionin", 1, 0);
594     m_avcontext->flags |= CODEC_FLAG_4MV;    // 4 motion vectors
595 #else
596     m_avcontext->max_b_frames=0; /*don't use b frames*/
597     m_avcontext->flags|=AV_CODEC_FLAG_AC_PRED;
598     av_opt_set_int(m_avcontext->priv_data, "umv", 1, 0);
599     /*c->flags|=CODEC_FLAG_QPEL;*/ /*don't enable this one: this forces profile_level to advanced simple profile */
600     m_avcontext->flags|=AV_CODEC_FLAG_4MV;
601     m_avcontext->flags|=AV_CODEC_FLAG_LOOP_FILTER;
602     av_opt_set_int(m_avcontext->priv_data, "structured_slices", 1, 0);
603 #endif
604     m_avcontext->opaque = this;              // for use in RTP callback
605 }
606 
607 /////////////////////////////////////////////////////////////////////////////
608 //
609 // Set dynamic encoding parameters.  These are values that may change over the
610 // encoding context's lifespan
611 //
612 
SetDynamicEncodingParams(bool restartOnResize)613 void MPEG4EncoderContext::SetDynamicEncodingParams(bool restartOnResize) {
614     // If no bitrate limit is set, max out at 3 mbit
615     // Use 75% of available bandwidth so not as many frames are dropped
616     unsigned bitRate
617         = (m_bitRateHighLimit ? 3*m_bitRateHighLimit/4 : MPEG4_BITRATE);
618     m_avcontext->bit_rate = bitRate;
619 
620     // In ffmpeg this is the tolerance over the entire file. We reset the
621     // bit counter toward the expected value a little bit every frame,
622     // so this probably needs to be readjusted.
623     m_avcontext->bit_rate_tolerance = bitRate;
624 
625     // The rc_* values affect the quantizer. Not even sure what bit_rate does.
626     m_avcontext->rc_max_rate = bitRate;
627 
628     // Update the quantization factor
629     m_avcontext->i_quant_factor = m_iQuantFactor;
630 
631     // Set full-frame min/max quantizers.
632     // Note: mb_qmin, mb_max don't seem to be used in the libavcodec code.
633 
634     m_avcontext->qmin = m_videoQMin;
635     m_avcontext->qmax = round ( (double)(31 - m_videoQMin) / 31 * m_videoTSTO + m_videoQMin);
636     m_avcontext->qmax = std::min( m_avcontext->qmax, 31);
637 
638     // Lagrange multipliers - this is how the context defaults do it:
639     av_opt_set_int(m_avcontext->priv_data, "lmin", m_avcontext->qmin * FF_QP2LAMBDA, 0);
640     av_opt_set_int(m_avcontext->priv_data, "lmax", m_avcontext->qmax * FF_QP2LAMBDA, 0);
641 
642     // If framesize has changed or is not yet initialized, fix it up
643     if((unsigned)m_avcontext->width != m_frameWidth || (unsigned)m_avcontext->height != m_frameHeight) {
644         ResizeEncodingFrame(restartOnResize);
645     }
646 }
647 
648 /////////////////////////////////////////////////////////////////////////////
649 //
650 // Updates the context's frame size and creates new buffers
651 //
652 
ResizeEncodingFrame(bool restartCodec)653 void MPEG4EncoderContext::ResizeEncodingFrame(bool restartCodec) {
654     m_avcontext->width = m_frameWidth;
655     m_avcontext->height = m_frameHeight;
656 
657     // Restart to force avcodec to use the new frame sizes
658     if (restartCodec) {
659         CloseCodec();
660         OpenCodec();
661     }
662 
663     m_rawFrameLen = (m_frameWidth * m_frameHeight * 3) / 2;
664     if (m_rawFrameBuffer)
665     {
666         delete[] m_rawFrameBuffer;
667     }
668     m_rawFrameBuffer = new BYTE[m_rawFrameLen + AV_INPUT_BUFFER_PADDING_SIZE];
669 
670     if (m_encFrameBuffer)
671     {
672         delete[] m_encFrameBuffer;
673     }
674     m_encFrameLen = m_rawFrameLen/2;         // assume at least 50% compression...
675     m_encFrameBuffer = new BYTE[m_encFrameLen];
676 
677     // Clear the back padding
678     memset(m_rawFrameBuffer + m_rawFrameLen, 0, AV_INPUT_BUFFER_PADDING_SIZE);
679     const unsigned fsz = m_frameWidth * m_frameHeight;
680     m_avpicture->data[0] = m_rawFrameBuffer;              // luminance
681     m_avpicture->data[1] = m_rawFrameBuffer + fsz;        // first chroma channel
682     m_avpicture->data[2] = m_avpicture->data[1] + fsz/4;  // second
683     m_avpicture->linesize[0] = m_frameWidth;
684     m_avpicture->linesize[1] = m_avpicture->linesize[2] = m_frameWidth/2;
685 }
686 
687 /////////////////////////////////////////////////////////////////////////////
688 //
689 // Initializes codec parameters and opens the encoder
690 //
691 
OpenCodec()692 bool MPEG4EncoderContext::OpenCodec()
693 {
694   m_avcontext = FFMPEGLibraryInstance.AvcodecAllocContext();
695   if (m_avcontext == NULL) {
696     PTRACE(1, "MPEG4", "Encoder failed to allocate context for encoder");
697     return false;
698   }
699 
700   m_avpicture = FFMPEGLibraryInstance.AvcodecAllocFrame();
701   if (m_avpicture == NULL) {
702     PTRACE(1, "MPEG4", "Encoder failed to allocate frame for encoder");
703     return false;
704   }
705 
706   if((m_avcodec = FFMPEGLibraryInstance.AvcodecFindEncoder(AV_CODEC_ID_MPEG4)) == NULL){
707     PTRACE(1, "MPEG4", "Encoder not found");
708     return false;
709   }
710 
711 #if PLUGINCODEC_TRACING
712   // debugging flags
713   if (PTRACE_CHECK(4)) {
714     m_avcontext->debug |= FF_DEBUG_RC;
715     m_avcontext->debug |= FF_DEBUG_PICT_INFO;
716 //    m_avcontext->debug |= FF_DEBUG_MV;
717   }
718 #endif
719 
720   SetStaticEncodingParams();
721   SetDynamicEncodingParams(false);    // don't force a restart, it's not open
722   AVDictionary *opts = NULL;
723   av_dict_set_int(&opts, "gmc", 1, 0);
724   if (FFMPEGLibraryInstance.AvcodecOpen(m_avcontext, m_avcodec, &opts) < 0)
725   {
726     PTRACE(1, "MPEG4", "Encoder could not be opened");
727     return false;
728   }
729   return true;
730 }
731 
732 /////////////////////////////////////////////////////////////////////////////
733 //
734 // Close the codec
735 //
736 
CloseCodec()737 void MPEG4EncoderContext::CloseCodec()
738 {
739   if (m_avcontext != NULL) {
740     if(m_avcontext->codec != NULL)
741       FFMPEGLibraryInstance.AvcodecClose(m_avcontext);
742     FFMPEGLibraryInstance.AvcodecFree(m_avcontext);
743     m_avcontext = NULL;
744   }
745   if (m_avpicture != NULL) {
746     FFMPEGLibraryInstance.AvcodecFree(m_avpicture);
747     m_avpicture = NULL;
748   }
749 }
750 
751 /////////////////////////////////////////////////////////////////////////////
752 //
753 // This is called after an Favcodec_encode_frame() call.  This populates the
754 // m_packetSizes deque with offsets, no greated than max_rtp which we will use
755 // to create RTP packets.
756 //
757 
RtpCallback(AVCodecContext * priv_data,void *,int size,int)758 void MPEG4EncoderContext::RtpCallback(AVCodecContext *priv_data, void * /*data*/,
759                                       int size, int /*num_mb*/)
760 {
761   MPEG4EncoderContext *c = static_cast<MPEG4EncoderContext *>(priv_data->opaque);
762   c->m_packetSizes.push_back(size);
763 }
764 
765 /////////////////////////////////////////////////////////////////////////////
766 //
767 // The main encoding loop.  If there are no packets ready to be sent, generate
768 // them by encoding a frame.  When there are, create packets from the encoded
769 // frame buffer and send them out
770 //
771 
EncodeFrames(const BYTE * src,unsigned & srcLen,BYTE * dst,unsigned & dstLen,unsigned int & flags)772 int MPEG4EncoderContext::EncodeFrames(const BYTE * src, unsigned & srcLen,
773                                       BYTE * dst, unsigned & dstLen,
774                                       unsigned int & flags)
775 {
776     if (!FFMPEGLibraryInstance.IsLoaded()){
777         return 0;
778     }
779 
780     if (dstLen < 16)
781       return false;
782 
783     // create frames frame from their respective buffers
784     RTPFrame srcRTP(src, srcLen);
785     RTPFrame dstRTP(dst, dstLen);
786 
787     // create the video frame header from the source and update video size
788     PluginCodec_Video_FrameHeader * header = (PluginCodec_Video_FrameHeader *)srcRTP.GetPayloadPtr();
789     m_frameWidth  = header->width;
790     m_frameHeight = header->height;
791 
792     if (m_packetSizes.empty()) {
793         if (m_avcontext == NULL) {
794             OpenCodec();
795         }
796         else {
797             // set our dynamic parameters, restart the codec if we need to
798             SetDynamicEncodingParams(true);
799         }
800         m_lastTimeStamp = srcRTP.GetTimestamp();
801         m_lastPktOffset = 0;
802 
803         // generate the raw picture
804         memcpy(m_rawFrameBuffer, OPAL_VIDEO_FRAME_DATA_PTR(header), m_rawFrameLen);
805 
806         // Should the next frame be an I-Frame?
807         if ((flags & PluginCodec_CoderForceIFrame) || (m_frameNum == 0))
808         {
809             m_avpicture->pict_type = AV_PICTURE_TYPE_I;
810         }
811         else // No IFrame requested, let avcodec decide what to do
812         {
813             m_avpicture->pict_type = AV_PICTURE_TYPE_NONE;
814         }
815 
816         // Encode a frame
817         int total = FFMPEGLibraryInstance.AvcodecEncodeVideo
818                             (m_avcontext, m_encFrameBuffer, m_encFrameLen,
819                              m_avpicture);
820 
821 
822         if (total > 0) {
823             m_frameNum++; // increment the number of frames encoded
824 #ifdef LIBAVCODEC_HAVE_SOURCE_DIR
825             ResetBitCounter(8); // Fix ffmpeg rate control
826 #endif
827 	    m_isIFrame = mpeg4IsIframe(m_encFrameBuffer, total );
828         }
829     }
830 
831     flags = 0;
832 
833     if (m_isIFrame)
834       flags |= PluginCodec_ReturnCoderIFrame;
835 
836     // get the next packet
837     if (m_packetSizes.size() == 0)
838 
839       dstLen = 0;
840 
841     else {
842 
843       unsigned pktLen = m_packetSizes.front();
844       m_packetSizes.pop_front();
845 
846       // if too large, split it
847       unsigned maxRtpSize = dstLen - dstRTP.GetHeaderSize();
848       if (pktLen > maxRtpSize) {
849           m_packetSizes.push_front(pktLen - maxRtpSize);
850           pktLen = maxRtpSize;
851       }
852 
853       dstRTP.SetPayloadSize(pktLen);
854 
855       // Copy the encoded data from the buffer into the outgoign RTP
856       memcpy(dstRTP.GetPayloadPtr(), &m_encFrameBuffer[m_lastPktOffset], pktLen);
857       m_lastPktOffset += pktLen;
858 
859       // If there are no more packet sizes left, we've reached the last packet
860       // for the frame, set the marker bit and flags
861       if (m_packetSizes.empty()) {
862           dstRTP.SetMarker(true);
863           flags |= PluginCodec_ReturnCoderLastFrame;
864       }
865 
866       // set timestamp and adjust dstLen to include header size
867       dstRTP.SetTimestamp(m_lastTimeStamp);
868 
869       dstLen = dstRTP.GetHeaderSize() + pktLen;
870 
871     }
872 
873     return 1;
874 }
875 
876 /////////////////////////////////////////////////////////////////////////////
877 //
878 // OPAL plugin functions
879 //
num2str(int num)880 static char * num2str(int num)
881 {
882   char buf[20];
883   sprintf(buf, "%i", num);
884   return strdup(buf);
885 }
886 
get_codec_options(const struct PluginCodec_Definition * codec,void *,const char *,void * parm,unsigned * parmLen)887 static int get_codec_options(const struct PluginCodec_Definition * codec,
888                                                   void *,
889                                                   const char *,
890                                                   void * parm,
891                                                   unsigned * parmLen)
892 {
893     if (parmLen == NULL || parm == NULL || *parmLen != sizeof(struct PluginCodec_Option **))
894         return 0;
895 
896     *(const void **)parm = codec->userData;
897     *parmLen = 0; //FIXME
898     return 1;
899 }
900 
free_codec_options(const struct PluginCodec_Definition *,void *,const char *,void * parm,unsigned * parmLen)901 static int free_codec_options ( const struct PluginCodec_Definition *, void *, const char *, void * parm, unsigned * parmLen)
902 {
903   if (parmLen == NULL || parm == NULL || *parmLen != sizeof(char ***))
904     return 0;
905 
906   char ** strings = (char **) parm;
907   for (char ** string = strings; *string != NULL; string++)
908     free(*string);
909   free(strings);
910   return 1;
911 }
912 
valid_for_protocol(const struct PluginCodec_Definition *,void *,const char *,void * parm,unsigned * parmLen)913 static int valid_for_protocol ( const struct PluginCodec_Definition *, void *, const char *, void * parm, unsigned * parmLen)
914 {
915   if (parmLen == NULL || parm == NULL || *parmLen != sizeof(char *))
916     return 0;
917 
918   return (STRCMPI((const char *)parm, "sip") == 0) ? 1 : 0;
919 }
920 
adjust_bitrate_to_profile_level(unsigned & targetBitrate,unsigned profileLevel,int idx=-1)921 static int adjust_bitrate_to_profile_level (unsigned & targetBitrate, unsigned profileLevel, int idx = -1)
922 {
923   int i = 0;
924   if (idx == -1) {
925     while (mpeg4_profile_levels[i].profileLevel) {
926       if (mpeg4_profile_levels[i].profileLevel == profileLevel)
927         break;
928     i++;
929     }
930 
931     if (!mpeg4_profile_levels[i].profileLevel) {
932       PTRACE(1, "MPEG4", "Illegal Profle-Level negotiated");
933       return 0;
934     }
935   }
936   else
937     i = idx;
938 
939 // Correct Target Bitrate
940   PTRACE(4, "MPEG4", "Adjusting to " << mpeg4_profile_levels[i].profileName << " Profile, Level " <<  mpeg4_profile_levels[i].level
941           << " bitrate: " << targetBitrate << "(" << mpeg4_profile_levels[i].bitrate << ")");
942   if (targetBitrate > mpeg4_profile_levels[i].bitrate)
943     targetBitrate = mpeg4_profile_levels[i].bitrate;
944 
945   return 1;
946 }
947 
adjust_to_profile_level(unsigned & width,unsigned & height,unsigned & frameTime,unsigned & targetBitrate,unsigned profileLevel)948 static int adjust_to_profile_level (unsigned & width, unsigned & height, unsigned & frameTime, unsigned & targetBitrate, unsigned profileLevel)
949 {
950   int i = 0;
951   while (mpeg4_profile_levels[i].profileLevel) {
952     if (mpeg4_profile_levels[i].profileLevel == profileLevel)
953       break;
954    i++;
955   }
956 
957   if (!mpeg4_profile_levels[i].profileLevel) {
958     PTRACE(1, "MPEG4", "tIllegal Level negotiated");
959     return 0;
960   }
961 
962 // Correct max. number of macroblocks per frame
963   uint32_t nbMBsPerFrame = width * height / 256;
964   unsigned j = 0;
965   PTRACE(4, "MPEG4", "Frame Size: " << nbMBsPerFrame << "(" << mpeg4_profile_levels[i].frame_size << ")");
966   if    ( (nbMBsPerFrame          > mpeg4_profile_levels[i].frame_size) ) {
967 
968     while (mpeg4_resolutions[j].width) {
969       if  ( (mpeg4_resolutions[j].macroblocks <= mpeg4_profile_levels[i].frame_size) )
970           break;
971       j++;
972     }
973     if (!mpeg4_resolutions[j].width) {
974       PTRACE(1, "MPEG4", "No Resolution found that has number of macroblocks <=" << mpeg4_profile_levels[i].frame_size);
975       return 0;
976     }
977     else {
978       width  = mpeg4_resolutions[j].width;
979       height = mpeg4_resolutions[j].height;
980     }
981   }
982 
983 // Correct macroblocks per second
984   uint32_t nbMBsPerSecond = width * height / 256 * (90000 / frameTime);
985   PTRACE(4, "MPEG4", "MBs/s: " << nbMBsPerSecond << "(" << mpeg4_profile_levels[i].mbps << ")");
986   if (nbMBsPerSecond > mpeg4_profile_levels[i].mbps)
987     frameTime =  (unsigned) (90000 / 256 * width  * height / mpeg4_profile_levels[i].mbps );
988 
989   adjust_bitrate_to_profile_level (targetBitrate, profileLevel, i);
990   return 1;
991 }
992 
993 /////////////////////////////////////////////////////////////////////////////
994 //
995 // OPAL plugin encoder functions
996 //
997 
create_encoder(const struct PluginCodec_Definition *)998 static void * create_encoder(const struct PluginCodec_Definition * /*codec*/)
999 {
1000   return new MPEG4EncoderContext;
1001 }
1002 
to_normalised_options(const struct PluginCodec_Definition *,void *,const char *,void * parm,unsigned * parmLen)1003 static int to_normalised_options(const struct PluginCodec_Definition *, void *, const char *, void * parm, unsigned * parmLen)
1004 {
1005   if (parmLen == NULL || parm == NULL || *parmLen != sizeof(char ***))
1006     return 0;
1007 
1008   unsigned profileLevel = 1;
1009   unsigned width = 352;
1010   unsigned height = 288;
1011   unsigned frameTime = 3000;
1012   unsigned targetBitrate = 64000;
1013 
1014   for (const char * const * option = *(const char * const * *)parm; *option != NULL; option += 2) {
1015       if (STRCMPI(option[0], ProfileAndLevel) == 0)
1016         profileLevel = atoi(option[1]);
1017       if (STRCMPI(option[0], PLUGINCODEC_OPTION_FRAME_WIDTH) == 0)
1018         width = atoi(option[1]);
1019       if (STRCMPI(option[0], PLUGINCODEC_OPTION_FRAME_HEIGHT) == 0)
1020         height = atoi(option[1]);
1021       if (STRCMPI(option[0], PLUGINCODEC_OPTION_FRAME_TIME) == 0)
1022         frameTime = atoi(option[1]);
1023       if (STRCMPI(option[0], PLUGINCODEC_OPTION_TARGET_BIT_RATE) == 0)
1024         targetBitrate = atoi(option[1]);
1025   }
1026 
1027   // Though this is not a strict requirement we enforce
1028   //it here in order to obtain optimal compression results
1029   width -= width % 16;
1030   height -= height % 16;
1031 
1032   if (profileLevel == 0) {
1033 #ifdef DEFAULT_TO_FULL_CAPABILITIES
1034     // Simple Profile, Level 5
1035     profileLevel = 5;
1036 #else
1037     // Default handling according to RFC 3016
1038     // Simple Profile, Level 1
1039     profileLevel = 1;
1040 #endif
1041   }
1042 
1043   if (!adjust_to_profile_level (width, height, frameTime, targetBitrate, profileLevel))
1044     return 0;
1045 
1046   char ** options = (char **)calloc(9, sizeof(char *));
1047   *(char ***)parm = options;
1048   if (options == NULL)
1049     return 0;
1050 
1051   options[0] = strdup(PLUGINCODEC_OPTION_FRAME_WIDTH);
1052   options[1] = num2str(width);
1053   options[2] = strdup(PLUGINCODEC_OPTION_FRAME_HEIGHT);
1054   options[3] = num2str(height);
1055   options[4] = strdup(PLUGINCODEC_OPTION_FRAME_TIME);
1056   options[5] = num2str(frameTime);
1057   options[6] = strdup(PLUGINCODEC_OPTION_TARGET_BIT_RATE);
1058   options[7] = num2str(targetBitrate);
1059 
1060   return 1;
1061 }
1062 
1063 // This is assuming the second param is the context...
encoder_set_options(const PluginCodec_Definition *,void * m_context,const char *,void * parm,unsigned * parmLen)1064 static int encoder_set_options(
1065       const PluginCodec_Definition * ,
1066       void * m_context,
1067       const char * ,
1068       void *parm,
1069       unsigned *parmLen )
1070 {
1071   if (parmLen == NULL || *parmLen != sizeof(const char **))
1072     return 0;
1073 
1074   MPEG4EncoderContext * context = (MPEG4EncoderContext *)m_context;
1075   // Scan the options passed in and check for:
1076   // 1) "Frame Width" sets the encoding frame width
1077   // 2) "Frame Height" sets the encoding frame height
1078   // 3) "Target Bit Rate" sets the bitrate upper limit
1079   // 5) "Tx Keyframe Period" interval in frames before an IFrame is sent
1080   // 6) "Minimum Quality" sets the minimum encoding quality
1081   // 7) "Maximum Quality" sets the maximum encoding quality
1082   // 8) "Encoding Quality" sets the default encoding quality
1083   // 9) "Dynamic Encoding Quality" enables dynamic adjustment of encoding quality
1084   // 10) "Bandwidth Throttling" will turn on bandwidth throttling for the encoder
1085   // 11) "IQuantFactor" will update the quantization factor to a float value
1086 
1087   if (parm != NULL) {
1088     const char ** options = (const char **)parm;
1089     unsigned targetBitrate = 64000;
1090     unsigned profileLevel = 1;
1091     for (int i = 0; options[i] != NULL; i += 2) {
1092       if (STRCMPI(options[i], ProfileAndLevel) == 0)
1093          profileLevel = atoi(options[i+1]);
1094       else if (STRCMPI(options[i], PLUGINCODEC_OPTION_FRAME_WIDTH) == 0)
1095         context->SetFrameWidth(atoi(options[i+1]));
1096       else if(STRCMPI(options[i], PLUGINCODEC_OPTION_FRAME_HEIGHT) == 0)
1097         context->SetFrameHeight(atoi(options[i+1]));
1098       else if(STRCMPI(options[i], PLUGINCODEC_OPTION_TARGET_BIT_RATE) == 0)
1099          targetBitrate = atoi(options[i+1]);
1100       else if(STRCMPI(options[i], PLUGINCODEC_OPTION_FRAME_TIME) == 0)
1101         context->SetFPS(atoi(options[i+1]));
1102       else if(STRCMPI(options[i], PLUGINCODEC_OPTION_TX_KEY_FRAME_PERIOD) == 0)
1103         context->SetKeyframeUpdatePeriod(atoi(options[i+1]));
1104       else if(STRCMPI(options[i], PLUGINCODEC_OPTION_TEMPORAL_SPATIAL_TRADE_OFF) == 0)
1105         context->SetTSTO(atoi(options[i+1]));
1106       else if(STRCMPI(options[i], "Minimum Quality") == 0)
1107         context->SetQMin(atoi(options[i+1]));
1108       else if(STRCMPI(options[i], "IQuantFactor") == 0)
1109         context->SetIQuantFactor((float)atof(options[i+1]));
1110     }
1111 
1112     if (profileLevel == 0) {
1113 #ifdef WITH_RFC_COMPLIANT_DEFAULTS
1114       profileLevel = 1;
1115 #else
1116       profileLevel = 5;
1117 #endif
1118     }
1119     if (!adjust_bitrate_to_profile_level (targetBitrate, profileLevel))
1120       return 0;
1121 
1122     context->SetMaxBitrate(targetBitrate);
1123     context->SetProfileLevel(profileLevel);
1124   }
1125   return 1;
1126 }
1127 
destroy_encoder(const struct PluginCodec_Definition *,void * m_context)1128 static void destroy_encoder(const struct PluginCodec_Definition * /*codec*/,
1129                             void * m_context)
1130 {
1131   MPEG4EncoderContext * context = (MPEG4EncoderContext *)m_context;
1132   delete context;
1133 }
1134 
codec_encoder(const struct PluginCodec_Definition *,void * m_context,const void * from,unsigned * fromLen,void * to,unsigned * toLen,unsigned int * flags)1135 static int codec_encoder(const struct PluginCodec_Definition * ,
1136                                            void * m_context,
1137                                      const void * from,
1138                                        unsigned * fromLen,
1139                                            void * to,
1140                                        unsigned * toLen,
1141                                    unsigned int * flags)
1142 {
1143   MPEG4EncoderContext * context = (MPEG4EncoderContext *)m_context;
1144   return context->EncodeFrames((const BYTE *)from, *fromLen, (BYTE *)to, *toLen,
1145                                *flags);
1146 }
1147 
encoder_get_output_data_size(const PluginCodec_Definition *,void * m_context,const char *,void *,unsigned *)1148 static int encoder_get_output_data_size(const PluginCodec_Definition * /*codec*/, void *m_context, const char *, void *, unsigned *)
1149 {
1150   MPEG4EncoderContext * context = (MPEG4EncoderContext *)m_context;
1151   return context->GetFrameBytes() * 3 / 2;
1152 }
1153 
1154 PLUGINCODEC_CONTROL_LOG_FUNCTION_DEF
1155 
1156 static PluginCodec_ControlDefn sipEncoderControls[] = {
1157   { PLUGINCODEC_CONTROL_VALID_FOR_PROTOCOL,    valid_for_protocol },
1158   { PLUGINCODEC_CONTROL_GET_CODEC_OPTIONS,     get_codec_options },
1159   { PLUGINCODEC_CONTROL_FREE_CODEC_OPTIONS,    free_codec_options },
1160   { PLUGINCODEC_CONTROL_TO_NORMALISED_OPTIONS, to_normalised_options },
1161   { PLUGINCODEC_CONTROL_SET_CODEC_OPTIONS,     encoder_set_options },
1162   { PLUGINCODEC_CONTROL_GET_OUTPUT_DATA_SIZE,  encoder_get_output_data_size },
1163   PLUGINCODEC_CONTROL_LOG_FUNCTION_INC
1164   { NULL }
1165 };
1166 
1167 /////////////////////////////////////////////////////////////////////////////
1168 //
1169 // Define the decoder context
1170 //
1171 
1172 class MPEG4DecoderContext
1173 {
1174   public:
1175     MPEG4DecoderContext();
1176     ~MPEG4DecoderContext();
1177 
1178     bool DecodeFrames(const BYTE * src, unsigned & srcLen,
1179                       BYTE * dst, unsigned & dstLen, unsigned int & flags);
1180 
1181     bool DecoderError(int threshold);
1182     void SetErrorRecovery(bool error);
1183     void SetErrorThresh(int thresh);
1184     void SetDisableResize(bool disable);
1185 
1186     void SetFrameHeight(int height);
1187     void SetFrameWidth(int width);
1188 
1189     int GetFrameBytes();
1190 
1191   protected:
1192 
1193     bool OpenCodec();
1194     void CloseCodec();
1195 
1196     void SetStaticDecodingParams();
1197     void SetDynamicDecodingParams(bool restartOnResize);
1198     void ResizeDecodingFrame(bool restartCodec);
1199 
1200     BYTE * m_encFrameBuffer;
1201     unsigned int m_encFrameLen;
1202 
1203     AVCodec        *m_avcodec;
1204     AVCodecContext *m_avcontext;
1205     AVFrame        *m_avpicture;
1206 
1207     int m_frameNum;
1208 
1209     bool m_doError;
1210     int m_keyRefreshThresh;
1211 
1212     bool m_disableResize;
1213 
1214     unsigned m_lastPktOffset;
1215     unsigned int m_frameWidth;
1216     unsigned int m_frameHeight;
1217 
1218     bool m_gotAGoodFrame;
1219 };
1220 
1221 /////////////////////////////////////////////////////////////////////////////
1222 //
1223 // Constructor.  Register the codec, allocate the context and frame and set
1224 // some parameters
1225 //
1226 
MPEG4DecoderContext()1227 MPEG4DecoderContext::MPEG4DecoderContext()
1228 :   m_encFrameBuffer(NULL),
1229     m_frameNum(0),
1230     m_doError(true),
1231     m_keyRefreshThresh(1),
1232     m_disableResize(false),
1233     m_lastPktOffset(0),
1234     m_frameWidth(0),
1235     m_frameHeight(0)
1236 {
1237   // Default frame sizes.  These may change after decoder_set_options is called
1238   m_frameWidth  = CIF_WIDTH;
1239   m_frameHeight = CIF_HEIGHT;
1240   m_gotAGoodFrame = true;
1241 
1242   if (FFMPEGLibraryInstance.Load())
1243     OpenCodec();
1244 }
1245 
1246 /////////////////////////////////////////////////////////////////////////////
1247 //
1248 // Close the codec, free the context, frame and buffer
1249 //
1250 
~MPEG4DecoderContext()1251 MPEG4DecoderContext::~MPEG4DecoderContext()
1252 {
1253   if (FFMPEGLibraryInstance.IsLoaded()) {
1254     CloseCodec();
1255   }
1256   if(m_encFrameBuffer) {
1257     delete[] m_encFrameBuffer;
1258     m_encFrameBuffer = NULL;
1259   }
1260 }
1261 
1262 /////////////////////////////////////////////////////////////////////////////
1263 //
1264 // Returns the number of bytes / frame.  This is called from
1265 // decoder_get_output_data_size to get an accurate frame size
1266 //
1267 
GetFrameBytes()1268 int MPEG4DecoderContext::GetFrameBytes() {
1269     return m_frameWidth * m_frameHeight;
1270 }
1271 
1272 
1273 
1274 /////////////////////////////////////////////////////////////////////////////
1275 //
1276 // Setter for decoding error recovery.  Called from decoder_set_options if
1277 // the user passes the "Error Recovery" option.
1278 //
1279 
SetErrorRecovery(bool error)1280 void MPEG4DecoderContext::SetErrorRecovery(bool error) {
1281     m_doError = error;
1282 }
1283 
1284 /////////////////////////////////////////////////////////////////////////////
1285 //
1286 // Setter for DecoderError threshold.  Called from decoder_set_options if
1287 // the user passes "Error Threshold" option.
1288 //
1289 
SetErrorThresh(int thresh)1290 void MPEG4DecoderContext::SetErrorThresh(int thresh) {
1291     m_keyRefreshThresh = thresh;
1292 }
1293 
1294 /////////////////////////////////////////////////////////////////////////////
1295 //
1296 // Setter for the automatic resize boolean.  Called from decoder_set_options if
1297 // the user passes "Disable Resize" option.
1298 //
1299 
SetDisableResize(bool disable)1300 void MPEG4DecoderContext::SetDisableResize(bool disable) {
1301     m_disableResize = disable;
1302 }
1303 
1304 
1305 /////////////////////////////////////////////////////////////////////////////
1306 //
1307 // Setter function for m_frameWidth. This is called from decoder_set_options
1308 // when the "Frame Width" integer option is passed
1309 
SetFrameWidth(int width)1310 void MPEG4DecoderContext::SetFrameWidth(int width) {
1311     m_frameWidth = width;
1312 }
1313 
1314 /////////////////////////////////////////////////////////////////////////////
1315 //
1316 // Setter function for m_frameHeight. This is called from decoder_set_options
1317 // when the "Frame Height" integer option is passed
1318 
SetFrameHeight(int height)1319 void MPEG4DecoderContext::SetFrameHeight(int height) {
1320     m_frameHeight = height;
1321 }
1322 
1323 /////////////////////////////////////////////////////////////////////////////
1324 //
1325 // Sets static decoding parameters.
1326 //
1327 
SetStaticDecodingParams()1328 void MPEG4DecoderContext::SetStaticDecodingParams() {
1329     m_avcontext->flags |= AV_CODEC_FLAG_4MV;
1330     av_opt_set_int(m_avcontext->priv_data, "data_partitionin", 1, 0);
1331     m_avcontext->workaround_bugs = 0; // no workaround for buggy implementations
1332 }
1333 
1334 
1335 /////////////////////////////////////////////////////////////////////////////
1336 //
1337 // Check for errors on I-Frames.  If we found one, ask for another.
1338 //
1339 #ifdef LIBAVCODEC_HAVE_SOURCE_DIR
DecoderError(int threshold)1340 bool MPEG4DecoderContext::DecoderError(int threshold) {
1341     if (m_doError) {
1342         int errors = 0;
1343         MpegEncContext *s = (MpegEncContext *) m_avcontext->priv_data;
1344         if (s->error_count && m_avcontext->coded_frame->pict_type == FF_I_TYPE) {
1345             const uint8_t badflags = AC_ERROR | DC_ERROR | MV_ERROR;
1346             for (int i = 0; i < s->mb_num && errors < threshold; ++i) {
1347                 if (s->error_status_table[s->mb_index2xy[i]] & badflags)
1348                     ++errors;
1349             }
1350         }
1351         return (errors >= threshold);
1352     }
1353     return false;
1354 }
1355 #endif
1356 
1357 /////////////////////////////////////////////////////////////////////////////
1358 //
1359 // If there's any other dynamic decoder updates to do, put them here.  For
1360 // now it just checks to see if the frame needs resizing.
1361 //
1362 
SetDynamicDecodingParams(bool restartOnResize)1363 void MPEG4DecoderContext::SetDynamicDecodingParams(bool restartOnResize) {
1364     if (m_frameWidth != (unsigned)m_avcontext->width || m_frameHeight != (unsigned)m_avcontext->height)
1365     {
1366         ResizeDecodingFrame(restartOnResize);
1367     }
1368 }
1369 
1370 /////////////////////////////////////////////////////////////////////////////
1371 //
1372 // Resizes the decoding frame, updates the buffer
1373 //
1374 
ResizeDecodingFrame(bool restartCodec)1375 void MPEG4DecoderContext::ResizeDecodingFrame(bool restartCodec) {
1376     m_avcontext->width = m_frameWidth;
1377     m_avcontext->height = m_frameHeight;
1378     unsigned m_rawFrameLen = (m_frameWidth * m_frameHeight * 3) / 2;
1379     if (m_encFrameBuffer)
1380     {
1381         delete[] m_encFrameBuffer;
1382     }
1383     m_encFrameLen = m_rawFrameLen/2;         // assume at least 50% compression...
1384     m_encFrameBuffer = new BYTE[m_encFrameLen];
1385     // Restart to force avcodec to use the new frame sizes
1386     if (restartCodec) {
1387         CloseCodec();
1388         OpenCodec();
1389     }
1390 }
1391 
1392 /////////////////////////////////////////////////////////////////////////////
1393 //
1394 // Set our parameters and open the decoder
1395 //
1396 
OpenCodec()1397 bool MPEG4DecoderContext::OpenCodec()
1398 {
1399     if ((m_avcodec = FFMPEGLibraryInstance.AvcodecFindDecoder(AV_CODEC_ID_MPEG4)) == NULL) {
1400         PTRACE(1, "MPEG4", "Decoder not found for encoder");
1401         return false;
1402     }
1403 
1404     m_avcontext = FFMPEGLibraryInstance.AvcodecAllocContext();
1405     if (m_avcontext == NULL) {
1406         PTRACE(1, "MPEG4", "Decoder failed to allocate context");
1407         return false;
1408     }
1409 
1410     m_avpicture = FFMPEGLibraryInstance.AvcodecAllocFrame();
1411     if (m_avpicture == NULL) {
1412         PTRACE(1, "MPEG4", "Decoder failed to allocate frame");
1413         return false;
1414     }
1415 
1416     m_avcontext->codec = NULL;
1417 
1418     SetStaticDecodingParams();
1419     SetDynamicDecodingParams(false);    // don't force a restart, it's not open
1420     if (FFMPEGLibraryInstance.AvcodecOpen(m_avcontext, m_avcodec, NULL) < 0) {
1421         PTRACE(1, "MPEG4", "Decoder failed to open");
1422         return false;
1423     }
1424 
1425     PTRACE(4, "MPEG4", "Decoder successfully opened");
1426     return true;
1427 }
1428 
1429 /////////////////////////////////////////////////////////////////////////////
1430 //
1431 // Closes the decoder
1432 //
1433 
CloseCodec()1434 void MPEG4DecoderContext::CloseCodec()
1435 {
1436   if (m_avcontext != NULL) {
1437     if(m_avcontext->codec != NULL)
1438       FFMPEGLibraryInstance.AvcodecClose(m_avcontext);
1439     FFMPEGLibraryInstance.AvcodecFree(m_avcontext);
1440     m_avcontext = NULL;
1441   }
1442   if(m_avpicture != NULL) {
1443     FFMPEGLibraryInstance.AvcodecFree(m_avpicture);
1444     m_avpicture = NULL;
1445   }
1446 }
1447 
1448 /////////////////////////////////////////////////////////////////////////////
1449 //
1450 // Frame decoding loop.  Copies incoming RTP payloads into a buffer, when a
1451 // marker frame is received, send the completed frame into the decoder then
1452 // display.
1453 //
1454 
DecodeFrames(const BYTE * src,unsigned & srcLen,BYTE * dst,unsigned & dstLen,unsigned int & flags)1455 bool MPEG4DecoderContext::DecodeFrames(const BYTE * src, unsigned & srcLen,
1456                                        BYTE * dst, unsigned & dstLen,
1457                                        unsigned int & flags)
1458 {
1459     if (!FFMPEGLibraryInstance.IsLoaded())
1460         return 0;
1461 
1462     // Creates our frames
1463     RTPFrame srcRTP(src, srcLen);
1464     RTPFrame dstRTP(dst, dstLen, RTP_DYNAMIC_PAYLOAD);
1465     dstLen = 0;
1466     flags = 0;
1467 
1468     int srcPayloadSize = srcRTP.GetPayloadSize();
1469     SetDynamicDecodingParams(true); // Adjust dynamic settings, restart allowed
1470 
1471     // Don't exceed buffer limits.  m_encFrameLen set by ResizeDecodingFrame
1472     if(m_lastPktOffset + srcPayloadSize < m_encFrameLen)
1473     {
1474         // Copy the payload data into the buffer and update the offset
1475         memcpy(m_encFrameBuffer + m_lastPktOffset, srcRTP.GetPayloadPtr(),
1476                srcPayloadSize);
1477         m_lastPktOffset += srcPayloadSize;
1478     }
1479     else {
1480 
1481         // Likely we dropped the marker packet, so at this point we have a
1482         // full buffer with some of the frame we wanted and some of the next
1483         // frame.
1484 
1485         //I'm on the fence about whether to send the data to the
1486         // decoder and hope for the best, or to throw it all away and start
1487         // again.
1488 
1489 
1490         // throw the data away and ask for an IFrame
1491         PTRACE(1, "MPEG4", "Decoder waiting for an I-Frame");
1492         m_lastPktOffset = 0;
1493         flags = (m_gotAGoodFrame ? PluginCodec_ReturnCoderRequestIFrame : 0);
1494         m_gotAGoodFrame = false;
1495         return 1;
1496     }
1497 
1498     // decode the frame if we got the marker packet
1499     int got_picture = 0;
1500     if (srcRTP.GetMarker()) {
1501         m_frameNum++;
1502         int len = FFMPEGLibraryInstance.AvcodecDecodeVideo
1503                         (m_avcontext, m_avpicture, &got_picture,
1504                          m_encFrameBuffer, m_lastPktOffset);
1505 
1506         if (len >= 0 && got_picture) {
1507 #ifdef LIBAVCODEC_HAVE_SOURCE_DIR
1508             if (DecoderError(m_keyRefreshThresh)) {
1509                 // ask for an IFrame update, but still show what we've got
1510                 flags = (m_gotAGoodFrame ? PluginCodec_ReturnCoderRequestIFrame : 0);
1511                 m_gotAGoodFrame = false;
1512             }
1513 #endif
1514             PTRACE(4, "MPEG4", "Decoded " << len << " bytes" << ", Resolution: " << m_avcontext->width << "x" << m_avcontext->height);
1515             // If the decoding size changes on us, we can catch it and resize
1516             if (!m_disableResize
1517                 && (m_frameWidth != (unsigned)m_avcontext->width
1518                    || m_frameHeight != (unsigned)m_avcontext->height))
1519             {
1520                 // Set the decoding width to what avcodec says it is
1521                 m_frameWidth  = m_avcontext->width;
1522                 m_frameHeight = m_avcontext->height;
1523                 // Set dynamic settings (framesize), restart as needed
1524                 SetDynamicDecodingParams(true);
1525                 return true;
1526             }
1527 
1528             // it's stride time
1529             int frameBytes = (m_frameWidth * m_frameHeight * 3) / 2;
1530             PluginCodec_Video_FrameHeader * header
1531                 = (PluginCodec_Video_FrameHeader *)dstRTP.GetPayloadPtr();
1532             header->x = header->y = 0;
1533             header->width = m_frameWidth;
1534             header->height = m_frameHeight;
1535             unsigned char *dstData = OPAL_VIDEO_FRAME_DATA_PTR(header);
1536             for (int i=0; i<3; i ++) {
1537                 unsigned char *srcData = m_avpicture->data[i];
1538                 int dst_stride = i ? m_frameWidth >> 1 : m_frameWidth;
1539                 int src_stride = m_avpicture->linesize[i];
1540                 int h = i ? m_frameHeight >> 1 : m_frameHeight;
1541                 if (src_stride==dst_stride) {
1542                     memcpy(dstData, srcData, dst_stride*h);
1543                     dstData += dst_stride*h;
1544                 }
1545                 else
1546                 {
1547                     while (h--) {
1548                         memcpy(dstData, srcData, dst_stride);
1549                         dstData += dst_stride;
1550                         srcData += src_stride;
1551                     }
1552                 }
1553             }
1554             // Treating the screen as an RTP is weird
1555             dstRTP.SetPayloadSize(sizeof(PluginCodec_Video_FrameHeader)
1556                                   + frameBytes);
1557             dstRTP.SetPayloadType(RTP_DYNAMIC_PAYLOAD);
1558             dstRTP.SetTimestamp(srcRTP.GetTimestamp());
1559             dstRTP.SetMarker(true);
1560             dstLen = dstRTP.GetFrameLen();
1561             flags = PluginCodec_ReturnCoderLastFrame;
1562             m_gotAGoodFrame = true;
1563         }
1564         else {
1565             PTRACE(5, "MPEG4", "Decoded "<< len << " bytes without getting a Picture...");
1566             // decoding error, ask for an IFrame update
1567             flags = (m_gotAGoodFrame ? PluginCodec_ReturnCoderRequestIFrame : 0);
1568             m_gotAGoodFrame = false;
1569         }
1570         m_lastPktOffset = 0;
1571     }
1572     return true;
1573 }
1574 
1575 
1576 /////////////////////////////////////////////////////////////////////////////
1577 //
1578 // OPAL plugin decoder functions
1579 //
1580 
create_decoder(const struct PluginCodec_Definition *)1581 static void * create_decoder(const struct PluginCodec_Definition *)
1582 {
1583   return new MPEG4DecoderContext;
1584 }
1585 
1586 // This is assuming the second param is the context...
decoder_set_options(const struct PluginCodec_Definition *,void * m_context,const char *,void * parm,unsigned * parmLen)1587 static int decoder_set_options(
1588       const struct PluginCodec_Definition *,
1589       void * m_context ,
1590       const char *,
1591       void * parm,
1592       unsigned * parmLen)
1593 {
1594   if (parmLen == NULL || *parmLen != sizeof(const char **))
1595     return 0;
1596 
1597   MPEG4DecoderContext * context = (MPEG4DecoderContext *)m_context;
1598 
1599   // This checks if any of the following options have been passed:
1600   // 1) get the "Frame Width" media format parameter and let the decoder know
1601   // 2) get the "Frame Height" media format parameter and let the decoder know
1602   // 3) Check if "Error Recovery" boolean option has been passed, then sets the
1603   //    value in the decoder context
1604   // 4) Check if "Error Threshold" integer has been passed, then sets the value
1605   // 5) Check if "Disable Resize" boolean has been passed, then sets the value
1606 
1607   if (parm != NULL) {
1608     const char ** options = (const char **)parm;
1609     int i;
1610     for (i = 0; options[i] != NULL; i += 2) {
1611       if (STRCMPI(options[i], PLUGINCODEC_OPTION_FRAME_WIDTH) == 0)
1612         context->SetFrameWidth(atoi(options[i+1]));
1613       else if(STRCMPI(options[i], PLUGINCODEC_OPTION_FRAME_HEIGHT) == 0)
1614         context->SetFrameHeight(atoi(options[i+1]));
1615       else if(STRCMPI(options[i], "Error Recovery") == 0)
1616         context->SetErrorRecovery(atoi(options[i+1]));
1617       else if(STRCMPI(options[i], "Error Threshold") == 0)
1618         context->SetErrorThresh(atoi(options[i+1]));
1619       else if(STRCMPI(options[i], "Disable Resize") == 0)
1620         context->SetDisableResize(atoi(options[i+1]));
1621     }
1622   }
1623   return 1;
1624 }
1625 
destroy_decoder(const struct PluginCodec_Definition *,void * m_context)1626 static void destroy_decoder(const struct PluginCodec_Definition * /*codec*/, void * m_context)
1627 {
1628   MPEG4DecoderContext * context = (MPEG4DecoderContext *)m_context;
1629   delete context;
1630 }
1631 
codec_decoder(const struct PluginCodec_Definition *,void * m_context,const void * from,unsigned * fromLen,void * to,unsigned * toLen,unsigned int * flag)1632 static int codec_decoder(const struct PluginCodec_Definition *,
1633                                            void * m_context,
1634                                      const void * from,
1635                                        unsigned * fromLen,
1636                                            void * to,
1637                                        unsigned * toLen,
1638                                    unsigned int * flag)
1639 {
1640   MPEG4DecoderContext * context = (MPEG4DecoderContext *)m_context;
1641   return context->DecodeFrames((const BYTE *)from, *fromLen, (BYTE *)to, *toLen, *flag);
1642 }
1643 
decoder_get_output_data_size(const PluginCodec_Definition *,void * m_context,const char *,void *,unsigned *)1644 static int decoder_get_output_data_size(const PluginCodec_Definition * /*codec*/, void * m_context, const char *, void *, unsigned *)
1645 {
1646   MPEG4DecoderContext * context = (MPEG4DecoderContext *) m_context;
1647   return sizeof(PluginCodec_Video_FrameHeader) + (context->GetFrameBytes() * 3 / 2);
1648 }
1649 
1650 // Plugin Codec Definitions
1651 
1652 static PluginCodec_ControlDefn sipDecoderControls[] = {
1653   { PLUGINCODEC_CONTROL_GET_CODEC_OPTIONS,     get_codec_options },
1654   { PLUGINCODEC_CONTROL_SET_CODEC_OPTIONS,     decoder_set_options },
1655   { PLUGINCODEC_CONTROL_GET_OUTPUT_DATA_SIZE,  decoder_get_output_data_size },
1656   { NULL }
1657 };
1658 
1659 /////////////////////////////////////////////////////////////////////////////
1660 
1661 
1662 static struct PluginCodec_information licenseInfo = {
1663 1168031935,                                                       // timestamp = Fri 5 Jan 2006 21:19:40 PM UTC
1664 
1665   "Craig Southeren, Guilhem Tardy, Derek Smithies, Michael Smith, Josh Mahonin", // authors
1666   "1.0",                                                        // source code version
1667   "openh323@openh323.org",                                      // source code email
1668   "http://sourceforge.net/projects/openh323",                   // source code URL
1669   "Copyright (C) 2007 Canadian Bank Note, Limited.",
1670   "Copyright (C) 2006 by Post Increment"                       // source code copyright
1671   ", Copyright (C) 2005 Salyens"
1672   ", Copyright (C) 2001 March Networks Corporation"
1673   ", Copyright (C) 1999-2000 Equivalence Pty. Ltd."
1674   "MPL 1.0",                                                    // source code license
1675   PluginCodec_License_MPL,                                      // source code license
1676 
1677   "FFMPEG",                                                     // codec description
1678   "Michael Niedermayer, Fabrice Bellard",                       // codec author
1679   "4.7.1",                                                      // codec version
1680   "ffmpeg-devel-request@ mplayerhq.hu",                         // codec email
1681   "http://sourceforge.net/projects/ffmpeg/",                    // codec URL
1682   "Copyright (c) 2000-2001 Fabrice Bellard"                     // codec copyright information
1683   ", Copyright (c) 2002-2003 Michael Niedermayer",
1684   "GNU LESSER GENERAL PUBLIC LICENSE, Version 2.1, February 1999", // codec license
1685   PluginCodec_License_LGPL                                         // codec license code
1686 };
1687 
1688 /////////////////////////////////////////////////////////////////////////////
1689 
1690 static const char YUV420PDesc[]  = { "YUV420P" };
1691 static const char mpeg4Desc[]      = { "MPEG4" };
1692 static const char sdpMPEG4[]   = { "MP4V-ES" };
1693 
1694 /////////////////////////////////////////////////////////////////////////////
1695 
1696 enum
1697 {
1698     H245_ANNEX_E_PROFILE_LEVEL = 0 | PluginCodec_H245_NonCollapsing | PluginCodec_H245_TCS | PluginCodec_H245_OLC | PluginCodec_H245_ReqMode,
1699     H245_ANNEX_E_OBJECT        = 1 | PluginCodec_H245_NonCollapsing |                        PluginCodec_H245_OLC | PluginCodec_H245_ReqMode,
1700     H245_ANNEX_E_DCI           = 2 | PluginCodec_H245_NonCollapsing |                        PluginCodec_H245_OLC,
1701     H245_ANNEX_E_DRAWING_ORDER = 3 | PluginCodec_H245_NonCollapsing |                        PluginCodec_H245_OLC,
1702     H245_ANNEX_E_VBCH          = 4 | PluginCodec_H245_Collapsing    | PluginCodec_H245_TCS | PluginCodec_H245_OLC | PluginCodec_H245_ReqMode,
1703 };
1704 
MergeProfileAndLevelMPEG4(char ** result,const char * dest,const char * src)1705 static int MergeProfileAndLevelMPEG4(char ** result, const char * dest, const char * src)
1706 {
1707   // Due to the "special case" where the value 8 and 9 is simple profile level zero and zero b,
1708   // we cannot actually use a simple min merge!
1709   unsigned dstPL = strtoul(dest, NULL, 10);
1710   unsigned srcPL = strtoul(src, NULL, 10);
1711 
1712   unsigned dstProfile;
1713   int dstLevel;
1714   unsigned srcProfile;
1715   int srcLevel;
1716 
1717   switch (dstPL) {
1718     case 0:
1719       dstProfile = 0;
1720       dstLevel = -10;
1721       break;
1722     case 8:
1723       dstProfile = 0;
1724       dstLevel = -2;
1725       break;
1726     case 9:
1727       dstProfile = 0;
1728       dstLevel = -1;
1729       break;
1730     default:
1731       dstProfile = (dstPL>>4)&7;
1732       dstLevel = dstPL&7;
1733       break;
1734   }
1735 
1736   switch (srcPL) {
1737     case 0:
1738       srcProfile = 0;
1739       srcLevel = -10;
1740       break;
1741     case 8:
1742       srcProfile = 0;
1743       srcLevel = -2;
1744       break;
1745     case 9:
1746       srcProfile = 0;
1747       srcLevel = -1;
1748       break;
1749     default:
1750       srcProfile = (srcPL>>4)&7;
1751       srcLevel = srcPL&7;
1752       break;
1753   }
1754 
1755 
1756   if (dstProfile > srcProfile)
1757     dstProfile = srcProfile;
1758   if (dstLevel > srcLevel)
1759     dstLevel = srcLevel;
1760 
1761   char buffer[10];
1762 
1763   switch (dstLevel) {
1764     case -10:
1765       sprintf(buffer, "%u", (0));
1766       break;
1767     case -2:
1768       sprintf(buffer, "%u", (8));
1769       break;
1770     case -1:
1771       sprintf(buffer, "%u", (9));
1772       break;
1773     default:
1774       sprintf(buffer, "%u", (dstProfile<<4)|(dstLevel));
1775       break;
1776   }
1777 
1778   *result = strdup(buffer);
1779 
1780   return true;
1781 }
1782 
FreeString(char * str)1783 static void FreeString(char * str)
1784 {
1785   free(str);
1786 }
1787 
1788 static struct PluginCodec_Option const H245ProfileLevelMPEG4 =
1789 {
1790   PluginCodec_IntegerOption,          // Option type
1791   ProfileAndLevel,                    // User visible name
1792   false,                              // User Read/Only flag
1793   PluginCodec_CustomMerge,            // Merge mode
1794   "5",                                // Initial value (Simple Profile/Level 5)
1795   "profile-level-id",                 // FMTP option name
1796   "0",                                // FMTP default value (Simple Profile/Level 1)
1797   H245_ANNEX_E_PROFILE_LEVEL,         // H.245 generic capability code and bit mask
1798   "0",                                // Minimum value
1799   "245",                              // Maximum value
1800   MergeProfileAndLevelMPEG4,          // Function to do merge
1801   FreeString                          // Function to free memory in string
1802 };
1803 
1804 static struct PluginCodec_Option const H245ObjectMPEG4 =
1805 {
1806   PluginCodec_IntegerOption,          // Option type
1807   "H.245 Object Id",                  // User visible name
1808   true,                               // User Read/Only flag
1809   PluginCodec_EqualMerge,             // Merge mode
1810   "0",                                // Initial value
1811   NULL,                               // FMTP option name
1812   NULL,                               // FMTP default value
1813   H245_ANNEX_E_OBJECT,                // H.245 generic capability code and bit mask
1814   "0",                                // Minimum value
1815   "15"                                // Maximum value
1816 };
1817 
1818 static struct PluginCodec_Option const DecoderConfigInfoMPEG4 =
1819 {
1820   PluginCodec_OctetsOption,           // Option type
1821   "DCI",                              // User visible name
1822   false,                              // User Read/Only flag
1823   PluginCodec_NoMerge,                // Merge mode
1824   "",                                 // Initial value
1825   "config",                           // FMTP option name
1826   NULL,                               // FMTP default value
1827   H245_ANNEX_E_DCI                    // H.245 generic capability code and bit mask
1828 };
1829 
1830 static struct PluginCodec_Option const MediaPacketizationMPEG4 =
1831 {
1832   PluginCodec_StringOption,           // Option type
1833   PLUGINCODEC_MEDIA_PACKETIZATION,    // User visible name
1834   true,                               // User Read/Only flag
1835   PluginCodec_EqualMerge,             // Merge mode
1836   OpalPluginCodec_Identifer_MPEG4     // Initial value
1837 };
1838 
1839 
1840 static struct PluginCodec_Option const * const optionTable[] = {
1841   &H245ProfileLevelMPEG4,
1842   &H245ObjectMPEG4,
1843   &DecoderConfigInfoMPEG4,
1844 //  &ProfileMPEG4,
1845 //  &LevelMPEG4,
1846   &MediaPacketizationMPEG4,
1847   NULL
1848 };
1849 
1850 static struct PluginCodec_H323GenericCodecData H323GenericMPEG4 = {
1851   OpalPluginCodec_Identifer_MPEG4
1852 };
1853 
1854 
1855 /////////////////////////////////////////////////////////////////////////////
1856 
1857 static struct PluginCodec_Definition mpeg4CodecDefn[2] = {
1858 {
1859   // Encoder
1860   PLUGIN_CODEC_VERSION_OPTIONS,       // codec API version
1861   &licenseInfo,                       // license information
1862 
1863   PluginCodec_MediaTypeVideo |        // video codec
1864   PluginCodec_RTPTypeShared |
1865   PluginCodec_RTPTypeDynamic,         // specified RTP type
1866 
1867   mpeg4Desc,                          // text decription
1868   YUV420PDesc,                        // source format
1869   mpeg4Desc,                          // destination format
1870 
1871   optionTable,                        // user data
1872 
1873   MPEG4_CLOCKRATE,                    // samples per second
1874   MPEG4_BITRATE,                      // raw bits per second
1875   20000,                              // nanoseconds per frame
1876 
1877   {{
1878     CIF_WIDTH,                        // frame width
1879     CIF_HEIGHT,                       // frame height
1880     10,                               // recommended frame rate
1881     60,                               // maximum frame rate
1882   }},
1883   0,                                  // IANA RTP payload code
1884   sdpMPEG4,                           // RTP payload name
1885 
1886   create_encoder,                     // create codec function
1887   destroy_encoder,                    // destroy codec
1888   codec_encoder,                      // encode/decode
1889   sipEncoderControls,                 // codec controls
1890 
1891   PluginCodec_H323Codec_generic,      // h323CapabilityType
1892   &H323GenericMPEG4                   // h323CapabilityData
1893 },
1894 {
1895   // Decoder
1896   PLUGIN_CODEC_VERSION_OPTIONS,       // codec API version
1897   &licenseInfo,                       // license information
1898 
1899   PluginCodec_MediaTypeVideo |        // video codec
1900   PluginCodec_RTPTypeShared |
1901   PluginCodec_RTPTypeDynamic,         // specified RTP type
1902 
1903   mpeg4Desc,                          // text decription
1904   mpeg4Desc,                          // source format
1905   YUV420PDesc,                        // destination format
1906 
1907   optionTable,                        // user data
1908 
1909   MPEG4_CLOCKRATE,                    // samples per second
1910   MPEG4_BITRATE,                      // raw bits per second
1911   20000,                              // nanoseconds per frame
1912 
1913   {{
1914     CIF_WIDTH,                        // frame width
1915     CIF_HEIGHT,                       // frame height
1916     10,                               // recommended frame rate
1917     60,                               // maximum frame rate
1918   }},
1919   0,                                  // IANA RTP payload code
1920   sdpMPEG4,                           // RTP payload name
1921 
1922   create_decoder,                     // create codec function
1923   destroy_decoder,                    // destroy codec
1924   codec_decoder,                      // encode/decode
1925   sipDecoderControls,                 // codec controls
1926 
1927   PluginCodec_H323Codec_generic,      // h323CapabilityType
1928   &H323GenericMPEG4                   // h323CapabilityData
1929 },
1930 
1931 };
1932 
1933 /////////////////////////////////////////////////////////////////////////////
1934 
1935 extern "C" {
1936 PLUGIN_CODEC_DLL_API struct PluginCodec_Definition *
PLUGIN_CODEC_GET_CODEC_FN(unsigned * count,unsigned version)1937 PLUGIN_CODEC_GET_CODEC_FN(unsigned * count, unsigned version)
1938 {
1939   if (!FFMPEGLibraryInstance.Load()) {
1940     *count = 0;
1941     PTRACE(1, "MPEG4", "Disabled");
1942     return NULL;
1943   }
1944 
1945   // check version numbers etc
1946   if (version < PLUGIN_CODEC_VERSION_OPTIONS) {
1947     *count = 0;
1948     return NULL;
1949   }
1950 
1951   *count = sizeof(mpeg4CodecDefn) / sizeof(struct PluginCodec_Definition);
1952   return mpeg4CodecDefn;
1953 }
1954 };
1955