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