~ubuntu-branches/ubuntu/vivid/freerdp/vivid

« back to all changes in this revision

Viewing changes to channels/drdynvc/tsmf/ffmpeg/tsmf_ffmpeg.c

  • Committer: Package Import Robot
  • Author(s): Iain Lane
  • Date: 2014-11-11 12:20:50 UTC
  • mfrom: (1.2.5)
  • mto: This revision was merged to the branch mainline in revision 24.
  • Revision ID: package-import@ubuntu.com-20141111122050-7z628f4ab38qxad5
Tags: upstream-1.1.0~git20140921.1.440916e+dfsg1
ImportĀ upstreamĀ versionĀ 1.1.0~git20140921.1.440916e+dfsg1

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
/**
2
 
 * FreeRDP: A Remote Desktop Protocol client.
3
 
 * Video Redirection Virtual Channel - FFmpeg Decoder
4
 
 *
5
 
 * Copyright 2010-2011 Vic Lee
6
 
 *
7
 
 * Licensed under the Apache License, Version 2.0 (the "License");
8
 
 * you may not use this file except in compliance with the License.
9
 
 * You may obtain a copy of the License at
10
 
 *
11
 
 *     http://www.apache.org/licenses/LICENSE-2.0
12
 
 *
13
 
 * Unless required by applicable law or agreed to in writing, software
14
 
 * distributed under the License is distributed on an "AS IS" BASIS,
15
 
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16
 
 * See the License for the specific language governing permissions and
17
 
 * limitations under the License.
18
 
 */
19
 
 
20
 
#include <stdio.h>
21
 
#include <stdlib.h>
22
 
#include <string.h>
23
 
#include <freerdp/utils/memory.h>
24
 
#include <freerdp/utils/event.h>
25
 
#include <freerdp/plugins/tsmf.h>
26
 
#include <libavcodec/avcodec.h>
27
 
 
28
 
#include "tsmf_constants.h"
29
 
#include "tsmf_decoder.h"
30
 
 
31
 
/* Compatibility with older FFmpeg */
32
 
#if LIBAVUTIL_VERSION_MAJOR < 50
33
 
#define AVMEDIA_TYPE_VIDEO 0
34
 
#define AVMEDIA_TYPE_AUDIO 1
35
 
#endif
36
 
 
37
 
typedef struct _TSMFFFmpegDecoder
38
 
{
39
 
        ITSMFDecoder iface;
40
 
 
41
 
        int media_type;
42
 
        enum CodecID codec_id;
43
 
        AVCodecContext* codec_context;
44
 
        AVCodec* codec;
45
 
        AVFrame* frame;
46
 
        int prepared;
47
 
 
48
 
        uint8* decoded_data;
49
 
        uint32 decoded_size;
50
 
        uint32 decoded_size_max;
51
 
} TSMFFFmpegDecoder;
52
 
 
53
 
static boolean tsmf_ffmpeg_init_context(ITSMFDecoder* decoder)
54
 
{
55
 
        TSMFFFmpegDecoder* mdecoder = (TSMFFFmpegDecoder*) decoder;
56
 
 
57
 
        mdecoder->codec_context = avcodec_alloc_context();
58
 
        if (!mdecoder->codec_context)
59
 
        {
60
 
                DEBUG_WARN("avcodec_alloc_context failed.");
61
 
                return false;
62
 
        }
63
 
 
64
 
        return true;
65
 
}
66
 
 
67
 
static boolean tsmf_ffmpeg_init_video_stream(ITSMFDecoder* decoder, const TS_AM_MEDIA_TYPE* media_type)
68
 
{
69
 
        TSMFFFmpegDecoder* mdecoder = (TSMFFFmpegDecoder*) decoder;
70
 
 
71
 
        mdecoder->codec_context->width = media_type->Width;
72
 
        mdecoder->codec_context->height = media_type->Height;
73
 
        mdecoder->codec_context->bit_rate = media_type->BitRate;
74
 
        mdecoder->codec_context->time_base.den = media_type->SamplesPerSecond.Numerator;
75
 
        mdecoder->codec_context->time_base.num = media_type->SamplesPerSecond.Denominator;
76
 
 
77
 
        mdecoder->frame = avcodec_alloc_frame();
78
 
 
79
 
        return true;
80
 
}
81
 
 
82
 
static boolean tsmf_ffmpeg_init_audio_stream(ITSMFDecoder* decoder, const TS_AM_MEDIA_TYPE* media_type)
83
 
{
84
 
        TSMFFFmpegDecoder* mdecoder = (TSMFFFmpegDecoder*) decoder;
85
 
 
86
 
        mdecoder->codec_context->sample_rate = media_type->SamplesPerSecond.Numerator;
87
 
        mdecoder->codec_context->bit_rate = media_type->BitRate;
88
 
        mdecoder->codec_context->channels = media_type->Channels;
89
 
        mdecoder->codec_context->block_align = media_type->BlockAlign;
90
 
 
91
 
#ifdef AV_CPU_FLAG_SSE2
92
 
        mdecoder->codec_context->dsp_mask = AV_CPU_FLAG_SSE2 | AV_CPU_FLAG_MMX2;
93
 
#else
94
 
#if LIBAVCODEC_VERSION_MAJOR < 53
95
 
        mdecoder->codec_context->dsp_mask = FF_MM_SSE2 | FF_MM_MMXEXT;
96
 
#else
97
 
        mdecoder->codec_context->dsp_mask = FF_MM_SSE2 | FF_MM_MMX2;
98
 
#endif
99
 
#endif
100
 
 
101
 
        return true;
102
 
}
103
 
 
104
 
static boolean tsmf_ffmpeg_init_stream(ITSMFDecoder* decoder, const TS_AM_MEDIA_TYPE* media_type)
105
 
{
106
 
        TSMFFFmpegDecoder* mdecoder = (TSMFFFmpegDecoder*) decoder;
107
 
        uint32 size;
108
 
        const uint8* s;
109
 
        uint8* p;
110
 
 
111
 
        mdecoder->codec = avcodec_find_decoder(mdecoder->codec_id);
112
 
        if (!mdecoder->codec)
113
 
        {
114
 
                DEBUG_WARN("avcodec_find_decoder failed.");
115
 
                return false;
116
 
        }
117
 
 
118
 
        mdecoder->codec_context->codec_id = mdecoder->codec_id;
119
 
        mdecoder->codec_context->codec_type = mdecoder->media_type;
120
 
 
121
 
        if (mdecoder->media_type == AVMEDIA_TYPE_VIDEO)
122
 
        {
123
 
                if (!tsmf_ffmpeg_init_video_stream(decoder, media_type))
124
 
                        return false;
125
 
        }
126
 
        else if (mdecoder->media_type == AVMEDIA_TYPE_AUDIO)
127
 
        {
128
 
                if (!tsmf_ffmpeg_init_audio_stream(decoder, media_type))
129
 
                        return false;
130
 
        }
131
 
 
132
 
        if (media_type->ExtraData)
133
 
        {
134
 
                if (media_type->SubType == TSMF_SUB_TYPE_AVC1 &&
135
 
                        media_type->FormatType == TSMF_FORMAT_TYPE_MPEG2VIDEOINFO)
136
 
                {
137
 
                        /* The extradata format that FFmpeg uses is following CodecPrivate in Matroska.
138
 
                           See http://haali.su/mkv/codecs.pdf */
139
 
                        mdecoder->codec_context->extradata_size = media_type->ExtraDataSize + 8;
140
 
                        mdecoder->codec_context->extradata = xzalloc(mdecoder->codec_context->extradata_size);
141
 
                        p = mdecoder->codec_context->extradata;
142
 
                        *p++ = 1; /* Reserved? */
143
 
                        *p++ = media_type->ExtraData[8]; /* Profile */
144
 
                        *p++ = 0; /* Profile */
145
 
                        *p++ = media_type->ExtraData[12]; /* Level */
146
 
                        *p++ = 0xff; /* Flag? */
147
 
                        *p++ = 0xe0 | 0x01; /* Reserved | #sps */
148
 
                        s = media_type->ExtraData + 20;
149
 
                        size = ((uint32)(*s)) * 256 + ((uint32)(*(s + 1)));
150
 
                        memcpy(p, s, size + 2);
151
 
                        s += size + 2;
152
 
                        p += size + 2;
153
 
                        *p++ = 1; /* #pps */
154
 
                        size = ((uint32)(*s)) * 256 + ((uint32)(*(s + 1)));
155
 
                        memcpy(p, s, size + 2);
156
 
                }
157
 
                else
158
 
                {
159
 
                        /* Add a padding to avoid invalid memory read in some codec */
160
 
                        mdecoder->codec_context->extradata_size = media_type->ExtraDataSize + 8;
161
 
                        mdecoder->codec_context->extradata = xzalloc(mdecoder->codec_context->extradata_size);
162
 
                        memcpy(mdecoder->codec_context->extradata, media_type->ExtraData, media_type->ExtraDataSize);
163
 
                        memset(mdecoder->codec_context->extradata + media_type->ExtraDataSize, 0, 8);
164
 
                }
165
 
        }
166
 
 
167
 
        if (mdecoder->codec->capabilities & CODEC_CAP_TRUNCATED)
168
 
                mdecoder->codec_context->flags |= CODEC_FLAG_TRUNCATED;
169
 
 
170
 
        return true;
171
 
}
172
 
 
173
 
static boolean tsmf_ffmpeg_prepare(ITSMFDecoder* decoder)
174
 
{
175
 
        TSMFFFmpegDecoder* mdecoder = (TSMFFFmpegDecoder*) decoder;
176
 
 
177
 
        if (avcodec_open(mdecoder->codec_context, mdecoder->codec) < 0)
178
 
        {
179
 
                DEBUG_WARN("avcodec_open failed.");
180
 
                return false;
181
 
        }
182
 
 
183
 
        mdecoder->prepared = 1;
184
 
 
185
 
        return true;
186
 
}
187
 
 
188
 
static boolean tsmf_ffmpeg_set_format(ITSMFDecoder* decoder, TS_AM_MEDIA_TYPE* media_type)
189
 
{
190
 
        TSMFFFmpegDecoder* mdecoder = (TSMFFFmpegDecoder*) decoder;
191
 
 
192
 
        switch (media_type->MajorType)
193
 
        {
194
 
                case TSMF_MAJOR_TYPE_VIDEO:
195
 
                        mdecoder->media_type = AVMEDIA_TYPE_VIDEO;
196
 
                        break;
197
 
                case TSMF_MAJOR_TYPE_AUDIO:
198
 
                        mdecoder->media_type = AVMEDIA_TYPE_AUDIO;
199
 
                        break;
200
 
                default:
201
 
                        return false;
202
 
        }
203
 
        switch (media_type->SubType)
204
 
        {
205
 
                case TSMF_SUB_TYPE_WVC1:
206
 
                        mdecoder->codec_id = CODEC_ID_VC1;
207
 
                        break;
208
 
                case TSMF_SUB_TYPE_WMA2:
209
 
                        mdecoder->codec_id = CODEC_ID_WMAV2;
210
 
                        break;
211
 
                case TSMF_SUB_TYPE_WMA9:
212
 
                        mdecoder->codec_id = CODEC_ID_WMAPRO;
213
 
                        break;
214
 
                case TSMF_SUB_TYPE_MP3:
215
 
                        mdecoder->codec_id = CODEC_ID_MP3;
216
 
                        break;
217
 
                case TSMF_SUB_TYPE_MP2A:
218
 
                        mdecoder->codec_id = CODEC_ID_MP2;
219
 
                        break;
220
 
                case TSMF_SUB_TYPE_MP2V:
221
 
                        mdecoder->codec_id = CODEC_ID_MPEG2VIDEO;
222
 
                        break;
223
 
                case TSMF_SUB_TYPE_WMV3:
224
 
                        mdecoder->codec_id = CODEC_ID_WMV3;
225
 
                        break;
226
 
                case TSMF_SUB_TYPE_AAC:
227
 
                        mdecoder->codec_id = CODEC_ID_AAC;
228
 
                        /* For AAC the pFormat is a HEAACWAVEINFO struct, and the codec data
229
 
                           is at the end of it. See
230
 
                           http://msdn.microsoft.com/en-us/library/dd757806.aspx */
231
 
                        if (media_type->ExtraData)
232
 
                        {
233
 
                                media_type->ExtraData += 12;
234
 
                                media_type->ExtraDataSize -= 12;
235
 
                        }
236
 
                        break;
237
 
                case TSMF_SUB_TYPE_H264:
238
 
                case TSMF_SUB_TYPE_AVC1:
239
 
                        mdecoder->codec_id = CODEC_ID_H264;
240
 
                        break;
241
 
                case TSMF_SUB_TYPE_AC3:
242
 
                        mdecoder->codec_id = CODEC_ID_AC3;
243
 
                        break;
244
 
                default:
245
 
                        return false;
246
 
        }
247
 
 
248
 
        if (!tsmf_ffmpeg_init_context(decoder))
249
 
                return false;
250
 
        if (!tsmf_ffmpeg_init_stream(decoder, media_type))
251
 
                return false;
252
 
        if (!tsmf_ffmpeg_prepare(decoder))
253
 
                return false;
254
 
 
255
 
        return true;
256
 
}
257
 
 
258
 
static boolean tsmf_ffmpeg_decode_video(ITSMFDecoder* decoder, const uint8* data, uint32 data_size, uint32 extensions)
259
 
{
260
 
        TSMFFFmpegDecoder* mdecoder = (TSMFFFmpegDecoder*) decoder;
261
 
        int decoded;
262
 
        int len;
263
 
        AVFrame* frame;
264
 
        boolean ret = true;
265
 
 
266
 
#if LIBAVCODEC_VERSION_MAJOR < 52 || (LIBAVCODEC_VERSION_MAJOR == 52 && LIBAVCODEC_VERSION_MINOR <= 20)
267
 
        len = avcodec_decode_video(mdecoder->codec_context, mdecoder->frame, &decoded, data, data_size);
268
 
#else
269
 
        {
270
 
                AVPacket pkt;
271
 
                av_init_packet(&pkt);
272
 
                pkt.data = (uint8*) data;
273
 
                pkt.size = data_size;
274
 
                if (extensions & TSMM_SAMPLE_EXT_CLEANPOINT)
275
 
                        pkt.flags |= AV_PKT_FLAG_KEY;
276
 
                len = avcodec_decode_video2(mdecoder->codec_context, mdecoder->frame, &decoded, &pkt);
277
 
        }
278
 
#endif
279
 
 
280
 
        if (len < 0)
281
 
        {
282
 
                DEBUG_WARN("data_size %d, avcodec_decode_video failed (%d)", data_size, len);
283
 
                ret = false;
284
 
        }
285
 
        else if (!decoded)
286
 
        {
287
 
                DEBUG_WARN("data_size %d, no frame is decoded.", data_size);
288
 
                ret = false;
289
 
        }
290
 
        else
291
 
        {
292
 
                DEBUG_DVC("linesize[0] %d linesize[1] %d linesize[2] %d linesize[3] %d "
293
 
                        "pix_fmt %d width %d height %d",
294
 
                        mdecoder->frame->linesize[0], mdecoder->frame->linesize[1],
295
 
                        mdecoder->frame->linesize[2], mdecoder->frame->linesize[3],
296
 
                        mdecoder->codec_context->pix_fmt,
297
 
                        mdecoder->codec_context->width, mdecoder->codec_context->height);
298
 
 
299
 
                mdecoder->decoded_size = avpicture_get_size(mdecoder->codec_context->pix_fmt,
300
 
                        mdecoder->codec_context->width, mdecoder->codec_context->height);
301
 
                mdecoder->decoded_data = xzalloc(mdecoder->decoded_size);
302
 
                frame = avcodec_alloc_frame();
303
 
                avpicture_fill((AVPicture *) frame, mdecoder->decoded_data,
304
 
                        mdecoder->codec_context->pix_fmt,
305
 
                        mdecoder->codec_context->width, mdecoder->codec_context->height);
306
 
 
307
 
                av_picture_copy((AVPicture *) frame, (AVPicture *) mdecoder->frame,
308
 
                        mdecoder->codec_context->pix_fmt,
309
 
                        mdecoder->codec_context->width, mdecoder->codec_context->height);
310
 
 
311
 
                av_free(frame);
312
 
        }
313
 
 
314
 
        return ret;
315
 
}
316
 
 
317
 
static boolean tsmf_ffmpeg_decode_audio(ITSMFDecoder* decoder, const uint8* data, uint32 data_size, uint32 extensions)
318
 
{
319
 
        TSMFFFmpegDecoder* mdecoder = (TSMFFFmpegDecoder*) decoder;
320
 
        int len;
321
 
        int frame_size;
322
 
        uint32 src_size;
323
 
        const uint8* src;
324
 
        uint8* dst;
325
 
        int dst_offset;
326
 
 
327
 
#if 0
328
 
        LLOGLN(0, ("tsmf_ffmpeg_decode_audio: data_size %d", data_size));
329
 
        int i;
330
 
        for (i = 0; i < data_size; i++)
331
 
        {
332
 
                LLOG(0, ("%02X ", data[i]));
333
 
                if (i % 16 == 15)
334
 
                        LLOG(0, ("\n"));
335
 
        }
336
 
        LLOG(0, ("\n"));
337
 
#endif
338
 
 
339
 
        if (mdecoder->decoded_size_max == 0)
340
 
                mdecoder->decoded_size_max = AVCODEC_MAX_AUDIO_FRAME_SIZE + 16;
341
 
        mdecoder->decoded_data = xzalloc(mdecoder->decoded_size_max);
342
 
        /* align the memory for SSE2 needs */
343
 
        dst = (uint8*) (((uintptr_t)mdecoder->decoded_data + 15) & ~ 0x0F);
344
 
        dst_offset = dst - mdecoder->decoded_data;
345
 
        src = data;
346
 
        src_size = data_size;
347
 
 
348
 
        while (src_size > 0)
349
 
        {
350
 
                /* Ensure enough space for decoding */
351
 
                if (mdecoder->decoded_size_max - mdecoder->decoded_size < AVCODEC_MAX_AUDIO_FRAME_SIZE)
352
 
                {
353
 
                        mdecoder->decoded_size_max = mdecoder->decoded_size_max * 2 + 16;
354
 
                        mdecoder->decoded_data = xrealloc(mdecoder->decoded_data, mdecoder->decoded_size_max);
355
 
                        dst = (uint8*) (((uintptr_t)mdecoder->decoded_data + 15) & ~ 0x0F);
356
 
                        if (dst - mdecoder->decoded_data != dst_offset)
357
 
                        {
358
 
                                /* re-align the memory if the alignment has changed after realloc */
359
 
                                memmove(dst, mdecoder->decoded_data + dst_offset, mdecoder->decoded_size);
360
 
                                dst_offset = dst - mdecoder->decoded_data;
361
 
                        }
362
 
                        dst += mdecoder->decoded_size;
363
 
                }
364
 
                frame_size = mdecoder->decoded_size_max - mdecoder->decoded_size;
365
 
#if LIBAVCODEC_VERSION_MAJOR < 52 || (LIBAVCODEC_VERSION_MAJOR == 52 && LIBAVCODEC_VERSION_MINOR <= 20)
366
 
                len = avcodec_decode_audio2(mdecoder->codec_context,
367
 
                        (int16_t*) dst, &frame_size,
368
 
                        src, src_size);
369
 
#else
370
 
                {
371
 
                        AVPacket pkt;
372
 
                        av_init_packet(&pkt);
373
 
                        pkt.data = (uint8*) src;
374
 
                        pkt.size = src_size;
375
 
                        len = avcodec_decode_audio3(mdecoder->codec_context,
376
 
                                (int16_t*) dst, &frame_size, &pkt);
377
 
                }
378
 
#endif
379
 
                if (len <= 0 || frame_size <= 0)
380
 
                {
381
 
                        DEBUG_WARN("error decoding");
382
 
                        break;
383
 
                }
384
 
                src += len;
385
 
                src_size -= len;
386
 
                mdecoder->decoded_size += frame_size;
387
 
                dst += frame_size;
388
 
        }
389
 
 
390
 
        if (mdecoder->decoded_size == 0)
391
 
        {
392
 
                xfree(mdecoder->decoded_data);
393
 
                mdecoder->decoded_data = NULL;
394
 
        }
395
 
        else if (dst_offset)
396
 
        {
397
 
                /* move the aligned decoded data to original place */
398
 
                memmove(mdecoder->decoded_data, mdecoder->decoded_data + dst_offset, mdecoder->decoded_size);
399
 
        }
400
 
 
401
 
        DEBUG_DVC("data_size %d decoded_size %d",
402
 
                data_size, mdecoder->decoded_size);
403
 
 
404
 
        return true;
405
 
}
406
 
 
407
 
static boolean tsmf_ffmpeg_decode(ITSMFDecoder* decoder, const uint8* data, uint32 data_size, uint32 extensions)
408
 
{
409
 
        TSMFFFmpegDecoder* mdecoder = (TSMFFFmpegDecoder*) decoder;
410
 
 
411
 
        if (mdecoder->decoded_data)
412
 
        {
413
 
                xfree(mdecoder->decoded_data);
414
 
                mdecoder->decoded_data = NULL;
415
 
        }
416
 
        mdecoder->decoded_size = 0;
417
 
 
418
 
        switch (mdecoder->media_type)
419
 
        {
420
 
                case AVMEDIA_TYPE_VIDEO:
421
 
                        return tsmf_ffmpeg_decode_video(decoder, data, data_size, extensions);
422
 
                case AVMEDIA_TYPE_AUDIO:
423
 
                        return tsmf_ffmpeg_decode_audio(decoder, data, data_size, extensions);
424
 
                default:
425
 
                        DEBUG_WARN("unknown media type.");
426
 
                        return false;
427
 
        }
428
 
}
429
 
 
430
 
static uint8* tsmf_ffmpeg_get_decoded_data(ITSMFDecoder* decoder, uint32* size)
431
 
{
432
 
        TSMFFFmpegDecoder* mdecoder = (TSMFFFmpegDecoder*) decoder;
433
 
        uint8* buf;
434
 
 
435
 
        *size = mdecoder->decoded_size;
436
 
        buf = mdecoder->decoded_data;
437
 
        mdecoder->decoded_data = NULL;
438
 
        mdecoder->decoded_size = 0;
439
 
        return buf;
440
 
}
441
 
 
442
 
static uint32 tsmf_ffmpeg_get_decoded_format(ITSMFDecoder* decoder)
443
 
{
444
 
        TSMFFFmpegDecoder* mdecoder = (TSMFFFmpegDecoder*) decoder;
445
 
 
446
 
        switch (mdecoder->codec_context->pix_fmt)
447
 
        {
448
 
                case PIX_FMT_YUV420P:
449
 
                        return RDP_PIXFMT_I420;
450
 
 
451
 
                default:
452
 
                        DEBUG_WARN("unsupported pixel format %u",
453
 
                                mdecoder->codec_context->pix_fmt);
454
 
                        return (uint32) -1;
455
 
        }
456
 
}
457
 
 
458
 
static boolean tsmf_ffmpeg_get_decoded_dimension(ITSMFDecoder* decoder, uint32* width, uint32* height)
459
 
{
460
 
        TSMFFFmpegDecoder* mdecoder = (TSMFFFmpegDecoder*) decoder;
461
 
 
462
 
        if (mdecoder->codec_context->width > 0 && mdecoder->codec_context->height > 0)
463
 
        {
464
 
                *width = mdecoder->codec_context->width;
465
 
                *height = mdecoder->codec_context->height;
466
 
                return true;
467
 
        }
468
 
        else
469
 
        {
470
 
                return false;
471
 
        }
472
 
}
473
 
 
474
 
static void tsmf_ffmpeg_free(ITSMFDecoder* decoder)
475
 
{
476
 
        TSMFFFmpegDecoder* mdecoder = (TSMFFFmpegDecoder*) decoder;
477
 
 
478
 
        if (mdecoder->frame)
479
 
                av_free(mdecoder->frame);
480
 
        if (mdecoder->decoded_data)
481
 
                xfree(mdecoder->decoded_data);
482
 
        if (mdecoder->codec_context)
483
 
        {
484
 
                if (mdecoder->prepared)
485
 
                        avcodec_close(mdecoder->codec_context);
486
 
                if (mdecoder->codec_context->extradata)
487
 
                        xfree(mdecoder->codec_context->extradata);
488
 
                av_free(mdecoder->codec_context);
489
 
        }
490
 
        xfree(decoder);
491
 
}
492
 
 
493
 
static boolean initialized = false;
494
 
 
495
 
ITSMFDecoder*
496
 
TSMFDecoderEntry(void)
497
 
{
498
 
        TSMFFFmpegDecoder * decoder;
499
 
 
500
 
        if (!initialized)
501
 
        {
502
 
                avcodec_init();
503
 
                avcodec_register_all();
504
 
                initialized = true;
505
 
        }
506
 
 
507
 
        decoder = xnew(TSMFFFmpegDecoder);
508
 
 
509
 
        decoder->iface.SetFormat = tsmf_ffmpeg_set_format;
510
 
        decoder->iface.Decode = tsmf_ffmpeg_decode;
511
 
        decoder->iface.GetDecodedData = tsmf_ffmpeg_get_decoded_data;
512
 
        decoder->iface.GetDecodedFormat = tsmf_ffmpeg_get_decoded_format;
513
 
        decoder->iface.GetDecodedDimension = tsmf_ffmpeg_get_decoded_dimension;
514
 
        decoder->iface.Free = tsmf_ffmpeg_free;
515
 
 
516
 
        return (ITSMFDecoder*) decoder;
517
 
}
518