2
* GPAC - Multimedia Framework C SDK
4
* Authors: Jean Le Feuvre
5
* Copyright (c) Telecom ParisTech 2000-2012
8
* This file is part of GPAC / FFMPEG module
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)
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.
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.
26
#include "ffmpeg_in.h"
28
#ifndef DISABLE_FFMPEG_DEMUX
30
/*default buffer is 200 ms per channel*/
31
#define FFD_DATA_BUFFER 800
33
//#define FFMPEG_DEMUX_ENABLE_MPEG2TS
35
//#if defined(__DARWIN__) || defined(__APPLE__)
36
#if !defined(WIN32) && !defined(_WIN32_WCE) && !defined(__SYMBIAN32__)
41
* New versions of ffmpeg do not declare AVERROR_NOMEM, AVERROR_IO, AVERROR_NOFMT
45
#define AVERROR_NOMEM AVERROR(ENOMEM)
46
#endif /* AVERROR_NOMEM */
49
#define AVERROR_IO AVERROR(EIO)
50
#endif /* AVERROR_IO */
53
#define AVERROR_NOFMT AVERROR(EINVAL)
54
#endif /* AVERROR_NOFMT */
57
#if (LIBAVFORMAT_VERSION_MAJOR >= 54) && (LIBAVFORMAT_VERSION_MINOR >= 20)
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
68
static u32 FFDemux_Run(void *par)
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;
77
FFDemux *ffd = (FFDemux *) par;
79
memset(&map, 0, sizeof(GF_NetworkCommand));
80
map.command_type = GF_NET_CHAN_MAP_TIME;
82
memset(&com, 0, sizeof(GF_NetworkCommand));
83
com.command_type = GF_NET_CHAN_BUFFER_QUERY;
85
memset(&slh, 0, sizeof(GF_SLHeader));
87
slh.compositionTimeStampFlag = slh.decodingTimeStampFlag = 1;
88
seek_to = (s64) (AV_TIME_BASE*ffd->seek_time);
89
map_video_time = !ffd->seekable;
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);
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;
103
while (ffd->is_running) {
105
pkt.stream_index = -1;
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;
111
slh.compositionTimeStamp = pkt.pts;
112
slh.decodingTimeStamp = pkt.dts;
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;
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;
127
gf_term_on_command(ffd->service, &map, GF_OK);
129
else if (slh.compositionTimeStamp < seek_audio) {
130
slh.decodingTimeStamp = slh.compositionTimeStamp = seek_audio;
132
gf_term_on_sl_packet(ffd->service, ffd->audio_ch, pkt.data, pkt.size, &slh, GF_OK);
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;
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) ) {
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);
150
else if (slh.compositionTimeStamp < seek_video) {
151
slh.decodingTimeStamp = slh.compositionTimeStamp = seek_video;
153
gf_term_on_sl_packet(ffd->service, ffd->video_ch, pkt.data, pkt.size, &slh, GF_OK);
157
av_free_packet(&pkt);
159
/*here's the trick - only seek after sending the first packets of each stream - this allows ffmpeg video decoders
161
if (do_seek && video_init && ffd->seekable) {
162
av_seek_frame(ffd->ctx, -1, seek_to, AVSEEK_FLAG_BACKWARD);
164
map_audio_time = ffd->unreliable_audio_timing;
166
/*sleep untill the buffer occupancy is too low - note that this work because all streams in this
167
demuxer are synchronized*/
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;
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;
181
/*escape if disconnect*/
182
if (!ffd->audio_run && !ffd->video_run) break;
184
if (!ffd->audio_run && !ffd->video_run) break;
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);
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",
222
static u32 FFD_RegisterMimeTypes(const GF_InputService *plug){
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]);
229
static int open_file(AVFormatContext ** ic_ptr, const char * filename, AVInputFormat * fmt){
231
return av_open_input_file(ic_ptr, filename, fmt, 0, NULL);
233
return avformat_open_input(ic_ptr, filename, fmt, NULL);
238
static Bool FFD_CanHandleURL(GF_InputService *plug, const char *url)
240
Bool has_audio, has_video;
242
AVFormatContext *ctx;
243
AVOutputFormat *fmt_out;
245
char *ext, szName[1000], szExt[20];
246
const char *szExtList;
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;
259
ext = strrchr(szName, '#');
261
ext = strrchr(szName, '?');
264
ext = strrchr(szName, '.');
265
if (ext && strlen(ext) > 19) ext = NULL;
267
if (ext && strlen(ext) > 1) {
268
strcpy(szExt, &ext[1]);
270
#ifndef FFMPEG_DEMUX_ENABLE_MPEG2TS
271
if (!strcmp(szExt, "ts")) return 0;
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")
285
|| !strcmp(szExt, "jpg") || !strcmp(szExt, "jpeg") || !strcmp(szExt, "png")
288
/*check any default stuff that should work with ffmpeg*/
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))
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");
304
if (open_file(&ctx, szName, av_in)<0) {
308
if (!ctx || av_find_stream_info(ctx) <0) goto exit;
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;
318
case AVMEDIA_TYPE_VIDEO:
319
if (!has_video) has_video= 1;
325
if (!has_audio && !has_video) goto exit;
327
#if LIBAVFORMAT_VERSION_MAJOR < 53 && LIBAVFORMAT_VERSION_MINOR < 45
328
fmt_out = guess_stream_format(NULL, url, NULL);
330
fmt_out = av_guess_format(NULL, url, NULL);
332
if (fmt_out) gf_term_register_mime_type(plug, fmt_out->mime_type, fmt_out->extensions, fmt_out->name);
334
ext = strrchr(szName, '.');
336
strcpy(szExt, &ext[1]);
339
szExtList = gf_modules_get_option((GF_BaseInterface *)plug, "MimeTypes", "application/x-ffmpeg");
341
gf_term_register_mime_type(plug, "application/x-ffmpeg", szExt, "Other Movies (FFMPEG)");
342
} else if (!strstr(szExtList, szExt)) {
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);
356
if (ctx) av_close_input_file(ctx);
360
static GF_ESD *FFD_GetESDescriptor(FFDemux *ffd, Bool for_audio)
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;
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*/
372
AVCodecContext *dec = ffd->ctx->streams[ffd->audio_st]->codec;
373
esd->slConfig->timestampResolution = ffd->audio_tscale.den;
374
switch (dec->codec_id) {
376
esd->decoderConfig->objectTypeIndication = GPAC_OTI_AUDIO_MPEG1;
379
esd->decoderConfig->objectTypeIndication = GPAC_OTI_AUDIO_MPEG2_PART3;
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,
388
sizeof(char)*dec->extradata_size);
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);
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);
407
gf_bs_get_content(bs, (char **) &esd->decoderConfig->decoderSpecificInfo->data, &esd->decoderConfig->decoderSpecificInfo->dataLength);
411
dont_use_sl = ffd->unreliable_audio_timing;
413
AVCodecContext *dec = ffd->ctx->streams[ffd->video_st]->codec;
414
esd->slConfig->timestampResolution = ffd->video_tscale.den;
415
switch (dec->codec_id) {
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,
429
sizeof(char)*dec->extradata_size);
431
case CODEC_ID_MPEG1VIDEO:
432
esd->decoderConfig->objectTypeIndication = GPAC_OTI_VIDEO_MPEG1;
434
case CODEC_ID_MPEG2VIDEO:
435
esd->decoderConfig->objectTypeIndication = GPAC_OTI_VIDEO_MPEG2_422;
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);
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);
449
if (dec->extradata_size) {
450
gf_bs_write_data(bs, dec->extradata, dec->extradata_size);
452
gf_bs_get_content(bs, (char **) &esd->decoderConfig->decoderSpecificInfo->data, &esd->decoderConfig->decoderSpecificInfo->dataLength);
460
esd->slConfig->predefined = SLPredef_SkipSL;
462
/*only send full AUs*/
463
esd->slConfig->useAccessUnitStartFlag = esd->slConfig->useAccessUnitEndFlag = 0;
464
esd->slConfig->hasRandomAccessUnitsOnlyFlag = 1;
465
esd->slConfig->useTimestampsFlag = 1;
472
static void FFD_SetupObjects(FFDemux *ffd)
475
GF_ObjectDescriptor *od;
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);
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);
497
static int ff_url_read(void *h, unsigned char *buf, int size)
502
FFDemux *ffd = (FFDemux *)h;
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);
514
full_size += ffd->buffer_used;
515
buf += ffd->buffer_used;
516
size -= ffd->buffer_used;
517
ffd->buffer_used = 0;
521
GF_Err e = gf_dm_sess_fetch_data(ffd->dnload, buf, size, &read);
522
if (e==GF_EOS) break;
524
if (e==GF_IP_NETWORK_EMPTY) {
526
GF_LOG(GF_LOG_ERROR, GF_LOG_CONTAINER, ("[FFMPEG Demuxer] timeout fetching bytes from network\n") );
534
GF_LOG(GF_LOG_ERROR, GF_LOG_CONTAINER, ("[FFMPEG Demuxer] error fetching bytes from network: %s\n", gf_error_to_string(e) ) );
538
if (read==size) break;
542
#ifdef FFMPEG_DUMP_REMOTE
543
if (ffd->outdbg) gf_fwrite(ffd->buffer, full_size, 1, ffd->outdbg);
545
return full_size ? (int) full_size : -1;
547
#endif /*USE_PRE_0_7*/
550
static GF_Err FFD_ConnectService(GF_InputService *plug, GF_ClientService *serv, const char *url)
558
char *ext, szName[1024];
559
FFDemux *ffd = plug->priv;
560
AVInputFormat *av_in = NULL;
563
if (ffd->ctx) return GF_SERVICE_ERROR;
565
assert( url && strlen(url) < 1024);
567
ext = strrchr(szName, '#');
568
ffd->service_type = 0;
569
e = GF_NOT_SUPPORTED;
573
if (!stricmp(&ext[1], "video")) ffd->service_type = 1;
574
else if (!stricmp(&ext[1], "audio")) ffd->service_type = 2;
578
/*some extensions not supported by ffmpeg, overload input format*/
579
ext = strrchr(szName, '.');
580
strcpy(szExt, ext ? ext+1 : "");
582
if (!strcmp(szExt, "cmp")) av_in = av_find_input_format("m4v");
584
is_local = (strnicmp(url, "file://", 7) && strstr(url, "://")) ? 0 : 1;
586
GF_LOG(GF_LOG_DEBUG, GF_LOG_CONTAINER, ("[FFMPEG] opening file %s - local %d - av_in %08x\n", url, is_local, av_in));
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");
600
init_put_byte(&ffd->io, ffd->buffer, ffd->buffer_size, 0, ffd, ff_url_read, NULL, NULL);
601
ffd->io.is_streamed = 1;
603
ffd->io.seekable = 1;
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;
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;
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;
619
const char *cache_file = gf_dm_sess_get_cache_name(ffd->dnload);
620
res = open_file(&ffd->ctx, cache_file, av_in);
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);
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;
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);
635
res = av_open_input_stream(&ffd->ctx, &ffd->io, szName, av_in, NULL);
639
res = open_file(&ffd->ctx, szName, av_in);
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;
650
default: e = GF_SERVICE_ERROR; goto err_exit;
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));
655
res = av_find_stream_info(ffd->ctx);
657
GF_LOG(GF_LOG_ERROR, GF_LOG_CONTAINER, ("[FFMPEG] cannot locate streams - error %d\n", res));
658
e = GF_NOT_SUPPORTED;
661
GF_LOG(GF_LOG_DEBUG, GF_LOG_CONTAINER, ("[FFMPEG] file %s opened - %d streams\n", url, ffd->ctx->nb_streams));
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)) {
671
ffd->audio_tscale = ffd->ctx->streams[i]->time_base;
674
case AVMEDIA_TYPE_VIDEO:
675
if ((ffd->video_st<0) && (ffd->service_type!=2)) {
677
ffd->video_tscale = ffd->ctx->streams[i]->time_base;
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"));
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;
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) {
703
for (i=0; i<20; i++) {
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;
710
if (last_aud_pts*ffd->audio_tscale.den<10*ffd->audio_tscale.num) ffd->unreliable_audio_timing = 1;
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);
717
open_file(&ffd->ctx, szName, av_in);
718
av_find_stream_info(ffd->ctx);
723
gf_term_on_connect(serv, NULL, GF_OK);
724
/*if (!ffd->service_type)*/ FFD_SetupObjects(ffd);
725
ffd->service_type = 0;
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);
732
gf_term_on_connect(serv, NULL, e);
737
static GF_Descriptor *FFD_GetServiceDesc(GF_InputService *plug, u32 expect_type, const char *sub_url)
739
GF_ObjectDescriptor *od;
741
FFDemux *ffd = plug->priv;
743
if (!ffd->ctx) return NULL;
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;
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;
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;
778
static GF_Err FFD_CloseService(GF_InputService *plug)
780
FFDemux *ffd = plug->priv;
784
if (ffd->ctx) av_close_input_file(ffd->ctx);
786
ffd->audio_ch = ffd->video_ch = NULL;
787
ffd->audio_run = ffd->video_run = 0;
790
if (ffd->is_running) {
791
while (!ffd->is_running) gf_sleep(1);
794
gf_term_download_del(ffd->dnload);
797
if (ffd->buffer) gf_free(ffd->buffer);
800
gf_term_on_disconnect(ffd->service, NULL, GF_OK);
801
#ifdef FFMPEG_DUMP_REMOTE
802
if (ffd->outdbg) fclose(ffd->outdbg);
807
static GF_Err FFD_ConnectChannel(GF_InputService *plug, LPNETCHANNEL channel, const char *url, Bool upstream)
811
FFDemux *ffd = plug->priv;
813
e = GF_STREAM_NOT_FOUND;
815
e = GF_ISOM_INVALID_FILE;
818
if (!strstr(url, "ES_ID=")) {
819
e = GF_NOT_SUPPORTED;
822
sscanf(url, "ES_ID=%u", &ESID);
824
if ((s32) ESID == 1 + ffd->audio_st) {
826
e = GF_SERVICE_ERROR;
829
ffd->audio_ch = channel;
832
else if ((s32) ESID == 1 + ffd->video_st) {
834
e = GF_SERVICE_ERROR;
837
ffd->video_ch = channel;
842
gf_term_on_connect(ffd->service, channel, e);
846
static GF_Err FFD_DisconnectChannel(GF_InputService *plug, LPNETCHANNEL channel)
849
FFDemux *ffd = plug->priv;
851
e = GF_STREAM_NOT_FOUND;
852
if (ffd->audio_ch == channel) {
854
ffd->audio_ch = NULL;
857
else if (ffd->video_ch == channel) {
859
ffd->video_ch = NULL;
862
gf_term_on_disconnect(ffd->service, channel, e);
866
static GF_Err FFD_ServiceCommand(GF_InputService *plug, GF_NetworkCommand *com)
868
FFDemux *ffd = plug->priv;
871
if (com->command_type==GF_NET_SERVICE_HAS_AUDIO) {
872
if (ffd->audio_st>=0) return GF_OK;
873
return GF_NOT_SUPPORTED;
876
if (!com->base.on_channel) return GF_NOT_SUPPORTED;
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;
887
case GF_NET_CHAN_DURATION:
888
if (ffd->ctx->duration == AV_NOPTS_VALUE)
889
com->duration.duration = -1;
891
com->duration.duration = (Double) ffd->ctx->duration / AV_TIME_BASE;
894
case GF_NET_CHAN_PLAY:
895
if (com->play.speed<0) return GF_NOT_SUPPORTED;
898
ffd->seek_time = (com->play.start_range>=0) ? com->play.start_range : 0;
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;
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) {
907
gf_th_run(ffd->thread, FFDemux_Run, ffd);
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;
916
/*note we don't handle PAUSE/RESUME/SET_SPEED, this is automatically handled by the demuxing thread
917
through buffer occupancy queries*/
927
static Bool FFD_CanHandleURLInService(GF_InputService *plug, const char *url)
929
char szURL[2048], *sep;
931
const char *this_url;
934
ffd = (FFDemux *)plug->priv;
935
this_url = gf_term_get_service_url(ffd->service);
939
strcpy(szURL, this_url);
940
sep = strrchr(szURL, '#');
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;
950
void *New_FFMPEG_Demux()
953
GF_InputService *ffd = gf_malloc(sizeof(GF_InputService));
954
memset(ffd, 0, sizeof(GF_InputService));
956
GF_SAFEALLOC(priv, FFDemux);
958
GF_LOG(GF_LOG_INFO, GF_LOG_CONTAINER, ("[FFMPEG Demuxer] Registering all ffmpeg plugins...\n") );
959
/* register all codecs, demux and protocols */
961
GF_LOG(GF_LOG_DEBUG, GF_LOG_CONTAINER, ("[FFMPEG Demuxer] Registering all ffmpeg plugins DONE.\n") );
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;
972
ffd->CanHandleURLInService = FFD_CanHandleURLInService;
974
priv->thread = gf_th_new("FFMPEG Demux");
975
priv->mx = gf_mx_new("FFMPEG Demux");
977
GF_REGISTER_MODULE_INTERFACE(ffd, GF_NET_CLIENT_INTERFACE, "FFMPEG Demuxer", "gpac distribution");
982
void Delete_FFMPEG_Demux(void *ifce)
985
GF_InputService *ptr = (GF_InputService *)ifce;
991
gf_th_del(ffd->thread);