~ubuntu-branches/debian/experimental/gpac/experimental

« back to all changes in this revision

Viewing changes to .pc/libav10.patch/modules/ffmpeg_in/ffmpeg_demux.c

  • Committer: Package Import Robot
  • Author(s): Reinhard Tartler
  • Date: 2014-02-22 18:15:00 UTC
  • mfrom: (1.2.2) (3.1.6 sid)
  • Revision ID: package-import@ubuntu.com-20140222181500-b4phupo05gjpmopa
Tags: 0.5.0+svn5104~dfsg1-1
* New  upstream version 0.5.0+svn5104~dfsg1:
  - src/utils/sha1.c is relicensed under LGPLv2.1, Closes: #730759
* Don't install modules in multi-arch directories, Closes: #730497
* Add libusb-1.0.0-dev headers because libfreenect requires this
* Fix install rule
* Follow upstream soname bump
  - Drop the symbols file for now until it has been revised thourougly
* Let binaries produce the correct svn revision
* Refresh patches
* Patch and build against libav10, Closes: #739321
* Bump standards version, no changes necessary

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
 *                      GPAC - Multimedia Framework C SDK
 
3
 *
 
4
 *                      Authors: Jean Le Feuvre 
 
5
 *                      Copyright (c) Telecom ParisTech 2000-2012
 
6
 *                                      All rights reserved
 
7
 *
 
8
 *  This file is part of GPAC / FFMPEG module
 
9
 *
 
10
 *  GPAC is free software; you can redistribute it and/or modify
 
11
 *  it under the terms of the GNU Lesser General Public License as published by
 
12
 *  the Free Software Foundation; either version 2, or (at your option)
 
13
 *  any later version.
 
14
 *
 
15
 *  GPAC is distributed in the hope that it will be useful,
 
16
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 
17
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 
18
 *  GNU Lesser General Public License for more details.
 
19
 *
 
20
 *  You should have received a copy of the GNU Lesser General Public
 
21
 *  License along with this library; see the file COPYING.  If not, write to
 
22
 *  the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
 
23
 *
 
24
 */
 
25
 
 
26
#include "ffmpeg_in.h"
 
27
 
 
28
#ifndef DISABLE_FFMPEG_DEMUX
 
29
 
 
30
/*default buffer is 200 ms per channel*/
 
31
#define FFD_DATA_BUFFER         800
 
32
 
 
33
//#define FFMPEG_DEMUX_ENABLE_MPEG2TS
 
34
 
 
35
//#if defined(__DARWIN__) || defined(__APPLE__)
 
36
#if !defined(WIN32) && !defined(_WIN32_WCE) && !defined(__SYMBIAN32__)
 
37
#include <errno.h>
 
38
#endif
 
39
 
 
40
/**
 
41
 * New versions of ffmpeg do not declare AVERROR_NOMEM, AVERROR_IO, AVERROR_NOFMT
 
42
 */
 
43
 
 
44
#ifndef AVERROR_NOMEM
 
45
#define AVERROR_NOMEM AVERROR(ENOMEM)
 
46
#endif /* AVERROR_NOMEM */
 
47
 
 
48
#ifndef AVERROR_IO
 
49
#define AVERROR_IO AVERROR(EIO)
 
50
#endif /* AVERROR_IO */
 
51
 
 
52
#ifndef AVERROR_NOFMT
 
53
#define AVERROR_NOFMT AVERROR(EINVAL)
 
54
#endif /* AVERROR_NOFMT */
 
55
 
 
56
 
 
57
#if (LIBAVFORMAT_VERSION_MAJOR >= 54) && (LIBAVFORMAT_VERSION_MINOR >= 20)
 
58
 
 
59
#define av_find_stream_info(__c)        avformat_find_stream_info(__c, NULL)
 
60
#ifndef FF_API_FORMAT_PARAMETERS
 
61
#define FF_API_FORMAT_PARAMETERS        1
 
62
#endif
 
63
 
 
64
#endif
 
65
 
 
66
 
 
67
 
 
68
static u32 FFDemux_Run(void *par)
 
69
{
 
70
        AVPacket pkt;
 
71
        s64 seek_to;
 
72
        u64 seek_audio, seek_video;
 
73
        Bool video_init, do_seek, map_audio_time, map_video_time;
 
74
        GF_NetworkCommand com;
 
75
        GF_NetworkCommand map;
 
76
        GF_SLHeader slh;
 
77
        FFDemux *ffd = (FFDemux *) par;
 
78
 
 
79
        memset(&map, 0, sizeof(GF_NetworkCommand));
 
80
        map.command_type = GF_NET_CHAN_MAP_TIME;
 
81
 
 
82
        memset(&com, 0, sizeof(GF_NetworkCommand));
 
83
        com.command_type = GF_NET_CHAN_BUFFER_QUERY;
 
84
 
 
85
        memset(&slh, 0, sizeof(GF_SLHeader));
 
86
 
 
87
        slh.compositionTimeStampFlag = slh.decodingTimeStampFlag = 1;
 
88
        seek_to = (s64) (AV_TIME_BASE*ffd->seek_time);
 
89
        map_video_time = !ffd->seekable;
 
90
 
 
91
        video_init = (seek_to && ffd->video_ch) ? GF_FALSE : GF_TRUE;
 
92
        seek_audio = seek_video = 0;
 
93
        if (ffd->seekable && (ffd->audio_st>=0)) seek_audio = (u64) (s64) (ffd->seek_time*ffd->audio_tscale.den);
 
94
        if (ffd->seekable && (ffd->video_st>=0)) seek_video = (u64) (s64) (ffd->seek_time*ffd->video_tscale.den);
 
95
 
 
96
        /*it appears that ffmpeg has trouble resyncing on some mpeg files - we trick it by restarting to 0 to get the
 
97
        first video frame, and only then seek*/
 
98
        if (ffd->seekable) av_seek_frame(ffd->ctx, -1, video_init ? seek_to : 0, AVSEEK_FLAG_BACKWARD);
 
99
        do_seek = !video_init;
 
100
        map_audio_time = video_init ? ffd->unreliable_audio_timing : 0;
 
101
 
 
102
        gf_sleep(1000);
 
103
        while (ffd->is_running) {
 
104
 
 
105
                pkt.stream_index = -1;
 
106
                /*EOF*/
 
107
                if (av_read_frame(ffd->ctx, &pkt) <0) break;
 
108
                if (pkt.pts == AV_NOPTS_VALUE) pkt.pts = pkt.dts;
 
109
                if (!pkt.dts) pkt.dts = pkt.pts;
 
110
 
 
111
                slh.compositionTimeStamp = pkt.pts;
 
112
                slh.decodingTimeStamp = pkt.dts;
 
113
 
 
114
                gf_mx_p(ffd->mx);
 
115
                /*blindly send audio as soon as video is init*/
 
116
                if (ffd->audio_ch && (pkt.stream_index == ffd->audio_st) && !do_seek) {
 
117
                        slh.compositionTimeStamp *= ffd->audio_tscale.num;
 
118
                        slh.decodingTimeStamp *= ffd->audio_tscale.num;
 
119
 
 
120
                        if (map_audio_time) {
 
121
                                map.base.on_channel = ffd->audio_ch;
 
122
                                map.map_time.media_time = ffd->seek_time;
 
123
                                /*mapwith TS=0 since we don't use SL*/
 
124
                                map.map_time.timestamp = 0;
 
125
                                map.map_time.reset_buffers = 1;
 
126
                                map_audio_time = 0;
 
127
                                gf_term_on_command(ffd->service, &map, GF_OK);
 
128
                        }
 
129
                        else if (slh.compositionTimeStamp < seek_audio) {
 
130
                                slh.decodingTimeStamp = slh.compositionTimeStamp = seek_audio;
 
131
                        }
 
132
                        gf_term_on_sl_packet(ffd->service, ffd->audio_ch, pkt.data, pkt.size, &slh, GF_OK);
 
133
                }
 
134
                else if (ffd->video_ch && (pkt.stream_index == ffd->video_st)) {
 
135
                        slh.compositionTimeStamp *= ffd->video_tscale.num;
 
136
                        slh.decodingTimeStamp *= ffd->video_tscale.num;
 
137
 
 
138
                        /*if we get pts = 0 after a seek the demuxer is reseting PTSs, so force map time*/
 
139
                        if ((!do_seek && seek_to && !slh.compositionTimeStamp) || (map_video_time) ) {
 
140
                                seek_to = 0;
 
141
                                map_video_time = 0;
 
142
 
 
143
                                map.base.on_channel = ffd->video_ch;
 
144
                                map.map_time.timestamp = (u64) pkt.pts;
 
145
//                              map.map_time.media_time = ffd->seek_time;
 
146
                                map.map_time.media_time = 0;
 
147
                                map.map_time.reset_buffers = 0;
 
148
                                gf_term_on_command(ffd->service, &map, GF_OK);
 
149
                        }
 
150
                        else if (slh.compositionTimeStamp < seek_video) {
 
151
                                slh.decodingTimeStamp = slh.compositionTimeStamp = seek_video;
 
152
                        }
 
153
                        gf_term_on_sl_packet(ffd->service, ffd->video_ch, pkt.data, pkt.size, &slh, GF_OK);
 
154
                        video_init = 1;
 
155
                }
 
156
                gf_mx_v(ffd->mx);
 
157
                av_free_packet(&pkt);
 
158
 
 
159
                /*here's the trick - only seek after sending the first packets of each stream - this allows ffmpeg video decoders
 
160
                to resync properly*/
 
161
                if (do_seek && video_init && ffd->seekable) {
 
162
                        av_seek_frame(ffd->ctx, -1, seek_to, AVSEEK_FLAG_BACKWARD);
 
163
                        do_seek = 0;
 
164
                        map_audio_time = ffd->unreliable_audio_timing;
 
165
                }
 
166
                /*sleep untill the buffer occupancy is too low - note that this work because all streams in this
 
167
                demuxer are synchronized*/
 
168
                while (1) {
 
169
                        if (ffd->audio_ch) {
 
170
                                com.base.on_channel = ffd->audio_ch;
 
171
                                gf_term_on_command(ffd->service, &com, GF_OK);
 
172
                                if (com.buffer.occupancy < ffd->data_buffer_ms) break;
 
173
                        }
 
174
                        if (ffd->video_ch) {
 
175
                                com.base.on_channel = ffd->video_ch;
 
176
                                gf_term_on_command(ffd->service, &com, GF_OK);
 
177
                                if (com.buffer.occupancy < ffd->data_buffer_ms) break;
 
178
                        }
 
179
                        gf_sleep(10);
 
180
 
 
181
                        /*escape if disconnect*/
 
182
                        if (!ffd->audio_run && !ffd->video_run) break;
 
183
                }
 
184
                if (!ffd->audio_run && !ffd->video_run) break;
 
185
        }
 
186
        /*signal EOS*/
 
187
        if (ffd->audio_ch) gf_term_on_sl_packet(ffd->service, ffd->audio_ch, NULL, 0, NULL, GF_EOS);
 
188
        if (ffd->video_ch) gf_term_on_sl_packet(ffd->service, ffd->video_ch, NULL, 0, NULL, GF_EOS);
 
189
        ffd->is_running = 2;
 
190
 
 
191
        return 0;
 
192
}
 
193
 
 
194
static const char * FFD_MIME_TYPES[] = {
 
195
  "video/x-mpeg", "mpg mpeg mp2 mpa mpe mpv2", "MPEG 1/2 Movies",
 
196
  "video/x-mpeg-systems", "mpg mpeg mp2 mpa mpe mpv2", "MPEG 1/2 Movies",
 
197
  "audio/basic", "snd au", "Basic Audio",
 
198
  "audio/x-wav", "wav", "WAV Audio",
 
199
  "audio/vnd.wave", "wav", "WAV Audio",
 
200
  "video/x-ms-asf", "asf wma wmv asx asr", "WindowsMedia Movies",
 
201
  "video/x-ms-wmv", "asf wma wmv asx asr", "WindowsMedia Movies",
 
202
  "video/x-msvideo", "avi", "AVI Movies",
 
203
  "video/x-ms-video", "avi", "AVI Movies",
 
204
  "video/avi", "avi", "AVI Movies",
 
205
  "video/vnd.avi", "avi", "AVI Movies",
 
206
  "video/H263", "h263 263", "H263 Video",
 
207
  "video/H264", "h264 264", "H264 Video",
 
208
  "video/MPEG4", "cmp", "MPEG-4 Video",
 
209
/* We let ffmpeg handle mov because some QT files with uncompressed or adpcm audio use 1 audio sample
 
210
   per MP4 sample which is a killer for our MP4 lib, whereas ffmpeg handles these as complete audio chunks
 
211
   moreover ffmpeg handles cmov, we don't */
 
212
  "video/quicktime", "mov qt", "QuickTime Movies",
 
213
/* Supported by latest versions of FFMPEG */
 
214
  "video/webm", "webm", "Google WebM Movies",
 
215
  "audio/webm", "webm", "Google WebM Music",
 
216
#ifdef FFMPEG_DEMUX_ENABLE_MPEG2TS
 
217
  "video/mp2t", "ts", "MPEG 2 TS",
 
218
#endif
 
219
  NULL
 
220
};
 
221
 
 
222
static u32 FFD_RegisterMimeTypes(const GF_InputService *plug){
 
223
    u32 i;
 
224
    for (i = 0 ; FFD_MIME_TYPES[i]; i+=3)
 
225
      gf_term_register_mime_type(plug, FFD_MIME_TYPES[i], FFD_MIME_TYPES[i+1], FFD_MIME_TYPES[i+2]);
 
226
    return i/3;
 
227
}
 
228
 
 
229
static int open_file(AVFormatContext ** ic_ptr, const char *    filename, AVInputFormat *       fmt){
 
230
#ifdef USE_PRE_0_7
 
231
        return av_open_input_file(ic_ptr, filename, fmt, 0, NULL);
 
232
#else
 
233
        return avformat_open_input(ic_ptr, filename, fmt, NULL);
 
234
#endif
 
235
}
 
236
 
 
237
 
 
238
static Bool FFD_CanHandleURL(GF_InputService *plug, const char *url)
 
239
{
 
240
        Bool has_audio, has_video;
 
241
        s32 i;
 
242
        AVFormatContext *ctx;
 
243
        AVOutputFormat *fmt_out;
 
244
        Bool ret = 0;
 
245
        char *ext, szName[1000], szExt[20];
 
246
        const char *szExtList;
 
247
        if (!plug || !url)
 
248
                return 0;
 
249
        /*disable RTP/RTSP from ffmpeg*/
 
250
        if (!strnicmp(url, "rtsp://", 7)) return 0;
 
251
        if (!strnicmp(url, "rtspu://", 8)) return 0;
 
252
        if (!strnicmp(url, "rtp://", 6)) return 0;
 
253
        if (!strnicmp(url, "plato://", 8)) return 0;
 
254
        if (!strnicmp(url, "udp://", 6)) return 0;
 
255
        if (!strnicmp(url, "tcp://", 6)) return 0;
 
256
        if (!strnicmp(url, "data:", 5)) return 0;
 
257
 
 
258
        strcpy(szName, url);
 
259
        ext = strrchr(szName, '#');
 
260
        if (ext) ext[0] = 0;
 
261
        ext = strrchr(szName, '?');
 
262
        if (ext) ext[0] = 0;
 
263
 
 
264
        ext = strrchr(szName, '.');
 
265
        if (ext && strlen(ext) > 19) ext = NULL;
 
266
 
 
267
        if (ext && strlen(ext) > 1) {
 
268
                strcpy(szExt, &ext[1]);
 
269
                strlwr(szExt);
 
270
#ifndef FFMPEG_DEMUX_ENABLE_MPEG2TS
 
271
                if (!strcmp(szExt, "ts")) return 0;
 
272
#endif
 
273
 
 
274
                /*note we forbid ffmpeg to handle files we support*/
 
275
                if (!strcmp(szExt, "mp4") || !strcmp(szExt, "mpg4") || !strcmp(szExt, "m4a") || !strcmp(szExt, "m21")
 
276
                        || !strcmp(szExt, "m4v") || !strcmp(szExt, "m4a")
 
277
                        || !strcmp(szExt, "m4s") || !strcmp(szExt, "3gs")
 
278
                        || !strcmp(szExt, "3gp") || !strcmp(szExt, "3gpp") || !strcmp(szExt, "3gp2") || !strcmp(szExt, "3g2")
 
279
                        || !strcmp(szExt, "mp3")
 
280
                        || !strcmp(szExt, "ac3")
 
281
                        || !strcmp(szExt, "amr")
 
282
                        || !strcmp(szExt, "bt") || !strcmp(szExt, "wrl") || !strcmp(szExt, "x3dv")
 
283
                        || !strcmp(szExt, "xmt") || !strcmp(szExt, "xmta") || !strcmp(szExt, "x3d")
 
284
 
 
285
                        || !strcmp(szExt, "jpg") || !strcmp(szExt, "jpeg") || !strcmp(szExt, "png")
 
286
                        ) return 0;
 
287
 
 
288
                /*check any default stuff that should work with ffmpeg*/
 
289
                {
 
290
                  u32 i;
 
291
                  for (i = 0 ; FFD_MIME_TYPES[i]; i+=3){
 
292
                    if (gf_term_check_extension(plug, FFD_MIME_TYPES[i], FFD_MIME_TYPES[i+1], FFD_MIME_TYPES[i+2], ext))
 
293
                      return 1;
 
294
                  }
 
295
                }
 
296
        }
 
297
 
 
298
        ctx = NULL;
 
299
    if (open_file(&ctx, szName, NULL)<0) {
 
300
                AVInputFormat *av_in = NULL;;
 
301
                /*some extensions not supported by ffmpeg*/
 
302
                if (ext && !strcmp(szExt, "cmp")) av_in = av_find_input_format("m4v");
 
303
 
 
304
                if (open_file(&ctx, szName, av_in)<0) {
 
305
                        return 0;
 
306
                }
 
307
        }
 
308
    if (!ctx || av_find_stream_info(ctx) <0) goto exit;
 
309
 
 
310
        /*figure out if we can use codecs or not*/
 
311
        has_video = has_audio = 0;
 
312
        for(i = 0; i < (s32)ctx->nb_streams; i++) {
 
313
                AVCodecContext *enc = ctx->streams[i]->codec;
 
314
                switch(enc->codec_type) {
 
315
                case AVMEDIA_TYPE_AUDIO:
 
316
                        if (!has_audio) has_audio = 1;
 
317
                        break;
 
318
                case AVMEDIA_TYPE_VIDEO:
 
319
                        if (!has_video) has_video= 1;
 
320
                        break;
 
321
                default:
 
322
                        break;
 
323
                }
 
324
        }
 
325
        if (!has_audio && !has_video) goto exit;
 
326
        ret = 1;
 
327
#if LIBAVFORMAT_VERSION_MAJOR < 53 && LIBAVFORMAT_VERSION_MINOR < 45
 
328
        fmt_out = guess_stream_format(NULL, url, NULL);
 
329
#else
 
330
        fmt_out = av_guess_format(NULL, url, NULL);
 
331
#endif
 
332
        if (fmt_out) gf_term_register_mime_type(plug, fmt_out->mime_type, fmt_out->extensions, fmt_out->name);
 
333
        else {
 
334
                ext = strrchr(szName, '.');
 
335
                if (ext) {
 
336
                        strcpy(szExt, &ext[1]);
 
337
                        strlwr(szExt);
 
338
 
 
339
                        szExtList = gf_modules_get_option((GF_BaseInterface *)plug, "MimeTypes", "application/x-ffmpeg");
 
340
                        if (!szExtList) {
 
341
                                gf_term_register_mime_type(plug, "application/x-ffmpeg", szExt, "Other Movies (FFMPEG)");
 
342
                        } else if (!strstr(szExtList, szExt)) {
 
343
                                u32 len;
 
344
                                char *buf;
 
345
                                len = (u32) (strlen(szExtList) + strlen(szExt) + 10);
 
346
                                buf = gf_malloc(sizeof(char)*len);
 
347
                                sprintf(buf, "\"%s ", szExt);
 
348
                                strcat(buf, &szExtList[1]);
 
349
                                gf_modules_set_option((GF_BaseInterface *)plug, "MimeTypes", "application/x-ffmpeg", buf);
 
350
                                gf_free(buf);
 
351
                        }
 
352
                }
 
353
        }
 
354
 
 
355
exit:
 
356
    if (ctx) av_close_input_file(ctx);
 
357
        return ret;
 
358
}
 
359
 
 
360
static GF_ESD *FFD_GetESDescriptor(FFDemux *ffd, Bool for_audio)
 
361
{
 
362
        GF_BitStream *bs;
 
363
        Bool dont_use_sl;
 
364
        GF_ESD *esd = (GF_ESD *) gf_odf_desc_esd_new(0);
 
365
        esd->ESID = 1 + (for_audio ? ffd->audio_st : ffd->video_st);
 
366
        esd->decoderConfig->streamType = for_audio ? GF_STREAM_AUDIO : GF_STREAM_VISUAL;
 
367
        esd->decoderConfig->avgBitrate = esd->decoderConfig->maxBitrate = 0;
 
368
 
 
369
        /*remap std object types - depending on input formats, FFMPEG may not have separate DSI from initial frame.
 
370
        In this case we have no choice but using FFMPEG decoders*/
 
371
        if (for_audio) {
 
372
        AVCodecContext *dec = ffd->ctx->streams[ffd->audio_st]->codec;
 
373
                esd->slConfig->timestampResolution = ffd->audio_tscale.den;
 
374
                switch (dec->codec_id) {
 
375
                case CODEC_ID_MP2:
 
376
                        esd->decoderConfig->objectTypeIndication = GPAC_OTI_AUDIO_MPEG1;
 
377
                        break;
 
378
                case CODEC_ID_MP3:
 
379
                        esd->decoderConfig->objectTypeIndication = GPAC_OTI_AUDIO_MPEG2_PART3;
 
380
                        break;
 
381
                case CODEC_ID_AAC:
 
382
                        if (!dec->extradata_size) goto opaque_audio;
 
383
                        esd->decoderConfig->objectTypeIndication = GPAC_OTI_AUDIO_AAC_MPEG4;
 
384
                        esd->decoderConfig->decoderSpecificInfo->dataLength = dec->extradata_size;
 
385
                        esd->decoderConfig->decoderSpecificInfo->data = gf_malloc(sizeof(char)*dec->extradata_size);
 
386
                        memcpy(esd->decoderConfig->decoderSpecificInfo->data,
 
387
                                        dec->extradata,
 
388
                                        sizeof(char)*dec->extradata_size);
 
389
                        break;
 
390
                default:
 
391
opaque_audio:
 
392
                        esd->decoderConfig->objectTypeIndication = GPAC_OTI_MEDIA_FFMPEG;
 
393
                        bs = gf_bs_new(NULL, 0, GF_BITSTREAM_WRITE);
 
394
                        gf_bs_write_u32(bs, dec->codec_id);
 
395
                        gf_bs_write_u32(bs, dec->sample_rate);
 
396
                        gf_bs_write_u16(bs, dec->channels);
 
397
                        gf_bs_write_u16(bs, dec->frame_size);
 
398
                        gf_bs_write_u8(bs, 16);
 
399
                        gf_bs_write_u8(bs, 0);
 
400
                        /*ffmpeg specific*/
 
401
                        gf_bs_write_u16(bs, dec->block_align);
 
402
                        gf_bs_write_u32(bs, dec->bit_rate);
 
403
                        gf_bs_write_u32(bs, dec->codec_tag);
 
404
                        if (dec->extradata_size) {
 
405
                                gf_bs_write_data(bs, dec->extradata, dec->extradata_size);
 
406
                        }
 
407
                        gf_bs_get_content(bs, (char **) &esd->decoderConfig->decoderSpecificInfo->data, &esd->decoderConfig->decoderSpecificInfo->dataLength);
 
408
                        gf_bs_del(bs);
 
409
                        break;
 
410
                }
 
411
                dont_use_sl = ffd->unreliable_audio_timing;
 
412
        } else {
 
413
                AVCodecContext *dec = ffd->ctx->streams[ffd->video_st]->codec;
 
414
                esd->slConfig->timestampResolution = ffd->video_tscale.den;
 
415
                switch (dec->codec_id) {
 
416
                case CODEC_ID_MPEG4:
 
417
                /*there is a bug in fragmentation of raw H264 in ffmpeg, the NALU startcode (0x00000001) is split across
 
418
                two frames - we therefore force internal ffmpeg codec ID to avoid NALU size recompute
 
419
                at the decoder level*/
 
420
//              case CODEC_ID_H264:
 
421
                        /*if dsi not detected force use ffmpeg*/
 
422
                        if (!dec->extradata_size) goto opaque_video;
 
423
                        /*otherwise use any MPEG-4 Visual*/
 
424
                        esd->decoderConfig->objectTypeIndication = (dec->codec_id==CODEC_ID_H264) ? GPAC_OTI_VIDEO_AVC : GPAC_OTI_VIDEO_MPEG4_PART2;
 
425
                        esd->decoderConfig->decoderSpecificInfo->dataLength = dec->extradata_size;
 
426
                        esd->decoderConfig->decoderSpecificInfo->data = gf_malloc(sizeof(char)*dec->extradata_size);
 
427
                        memcpy(esd->decoderConfig->decoderSpecificInfo->data,
 
428
                                        dec->extradata,
 
429
                                        sizeof(char)*dec->extradata_size);
 
430
                        break;
 
431
                case CODEC_ID_MPEG1VIDEO:
 
432
                        esd->decoderConfig->objectTypeIndication = GPAC_OTI_VIDEO_MPEG1;
 
433
                        break;
 
434
                case CODEC_ID_MPEG2VIDEO:
 
435
                        esd->decoderConfig->objectTypeIndication = GPAC_OTI_VIDEO_MPEG2_422;
 
436
                        break;
 
437
                default:
 
438
opaque_video:
 
439
                        esd->decoderConfig->objectTypeIndication = GPAC_OTI_MEDIA_FFMPEG;
 
440
                        bs = gf_bs_new(NULL, 0, GF_BITSTREAM_WRITE);
 
441
                        gf_bs_write_u32(bs, dec->codec_id);
 
442
                        gf_bs_write_u16(bs, dec->width);
 
443
                        gf_bs_write_u16(bs, dec->height);
 
444
                        /*ffmpeg specific*/
 
445
                        gf_bs_write_u32(bs, dec->bit_rate);
 
446
                        gf_bs_write_u32(bs, dec->codec_tag);
 
447
                        gf_bs_write_u32(bs, dec->pix_fmt);
 
448
 
 
449
                        if (dec->extradata_size) {
 
450
                                gf_bs_write_data(bs, dec->extradata, dec->extradata_size);
 
451
                        }
 
452
                        gf_bs_get_content(bs, (char **) &esd->decoderConfig->decoderSpecificInfo->data, &esd->decoderConfig->decoderSpecificInfo->dataLength);
 
453
                        gf_bs_del(bs);
 
454
                        break;
 
455
                }
 
456
                dont_use_sl = 0;
 
457
        }
 
458
 
 
459
        if (dont_use_sl) {
 
460
                esd->slConfig->predefined = SLPredef_SkipSL;
 
461
        } else {
 
462
                /*only send full AUs*/
 
463
                esd->slConfig->useAccessUnitStartFlag = esd->slConfig->useAccessUnitEndFlag = 0;
 
464
                esd->slConfig->hasRandomAccessUnitsOnlyFlag = 1;
 
465
                esd->slConfig->useTimestampsFlag = 1;
 
466
        }
 
467
 
 
468
        return esd;
 
469
}
 
470
 
 
471
 
 
472
static void FFD_SetupObjects(FFDemux *ffd)
 
473
{
 
474
        GF_ESD *esd;
 
475
        GF_ObjectDescriptor *od;
 
476
        u32 audio_esid = 0;
 
477
 
 
478
        if ((ffd->audio_st>=0) && (ffd->service_type != 1)) {
 
479
                od = (GF_ObjectDescriptor *) gf_odf_desc_new(GF_ODF_OD_TAG);
 
480
                esd = FFD_GetESDescriptor(ffd, 1);
 
481
                od->objectDescriptorID = esd->ESID;
 
482
                audio_esid = esd->ESID;
 
483
                gf_list_add(od->ESDescriptors, esd);
 
484
                gf_term_add_media(ffd->service, (GF_Descriptor*)od, (ffd->video_st>=0) ? 1 : 0);
 
485
        }
 
486
        if ((ffd->video_st>=0) && (ffd->service_type != 2)) {
 
487
                od = (GF_ObjectDescriptor *) gf_odf_desc_new(GF_ODF_OD_TAG);
 
488
                esd = FFD_GetESDescriptor(ffd, 0);
 
489
                od->objectDescriptorID = esd->ESID;
 
490
                esd->OCRESID = audio_esid;
 
491
                gf_list_add(od->ESDescriptors, esd);
 
492
                gf_term_add_media(ffd->service, (GF_Descriptor*)od, 0);
 
493
        }
 
494
}
 
495
 
 
496
#ifdef USE_PRE_0_7
 
497
static int ff_url_read(void *h, unsigned char *buf, int size)
 
498
{
 
499
        u32 retry = 10;
 
500
        u32 read;
 
501
        int full_size;
 
502
        FFDemux *ffd = (FFDemux *)h;
 
503
 
 
504
        full_size = 0;
 
505
        if (ffd->buffer_used) {
 
506
                if (ffd->buffer_used >= (u32) size) {
 
507
                        ffd->buffer_used-=size;
 
508
                        memcpy(ffd->buffer, ffd->buffer+size, sizeof(char)*ffd->buffer_used);
 
509
#ifdef FFMPEG_DUMP_REMOTE
 
510
                        if (ffd->outdbg) gf_fwrite(buf, size, 1, ffd->outdbg);
 
511
#endif
 
512
                        return size;
 
513
                }
 
514
                full_size += ffd->buffer_used;
 
515
                buf += ffd->buffer_used;
 
516
                size -= ffd->buffer_used;
 
517
                ffd->buffer_used = 0;
 
518
        }
 
519
 
 
520
        while (size) {
 
521
                GF_Err e = gf_dm_sess_fetch_data(ffd->dnload, buf, size, &read);
 
522
                if (e==GF_EOS) break;
 
523
                /*we're sync!!*/
 
524
                if (e==GF_IP_NETWORK_EMPTY) {
 
525
                        if (!retry) {
 
526
                                GF_LOG(GF_LOG_ERROR, GF_LOG_CONTAINER, ("[FFMPEG Demuxer] timeout fetching bytes from network\n") );
 
527
                                return -1;
 
528
                        }
 
529
                        retry --;
 
530
                        gf_sleep(100);
 
531
                        continue;
 
532
                }
 
533
                if (e) {
 
534
                        GF_LOG(GF_LOG_ERROR, GF_LOG_CONTAINER, ("[FFMPEG Demuxer] error fetching bytes from network: %s\n", gf_error_to_string(e) ) );
 
535
                        return -1;
 
536
                }
 
537
                full_size += read;
 
538
                if (read==size) break;
 
539
                size -= read;
 
540
                buf += read;
 
541
        }
 
542
#ifdef FFMPEG_DUMP_REMOTE
 
543
        if (ffd->outdbg) gf_fwrite(ffd->buffer, full_size, 1, ffd->outdbg);
 
544
#endif
 
545
        return full_size ? (int) full_size : -1;
 
546
}
 
547
#endif /*USE_PRE_0_7*/
 
548
 
 
549
 
 
550
static GF_Err FFD_ConnectService(GF_InputService *plug, GF_ClientService *serv, const char *url)
 
551
{
 
552
        GF_Err e;
 
553
        s64 last_aud_pts;
 
554
        u32 i;
 
555
        s32 res;
 
556
        Bool is_local;
 
557
        const char *sOpt;
 
558
        char *ext, szName[1024];
 
559
        FFDemux *ffd = plug->priv;
 
560
        AVInputFormat *av_in = NULL;
 
561
        char szExt[20];
 
562
 
 
563
        if (ffd->ctx) return GF_SERVICE_ERROR;
 
564
 
 
565
        assert( url && strlen(url) < 1024);
 
566
        strcpy(szName, url);
 
567
        ext = strrchr(szName, '#');
 
568
        ffd->service_type = 0;
 
569
        e = GF_NOT_SUPPORTED;
 
570
        ffd->service = serv;
 
571
 
 
572
        if (ext) {
 
573
                if (!stricmp(&ext[1], "video")) ffd->service_type = 1;
 
574
                else if (!stricmp(&ext[1], "audio")) ffd->service_type = 2;
 
575
                ext[0] = 0;
 
576
        }
 
577
 
 
578
        /*some extensions not supported by ffmpeg, overload input format*/
 
579
        ext = strrchr(szName, '.');
 
580
        strcpy(szExt, ext ? ext+1 : "");
 
581
        strlwr(szExt);
 
582
        if (!strcmp(szExt, "cmp")) av_in = av_find_input_format("m4v");
 
583
 
 
584
        is_local = (strnicmp(url, "file://", 7) && strstr(url, "://")) ? 0 : 1;
 
585
 
 
586
        GF_LOG(GF_LOG_DEBUG, GF_LOG_CONTAINER, ("[FFMPEG] opening file %s - local %d - av_in %08x\n", url, is_local, av_in));
 
587
 
 
588
        if (!is_local) {
 
589
                AVProbeData   pd;
 
590
 
 
591
                /*setup wraper for FFMPEG I/O*/
 
592
                ffd->buffer_size = 8192;
 
593
                sOpt = gf_modules_get_option((GF_BaseInterface *)plug, "FFMPEG", "IOBufferSize");
 
594
                if (sOpt) ffd->buffer_size = atoi(sOpt);
 
595
                ffd->buffer = gf_malloc(sizeof(char)*ffd->buffer_size);
 
596
#ifdef FFMPEG_DUMP_REMOTE
 
597
                ffd->outdbg = gf_f64_open("ffdeb.raw", "wb");
 
598
#endif
 
599
#ifdef USE_PRE_0_7
 
600
                init_put_byte(&ffd->io, ffd->buffer, ffd->buffer_size, 0, ffd, ff_url_read, NULL, NULL);
 
601
                ffd->io.is_streamed = 1;
 
602
#else
 
603
                ffd->io.seekable = 1;
 
604
#endif
 
605
 
 
606
                ffd->dnload = gf_term_download_new(ffd->service, url, GF_NETIO_SESSION_NOT_THREADED  | GF_NETIO_SESSION_NOT_CACHED, NULL, ffd);
 
607
                if (!ffd->dnload) return GF_URL_ERROR;
 
608
                while (1) {
 
609
                        u32 read;
 
610
                        e = gf_dm_sess_fetch_data(ffd->dnload, ffd->buffer + ffd->buffer_used, ffd->buffer_size - ffd->buffer_used, &read);
 
611
                        if (e==GF_EOS) break;
 
612
                        /*we're sync!!*/
 
613
                        if (e==GF_IP_NETWORK_EMPTY) continue;
 
614
                        if (e) goto err_exit;
 
615
                        ffd->buffer_used += read;
 
616
                        if (ffd->buffer_used == ffd->buffer_size) break;
 
617
                }
 
618
                if (e==GF_EOS) {
 
619
                        const char *cache_file = gf_dm_sess_get_cache_name(ffd->dnload);
 
620
                        res = open_file(&ffd->ctx, cache_file, av_in);
 
621
                } else {
 
622
                        pd.filename = szName;
 
623
                        pd.buf_size = ffd->buffer_used;
 
624
                        pd.buf = ffd->buffer;
 
625
                        av_in = av_probe_input_format(&pd, 1);
 
626
                        if (!av_in) {
 
627
                                GF_LOG(GF_LOG_ERROR, GF_LOG_CONTAINER, ("[FFMPEG] error probing file %s - probe start with %c %c %c %c\n", url, ffd->buffer[0], ffd->buffer[1], ffd->buffer[2], ffd->buffer[3]));
 
628
                                return GF_NOT_SUPPORTED;
 
629
                        }
 
630
                        /*setup downloader*/
 
631
                        av_in->flags |= AVFMT_NOFILE;
 
632
#if FF_API_FORMAT_PARAMETERS /*commit ffmpeg 603b8bc2a109978c8499b06d2556f1433306eca7*/
 
633
                        res = avformat_open_input(&ffd->ctx, szName, av_in, NULL);
 
634
#else
 
635
                        res = av_open_input_stream(&ffd->ctx, &ffd->io, szName, av_in, NULL);
 
636
#endif
 
637
                }
 
638
        } else {
 
639
                res = open_file(&ffd->ctx, szName, av_in);
 
640
        }
 
641
 
 
642
        switch (res) {
 
643
#ifndef _WIN32_WCE
 
644
        case 0: e = GF_OK; break;
 
645
        case AVERROR_IO: e = GF_URL_ERROR; goto err_exit;
 
646
        case AVERROR_INVALIDDATA: e = GF_NON_COMPLIANT_BITSTREAM; goto err_exit;
 
647
        case AVERROR_NOMEM: e = GF_OUT_OF_MEM; goto err_exit;
 
648
        case AVERROR_NOFMT: e = GF_NOT_SUPPORTED; goto err_exit;
 
649
#endif
 
650
        default: e = GF_SERVICE_ERROR; goto err_exit;
 
651
        }
 
652
 
 
653
        GF_LOG(GF_LOG_DEBUG, GF_LOG_CONTAINER, ("[FFMPEG] looking for streams in %s - %d streams - type %s\n", ffd->ctx->filename, ffd->ctx->nb_streams, ffd->ctx->iformat->name));
 
654
 
 
655
        res = av_find_stream_info(ffd->ctx);
 
656
        if (res <0) {
 
657
                GF_LOG(GF_LOG_ERROR, GF_LOG_CONTAINER, ("[FFMPEG] cannot locate streams - error %d\n", res));
 
658
                e = GF_NOT_SUPPORTED;
 
659
                goto err_exit;
 
660
        }
 
661
        GF_LOG(GF_LOG_DEBUG, GF_LOG_CONTAINER, ("[FFMPEG] file %s opened - %d streams\n", url, ffd->ctx->nb_streams));
 
662
 
 
663
        /*figure out if we can use codecs or not*/
 
664
        ffd->audio_st = ffd->video_st = -1;
 
665
        for (i = 0; i < ffd->ctx->nb_streams; i++) {
 
666
                AVCodecContext *enc = ffd->ctx->streams[i]->codec;
 
667
                switch(enc->codec_type) {
 
668
                case AVMEDIA_TYPE_AUDIO:
 
669
                        if ((ffd->audio_st<0) && (ffd->service_type!=1)) {
 
670
                                ffd->audio_st = i;
 
671
                                ffd->audio_tscale = ffd->ctx->streams[i]->time_base;
 
672
                        }
 
673
                        break;
 
674
                case AVMEDIA_TYPE_VIDEO:
 
675
                        if ((ffd->video_st<0) && (ffd->service_type!=2)) {
 
676
                                ffd->video_st = i;
 
677
                                ffd->video_tscale = ffd->ctx->streams[i]->time_base;
 
678
                        }
 
679
                        break;
 
680
                default:
 
681
                        break;
 
682
                }
 
683
        }
 
684
        if ((ffd->service_type==1) && (ffd->video_st<0)) goto err_exit;
 
685
        if ((ffd->service_type==2) && (ffd->audio_st<0)) goto err_exit;
 
686
        if ((ffd->video_st<0) && (ffd->audio_st<0)) {
 
687
                GF_LOG(GF_LOG_ERROR, GF_LOG_CONTAINER, ("[FFMPEG] No supported streams in file\n"));
 
688
                goto err_exit;
 
689
        }
 
690
 
 
691
 
 
692
        sOpt = gf_modules_get_option((GF_BaseInterface *)plug, "FFMPEG", "DataBufferMS");
 
693
        ffd->data_buffer_ms = 0;
 
694
        if (sOpt) ffd->data_buffer_ms = atoi(sOpt);
 
695
        if (!ffd->data_buffer_ms) ffd->data_buffer_ms = FFD_DATA_BUFFER;
 
696
 
 
697
        /*build seek*/
 
698
        if (is_local) {
 
699
                /*check we do have increasing pts. If not we can't rely on pts, we must skip SL
 
700
                we assume video pts is always present*/
 
701
                if (ffd->audio_st>=0) {
 
702
                        last_aud_pts = 0;
 
703
                        for (i=0; i<20; i++) {
 
704
                                AVPacket pkt;
 
705
                                pkt.stream_index = -1;
 
706
                                if (av_read_frame(ffd->ctx, &pkt) <0) break;
 
707
                                if (pkt.pts == AV_NOPTS_VALUE) pkt.pts = pkt.dts;
 
708
                                if (pkt.stream_index==ffd->audio_st) last_aud_pts = pkt.pts;
 
709
                        }
 
710
                        if (last_aud_pts*ffd->audio_tscale.den<10*ffd->audio_tscale.num) ffd->unreliable_audio_timing = 1;
 
711
                }
 
712
 
 
713
                ffd->seekable = (av_seek_frame(ffd->ctx, -1, 0, AVSEEK_FLAG_BACKWARD)<0) ? 0 : 1;
 
714
                if (!ffd->seekable) {
 
715
                        av_close_input_file(ffd->ctx);
 
716
                        ffd->ctx = NULL;
 
717
                        open_file(&ffd->ctx, szName, av_in);
 
718
                        av_find_stream_info(ffd->ctx);
 
719
                }
 
720
        }
 
721
 
 
722
        /*let's go*/
 
723
        gf_term_on_connect(serv, NULL, GF_OK);
 
724
        /*if (!ffd->service_type)*/ FFD_SetupObjects(ffd);
 
725
        ffd->service_type = 0;
 
726
        return GF_OK;
 
727
 
 
728
err_exit:
 
729
        GF_LOG(GF_LOG_ERROR, GF_LOG_CONTAINER, ("[FFMPEG] Error opening file %s: %s\n", url, gf_error_to_string(e)));
 
730
    if (ffd->ctx) av_close_input_file(ffd->ctx);
 
731
        ffd->ctx = NULL;
 
732
        gf_term_on_connect(serv, NULL, e);
 
733
        return GF_OK;
 
734
}
 
735
 
 
736
 
 
737
static GF_Descriptor *FFD_GetServiceDesc(GF_InputService *plug, u32 expect_type, const char *sub_url)
 
738
{
 
739
        GF_ObjectDescriptor *od;
 
740
        GF_ESD *esd;
 
741
        FFDemux *ffd = plug->priv;
 
742
 
 
743
        if (!ffd->ctx) return NULL;
 
744
 
 
745
        if (expect_type==GF_MEDIA_OBJECT_UNDEF) {
 
746
                if (ffd->video_st>=0) expect_type=GF_MEDIA_OBJECT_VIDEO;
 
747
                else if (ffd->audio_st>=0) expect_type=GF_MEDIA_OBJECT_AUDIO;
 
748
        }
 
749
 
 
750
 
 
751
        /*since we don't handle multitrack in ffmpeg, we don't need to check sub_url, only use expected type*/
 
752
        if (expect_type==GF_MEDIA_OBJECT_AUDIO) {
 
753
                if (ffd->audio_st<0) return NULL;
 
754
                od = (GF_ObjectDescriptor *) gf_odf_desc_new(GF_ODF_OD_TAG);
 
755
                od->objectDescriptorID = 1;
 
756
                esd = FFD_GetESDescriptor(ffd, 1);
 
757
                /*if session join, setup sync*/
 
758
                if (ffd->video_ch) esd->OCRESID = ffd->video_st+1;
 
759
                gf_list_add(od->ESDescriptors, esd);
 
760
                ffd->service_type = 2;
 
761
                return (GF_Descriptor *) od;
 
762
        }
 
763
        if (expect_type==GF_MEDIA_OBJECT_VIDEO) {
 
764
                if (ffd->video_st<0) return NULL;
 
765
                od = (GF_ObjectDescriptor *) gf_odf_desc_new(GF_ODF_OD_TAG);
 
766
                od->objectDescriptorID = 1;
 
767
                esd = FFD_GetESDescriptor(ffd, 0);
 
768
                /*if session join, setup sync*/
 
769
                if (ffd->audio_ch) esd->OCRESID = ffd->audio_st+1;
 
770
                gf_list_add(od->ESDescriptors, esd);
 
771
                ffd->service_type = 1;
 
772
                return (GF_Descriptor *) od;
 
773
        }
 
774
        return NULL;
 
775
}
 
776
 
 
777
 
 
778
static GF_Err FFD_CloseService(GF_InputService *plug)
 
779
{
 
780
        FFDemux *ffd = plug->priv;
 
781
 
 
782
        ffd->is_running = 0;
 
783
 
 
784
        if (ffd->ctx) av_close_input_file(ffd->ctx);
 
785
        ffd->ctx = NULL;
 
786
        ffd->audio_ch = ffd->video_ch = NULL;
 
787
        ffd->audio_run = ffd->video_run = 0;
 
788
 
 
789
        if (ffd->dnload) {
 
790
                if (ffd->is_running) {
 
791
                        while (!ffd->is_running) gf_sleep(1);
 
792
                        ffd->is_running = 0;
 
793
                }
 
794
                gf_term_download_del(ffd->dnload);
 
795
                ffd->dnload = NULL;
 
796
        }
 
797
        if (ffd->buffer) gf_free(ffd->buffer);
 
798
        ffd->buffer = NULL;
 
799
 
 
800
        gf_term_on_disconnect(ffd->service, NULL, GF_OK);
 
801
#ifdef FFMPEG_DUMP_REMOTE
 
802
        if (ffd->outdbg) fclose(ffd->outdbg);
 
803
#endif
 
804
        return GF_OK;
 
805
}
 
806
 
 
807
static GF_Err FFD_ConnectChannel(GF_InputService *plug, LPNETCHANNEL channel, const char *url, Bool upstream)
 
808
{
 
809
        GF_Err e;
 
810
        u32 ESID;
 
811
        FFDemux *ffd = plug->priv;
 
812
 
 
813
        e = GF_STREAM_NOT_FOUND;
 
814
        if (upstream) {
 
815
                e = GF_ISOM_INVALID_FILE;
 
816
                goto exit;
 
817
        }
 
818
        if (!strstr(url, "ES_ID=")) {
 
819
                e = GF_NOT_SUPPORTED;
 
820
                goto exit;
 
821
        }
 
822
        sscanf(url, "ES_ID=%u", &ESID);
 
823
 
 
824
        if ((s32) ESID == 1 + ffd->audio_st) {
 
825
                if (ffd->audio_ch) {
 
826
                        e = GF_SERVICE_ERROR;
 
827
                        goto exit;
 
828
                }
 
829
                ffd->audio_ch = channel;
 
830
                e = GF_OK;
 
831
        }
 
832
        else if ((s32) ESID == 1 + ffd->video_st) {
 
833
                if (ffd->video_ch) {
 
834
                        e = GF_SERVICE_ERROR;
 
835
                        goto exit;
 
836
                }
 
837
                ffd->video_ch = channel;
 
838
                e = GF_OK;
 
839
        }
 
840
 
 
841
exit:
 
842
        gf_term_on_connect(ffd->service, channel, e);
 
843
        return GF_OK;
 
844
}
 
845
 
 
846
static GF_Err FFD_DisconnectChannel(GF_InputService *plug, LPNETCHANNEL channel)
 
847
{
 
848
        GF_Err e;
 
849
        FFDemux *ffd = plug->priv;
 
850
 
 
851
        e = GF_STREAM_NOT_FOUND;
 
852
        if (ffd->audio_ch == channel) {
 
853
                e = GF_OK;
 
854
                ffd->audio_ch = NULL;
 
855
                ffd->audio_run = 0;
 
856
        }
 
857
        else if (ffd->video_ch == channel) {
 
858
                e = GF_OK;
 
859
                ffd->video_ch = NULL;
 
860
                ffd->video_run = 0;
 
861
        }
 
862
        gf_term_on_disconnect(ffd->service, channel, e);
 
863
        return GF_OK;
 
864
}
 
865
 
 
866
static GF_Err FFD_ServiceCommand(GF_InputService *plug, GF_NetworkCommand *com)
 
867
{
 
868
        FFDemux *ffd = plug->priv;
 
869
 
 
870
 
 
871
        if (com->command_type==GF_NET_SERVICE_HAS_AUDIO) {
 
872
                if (ffd->audio_st>=0) return GF_OK;
 
873
                return GF_NOT_SUPPORTED;
 
874
        }
 
875
 
 
876
        if (!com->base.on_channel) return GF_NOT_SUPPORTED;
 
877
 
 
878
        switch (com->command_type) {
 
879
        /*only BIFS/OD work in pull mode (cf ffmpeg_in.h)*/
 
880
        case GF_NET_CHAN_SET_PULL:
 
881
                return GF_NOT_SUPPORTED;
 
882
        case GF_NET_CHAN_INTERACTIVE:
 
883
                return ffd->seekable ? GF_OK : GF_NOT_SUPPORTED;
 
884
        case GF_NET_CHAN_BUFFER:
 
885
                com->buffer.max = com->buffer.min = 0;
 
886
                return GF_OK;
 
887
        case GF_NET_CHAN_DURATION:
 
888
                if (ffd->ctx->duration == AV_NOPTS_VALUE)
 
889
                        com->duration.duration = -1;
 
890
                else
 
891
                        com->duration.duration = (Double) ffd->ctx->duration / AV_TIME_BASE;
 
892
                return GF_OK;
 
893
        /*fetch start time*/
 
894
        case GF_NET_CHAN_PLAY:
 
895
                if (com->play.speed<0) return GF_NOT_SUPPORTED;
 
896
 
 
897
                gf_mx_p(ffd->mx);
 
898
                ffd->seek_time = (com->play.start_range>=0) ? com->play.start_range : 0;
 
899
 
 
900
                if (ffd->audio_ch==com->base.on_channel) ffd->audio_run = 1;
 
901
                else if (ffd->video_ch==com->base.on_channel) ffd->video_run = 1;
 
902
 
 
903
                /*play on media stream, start thread*/
 
904
                if ((ffd->audio_ch==com->base.on_channel) || (ffd->video_ch==com->base.on_channel)) {
 
905
                        if (ffd->is_running!=1) {
 
906
                                ffd->is_running = 1;
 
907
                                gf_th_run(ffd->thread, FFDemux_Run, ffd);
 
908
                        }
 
909
                }
 
910
                gf_mx_v(ffd->mx);
 
911
                return GF_OK;
 
912
        case GF_NET_CHAN_STOP:
 
913
                if (ffd->audio_ch==com->base.on_channel) ffd->audio_run = 0;
 
914
                else if (ffd->video_ch==com->base.on_channel) ffd->video_run = 0;
 
915
                return GF_OK;
 
916
        /*note we don't handle PAUSE/RESUME/SET_SPEED, this is automatically handled by the demuxing thread
 
917
        through buffer occupancy queries*/
 
918
 
 
919
        default:
 
920
                return GF_OK;
 
921
        }
 
922
 
 
923
        return GF_OK;
 
924
}
 
925
 
 
926
 
 
927
static Bool FFD_CanHandleURLInService(GF_InputService *plug, const char *url)
 
928
{
 
929
        char szURL[2048], *sep;
 
930
        FFDemux *ffd;
 
931
        const char *this_url;
 
932
        if (!plug || !url)
 
933
                return GF_FALSE;
 
934
        ffd = (FFDemux *)plug->priv;
 
935
        this_url = gf_term_get_service_url(ffd->service);
 
936
        if (!this_url)
 
937
                return GF_FALSE;
 
938
 
 
939
        strcpy(szURL, this_url);
 
940
        sep = strrchr(szURL, '#');
 
941
        if (sep) sep[0] = 0;
 
942
 
 
943
        if ((url[0] != '#') && strnicmp(szURL, url, sizeof(char)*strlen(szURL))) return 0;
 
944
        sep = strrchr(url, '#');
 
945
        if (sep && !stricmp(sep, "#video") && (ffd->video_st>=0)) return 1;
 
946
        if (sep && !stricmp(sep, "#audio") && (ffd->audio_st>=0)) return 1;
 
947
        return GF_FALSE;
 
948
}
 
949
 
 
950
void *New_FFMPEG_Demux()
 
951
{
 
952
        FFDemux *priv;
 
953
        GF_InputService *ffd = gf_malloc(sizeof(GF_InputService));
 
954
        memset(ffd, 0, sizeof(GF_InputService));
 
955
 
 
956
        GF_SAFEALLOC(priv, FFDemux);
 
957
 
 
958
    GF_LOG(GF_LOG_INFO, GF_LOG_CONTAINER, ("[FFMPEG Demuxer] Registering all ffmpeg plugins...\n") );
 
959
    /* register all codecs, demux and protocols */
 
960
    av_register_all();
 
961
    GF_LOG(GF_LOG_DEBUG, GF_LOG_CONTAINER, ("[FFMPEG Demuxer] Registering all ffmpeg plugins DONE.\n") );
 
962
 
 
963
        ffd->RegisterMimeTypes = FFD_RegisterMimeTypes;
 
964
        ffd->CanHandleURL = FFD_CanHandleURL;   
 
965
        ffd->CloseService = FFD_CloseService;
 
966
        ffd->ConnectChannel = FFD_ConnectChannel;
 
967
        ffd->ConnectService = FFD_ConnectService;
 
968
        ffd->DisconnectChannel = FFD_DisconnectChannel;
 
969
        ffd->GetServiceDescriptor = FFD_GetServiceDesc;
 
970
        ffd->ServiceCommand = FFD_ServiceCommand;
 
971
 
 
972
        ffd->CanHandleURLInService = FFD_CanHandleURLInService;
 
973
 
 
974
        priv->thread = gf_th_new("FFMPEG Demux");
 
975
        priv->mx = gf_mx_new("FFMPEG Demux");
 
976
 
 
977
        GF_REGISTER_MODULE_INTERFACE(ffd, GF_NET_CLIENT_INTERFACE, "FFMPEG Demuxer", "gpac distribution");
 
978
        ffd->priv = priv;
 
979
        return ffd;
 
980
}
 
981
 
 
982
void Delete_FFMPEG_Demux(void *ifce)
 
983
{
 
984
        FFDemux *ffd;
 
985
        GF_InputService *ptr = (GF_InputService *)ifce;
 
986
        if (!ptr)
 
987
                return;
 
988
        ffd = ptr->priv;
 
989
        if (ffd) {
 
990
                if (ffd->thread)
 
991
                        gf_th_del(ffd->thread);
 
992
                ffd->thread = NULL;
 
993
                if (ffd->mx)
 
994
                        gf_mx_del(ffd->mx);
 
995
                ffd->mx = NULL;
 
996
                gf_free(ffd);
 
997
                ptr->priv = NULL;
 
998
        }
 
999
        gf_free(ptr);
 
1000
}
 
1001
 
 
1002
 
 
1003
#endif