~ubuntu-branches/ubuntu/wily/freerdp/wily-proposed

« back to all changes in this revision

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

  • Committer: Package Import Robot
  • Author(s): Martin Pitt, Jeremy Bicha, Jean-Louis Dupond, Martin Pitt
  • Date: 2012-01-31 10:02:14 UTC
  • mfrom: (1.1.6)
  • Revision ID: package-import@ubuntu.com-20120131100214-jaok3uwvni7sqxth
Tags: 1.0.0-0git1
Upload current Debian packaging git to get this rolling for precise.

[ Jeremy Bicha ]
* New upstream release. Closes: #647498.
* Updated symbols and bumped soname
* debian/control:
  - Added new build dependencies
  - Bump Standards-Version to 3.9.2
* debian/source/format: Set to 3.0 (quilt)
* debian/rules: Turn on strict symbols checking
* debian/watch: Watch github

[ Jean-Louis Dupond ]
* debian/control: Updated homepage
* debian/copyright: Reflect upstream switch to the Apache license

[ Martin Pitt ]
* debian/libfreerdp0.symbols: Fix version number, should
  be 1.0~beta5, not 1.0-beta5.
* debian/control: Add libavcodec-dev build dependency, upstream build system
  checks for that. Thanks Jean-Louis Dupond!

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