source: titan/libeplayer3/container/container_ffmpeg.c @ 42162

Last change on this file since 42162 was 42162, checked in by obi, 5 years ago

update libeplayer3 to v47

File size: 130.7 KB
Line 
1/*
2 * Container handling for all stream's handled by ffmpeg
3 * konfetti 2010; based on code from crow
4 *
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
19 *
20 */
21
22 /* Support Large File */
23#define _FILE_OFFSET_BITS 64
24
25/* ***************************** */
26/* Includes                      */
27/* ***************************** */
28
29#include <stdio.h>
30#include <stdlib.h>
31#include <sys/ioctl.h>
32#include <fcntl.h>
33#include <unistd.h>
34#include <memory.h>
35#include <string.h>
36
37#include <sys/stat.h>
38#include <fcntl.h>
39#include <errno.h>
40#include <sys/poll.h>
41#include <pthread.h>
42#include <sys/prctl.h>
43#include <stdint.h>
44
45#include <libavutil/avutil.h>
46#include <libavutil/time.h>
47#include <libavformat/avformat.h>
48#include <libswresample/swresample.h>
49#include <libavutil/opt.h>
50
51#include <ffmpeg/mpeg4audio.h>
52
53#include "common.h"
54#include "misc.h"
55#include "debug.h"
56#include "aac.h"
57#include "pcm.h"
58#include "ffmpeg_metadata.h"
59/* ***************************** */
60/* Makros/Constants              */
61/* ***************************** */
62#if (LIBAVFORMAT_VERSION_MAJOR > 57)
63#define TS_BYTES_SEEKING 0
64#else
65#define TS_BYTES_SEEKING 1
66#endif
67
68/* Some STB with old kernels have problem with default
69 * read/write functions in ffmpeg which use open/read
70 * due to this we set own which use fopen/fread from
71 * std library.
72 */
73#define SAM_CUSTOM_IO
74//obi
75#define SAM_WITH_DEBUG
76//obi (end)
77#ifdef SAM_WITH_DEBUG
78#define FFMPEG_DEBUG
79#else
80#define FFMPEG_SILENT
81#endif
82
83#ifdef FFMPEG_DEBUG
84
85//obi
86static short debug_level = 10;
87//obi (end)
88
89#define ffmpeg_printf(level, fmt, x...) do { \
90if (debug_level >= level) printf("[%s:%s] " fmt, __FILE__, __FUNCTION__, ## x); } while (0)
91#else
92#define ffmpeg_printf(level, fmt, x...)
93#endif
94
95#ifndef FFMPEG_SILENT
96#define ffmpeg_err(fmt, x...) do { printf("[%s:%s] " fmt, __FILE__, __FUNCTION__, ## x); } while (0)
97#else
98#define ffmpeg_err(fmt, x...)
99#endif
100
101/* Error Constants */
102#define cERR_CONTAINER_FFMPEG_NO_ERROR        0
103#define cERR_CONTAINER_FFMPEG_INIT           -1
104#define cERR_CONTAINER_FFMPEG_NOT_SUPPORTED  -2
105#define cERR_CONTAINER_FFMPEG_INVALID_FILE   -3
106#define cERR_CONTAINER_FFMPEG_RUNNING        -4
107#define cERR_CONTAINER_FFMPEG_NOMEM          -5
108#define cERR_CONTAINER_FFMPEG_OPEN           -6
109#define cERR_CONTAINER_FFMPEG_STREAM         -7
110#define cERR_CONTAINER_FFMPEG_NULL           -8
111#define cERR_CONTAINER_FFMPEG_ERR            -9
112#define cERR_CONTAINER_FFMPEG_END_OF_FILE    -10
113
114#define IPTV_AV_CONTEXT_MAX_NUM 2
115/* ***************************** */
116/* Types                         */
117/* ***************************** */
118typedef enum {RTMP_NATIVE, RTMP_LIBRTMP, RTMP_NONE} eRTMPProtoImplType;
119
120/* ***************************** */
121/* Varaibles                     */
122/* ***************************** */
123
124static pthread_mutex_t mutex;
125
126static pthread_t PlayThread;
127static int32_t hasPlayThreadStarted = 0;
128
129static AVFormatContext *avContextTab[IPTV_AV_CONTEXT_MAX_NUM] = {NULL, NULL};
130static int32_t use_custom_io[IPTV_AV_CONTEXT_MAX_NUM] = {0, 0};
131static AVDictionary *avio_opts = NULL;
132
133static uint8_t isContainerRunning = 0;
134
135static int64_t latestPts = 0;
136
137static int32_t restart_audio_resampling = 0;
138
139static off_t seek_target_bytes = 0;
140static int32_t do_seek_target_bytes = 0;
141
142static int64_t seek_target_seconds = 0;
143static int8_t do_seek_target_seconds = 0;
144static int64_t prev_seek_time_sec = -1;
145
146static int32_t seek_target_flag = 0;
147
148static int32_t mutexInitialized = 0;
149
150/* ***************************** */
151/* Prototypes                    */
152/* ***************************** */
153static int32_t container_ffmpeg_seek_bytes(off_t pos);
154static int32_t container_ffmpeg_seek(Context_t *context, int64_t sec, uint8_t absolute);
155static int32_t container_ffmpeg_seek_rel(Context_t *context, off_t pos, int64_t pts, int64_t sec);
156static int32_t container_ffmpeg_get_length(Context_t *context, int64_t *length);
157static int64_t calcPts(uint32_t avContextIdx, AVStream *stream, int64_t pts);
158
159/* Progressive playback means that we play local file
160 * but this local file can grows up, for example
161 * we start playback before download was finished
162 */
163static int32_t progressive_playback = 0;
164void progressive_playback_set(int32_t val)
165{
166    progressive_playback = val;
167}
168
169static void initMutex(void)
170{
171    pthread_mutex_init(&mutex, NULL);
172    mutexInitialized = 1;
173}
174
175static void getMutex(const char *filename __attribute__((unused)), const char *function __attribute__((unused)), int32_t line)
176{
177    ffmpeg_printf(100, "::%d requesting mutex\n", line);
178
179    if (!mutexInitialized)
180    {
181        initMutex();
182    }
183
184    pthread_mutex_lock(&mutex);
185
186    ffmpeg_printf(100, "::%d received mutex\n", line);
187}
188
189static void releaseMutex(const char *filename __attribute__((unused)), const const char *function __attribute__((unused)), int32_t line)
190{
191    pthread_mutex_unlock(&mutex);
192
193    ffmpeg_printf(100, "::%d released mutex\n", line);
194}
195
196typedef int32_t (* Write_FN) (void  *, void *);
197
198static int32_t Write(Write_FN WriteFun, void *context, void *privateData, int64_t pts)
199{
200    /* Because Write is blocking we will release mutex which protect
201     * avformat structures, during write time
202     */
203    int32_t ret = 0;
204    releaseMutex(__FILE__, __FUNCTION__,__LINE__);
205    ret = WriteFun(context, privateData);
206    getMutex(__FILE__, __FUNCTION__,__LINE__);
207    return ret;
208}
209
210
211#include "buff_ffmpeg.c"
212#include "wrapped_ffmpeg.c"
213//obi
214#include "tools_ffmpeg.c"
215//obi (end)
216#if LIBAVCODEC_VERSION_INT >= AV_VERSION_INT(56, 34, 100)
217#include "mpeg4p2_ffmpeg.c"
218#endif
219
220#ifdef HAVE_FLV2MPEG4_CONVERTER
221#include "flv2mpeg4_ffmpeg.c"
222#endif
223
224/* This is also bad solution
225 * such configuration should passed maybe
226 * via struct
227 */
228static int32_t wma_software_decode = 0;
229static int32_t aac_software_decode = 0;
230#ifdef __sh__
231static int32_t aac_latm_software_decode = 1;
232#else
233static int32_t aac_latm_software_decode = 0;
234#endif
235
236static int32_t ac3_software_decode = 0;
237static int32_t eac3_software_decode = 0;
238static int32_t dts_software_decode = 0;
239static int32_t pcm_resampling = 1;
240static int32_t stereo_software_decoder = 0;
241static int32_t insert_pcm_as_lpcm = 0;
242static int32_t mp3_software_decode = 0;
243static int32_t rtmp_proto_impl = 0; // 0 - auto, 1 - native, 2 - librtmp
244
245static int32_t g_sel_program_id = -1;
246
247#ifdef HAVE_FLV2MPEG4_CONVERTER
248static int32_t flv2mpeg4_converter = 1;
249#else
250static int32_t flv2mpeg4_converter = 0;
251#endif
252
253/* ***************************** */
254/* MISC Functions                */
255/* ***************************** */
256
257//obi
258    uint32_t         tmptrackId;
259//    uint8_t         *tmpdata;
260    char         *tmpdata;
261
262    uint32_t         tmplen;
263    int64_t          tmppts;
264    int64_t          tmpduration; // duration in miliseconds
265    char            *tmptype;
266    int              enablesub = 0;
267
268void dvbsub_ass_write(Context_t *context, AVCodecContext *c, AVSubtitle *sub, int pid, AVPacket *packet)
269{
270   unsigned int i;
271
272   ffmpeg_printf(0, "format %d\n", sub->format);
273   ffmpeg_printf(0, "start_display_time %d\n", sub->start_display_time);
274   ffmpeg_printf(0, "end_display_time %d\n", sub->end_display_time);
275   ffmpeg_printf(0, "num_rects %d\n", sub->num_rects);
276   //ffmpeg_printf(0, "pts %lld\n", sub->pts);
277
278   for (i = 0; i < sub->num_rects; i++)
279   {
280
281                ffmpeg_printf(0, "x %d\n", sub->rects[i]->x);
282                ffmpeg_printf(0, "y %d\n", sub->rects[i]->y);
283                ffmpeg_printf(0, "w %d\n", sub->rects[i]->w);
284                ffmpeg_printf(0, "h %d\n", sub->rects[i]->h);
285                ffmpeg_printf(0, "nb_colors %d\n", sub->rects[i]->nb_colors);
286                ffmpeg_printf(0, "type %d\n", sub->rects[i]->type);
287                ffmpeg_printf(0, "text %s\n", sub->rects[i]->text);
288                ffmpeg_printf(0, "ass %s\n", sub->rects[i]->ass);
289               
290               
291                ffmpeg_printf(0, "packet->data %s\n", packet->data);
292                ffmpeg_printf(0, "packet->data[0] %x\n", packet->data[0]);
293                ffmpeg_printf(0, "packet->data[1] %x\n", packet->data[1]);
294
295                subtext = ostrcat(subtext, (char *)sub->rects[i]->ass, 1, 0);   
296
297                int ret, horIni, minIni, secIni, milIni, horFim, minFim, secFim, milFim;
298                double Duration = 0;
299                unsigned long long int Pts = 0;
300
301                ret = sscanf((char *)sub->rects[i]->ass, "Dialogue: 0,%d:%d:%d.%d,%d:%d:%d.%d,", &horIni, &minIni, &secIni, &milIni, &horFim, &minFim, &secFim, &milFim);
302
303                if (ret!=8) continue; /* Data is not in correct format */
304                ffmpeg_printf(0, "ret %d\n", ret);
305
306                ffmpeg_printf(0, "horIni %d\n", horIni);
307                ffmpeg_printf(0, "minIni %d\n", minIni);
308                ffmpeg_printf(0, "secIni %d\n", secIni);
309                ffmpeg_printf(0, "milIni %d\n", milIni);
310
311                ffmpeg_printf(0, "horFim %d\n", horFim);
312                ffmpeg_printf(0, "minFim %d\n", minFim);
313                ffmpeg_printf(0, "secFim %d\n", secFim);
314                ffmpeg_printf(0, "milFim %d\n", milFim);
315/*
316                Pts = (horIni*3600 + minIni*60 + secIni)*1000 + milIni;
317                Duration = ((horFim*3600 + minFim*60 + secFim) * 1000  + milFim - Pts) / 1000.0;
318                ffmpeg_printf(0, "new Pts %llu\n", Pts);
319                ffmpeg_printf(0, "new Duration %f\n", Duration);
320
321*/
322                tmppts = (horIni*3600 + minIni*60 + secIni)*1000 + milIni;
323                tmpduration = ((horFim*3600 + minFim*60 + secFim) * 1000  + milFim - Pts) / 1000.0;
324                tmpdata = packet->data;
325
326                ffmpeg_printf(0, "new Pts %llu\n", tmppts);
327                ffmpeg_printf(0, "new Duration %d\n", tmpduration);
328                ffmpeg_printf(0, "new Data %s\n", tmpdata);
329
330                // pict ->AVPicture
331   }
332}
333
334//int ReadSubtitle(Context_t *context, const char *filename, const char *format, int pid)
335int ReadSubtitle(Context_t *context, const char *filename, char *format, int pid)
336{
337        int ret = 0;
338        const char *lastDot = strrchr(filename, '.');
339        if (!lastDot)
340                return ret;
341        char subfile[strlen(filename) + strlen(format)];
342        strcpy(subfile, filename);
343        strcpy(subfile + (lastDot + 1 - filename), format);
344
345        if (access(subfile, R_OK))
346                return ret;
347
348        AVFormatContext *subavfc = avformat_alloc_context();
349        int err = avformat_open_input(&subavfc, subfile, av_find_input_format(format), 0);
350//      if (averror(err, avformat_open_input)) {
351        if (err != 0)
352    {
353                avformat_free_context(subavfc);
354                return ret;
355        }
356
357        avformat_find_stream_info(subavfc, NULL);
358        if (subavfc->nb_streams != 1) {
359                avformat_free_context(subavfc);
360                return ret;
361        }
362
363        AVCodecContext *c = subavfc->streams[0]->codec;
364        AVCodec *codec = avcodec_find_decoder(c->codec_id);
365        if (!codec) {
366                avformat_free_context(subavfc);
367                return ret;
368        }
369
370        err = avcodec_open2(c, codec, NULL);
371//      if (averror(err, avcodec_open2)) {
372        if (err != 0)
373    {
374                avformat_free_context(subavfc);
375                return ret;
376        }
377
378        AVPacket packet;
379        av_init_packet(&packet);
380
381        free(subtext), subtext = NULL;
382
383        while (av_read_frame(subavfc, &packet) > -1) {
384                AVSubtitle sub;
385                memset(&sub, 0, sizeof(sub));
386                int got_sub = 0;
387                avcodec_decode_subtitle2(c, &sub, &got_sub, &packet);
388                if (got_sub)
389                {
390                        dvbsub_ass_write(context, c, &sub, pid, &packet);
391
392                        char* tmpstr = NULL;
393                        tmpstr = ostrcat(tmpstr, "duration=", 1, 0);
394                        tmpstr = ostrcat(tmpstr, ollutoa(tmpduration), 1, 1);
395                        tmpstr = ostrcat(tmpstr, ";pts=", 1, 0);;
396                        tmpstr = ostrcat(tmpstr, ollutoa(tmppts), 1, 0);;
397                        tmpstr = ostrcat(tmpstr, ";trackid=", 1, 0);;
398                        tmpstr = ostrcat(tmpstr, oitoa(tmptrackId), 1, 0);
399                        tmpstr = ostrcat(tmpstr, ";subtext=", 1, 0);;
400                        tmpstr = ostrcat(tmpstr, tmpdata, 1, 0);;
401                        tmpstr = ostrcat(tmpstr, "\n", 1, 0);;
402
403                        subtext = ostrcat(subtext, tmpstr, 1, 0);
404                        free(tmpstr), tmpstr = NULL;
405
406                        tmpduration = 0;
407                        tmppts = 0;
408                        tmptrackId = 0;
409
410
411                }
412                av_free_packet(&packet);
413        }
414
415//      free(subtext), subtext = NULL;
416
417        avcodec_close(c);
418        avformat_close_input(&subavfc);
419        avformat_free_context(subavfc);
420
421        ffmpeg_printf(1, "format=%s\n", format);
422        ffmpeg_printf(1, "pid=%d\n", pid);
423
424        if(pid != -1)
425        {
426                Track_t Subtitle;
427                memset(&Subtitle, 0, sizeof(Subtitle));
428                Subtitle.Name = ostrcat("External Sub: ", format, 0, 0);
429                if(ostrstr(format, "srt") != NULL)
430                        Subtitle.Encoding = "S_TEXT/SRT";
431                else if(ostrstr(format, "ass") != NULL)
432                        Subtitle.Encoding = "S_TEXT/ASS";
433                else if(ostrstr(format, "ssa") != NULL)
434                        Subtitle.Encoding = "S_TEXT/SSA";
435                else if(ostrstr(format, "sub") != NULL)
436                        Subtitle.Encoding = "S_TEXT/SUBRIP";
437                else if(ostrstr(format, "idx") != NULL)
438                        Subtitle.Encoding = "S_TEXT/SUBRIP";
439                Subtitle.File       = strdup(subfile); 
440                Subtitle.Id = pid,
441                context->manager->subtitle->Command(context, MANAGER_ADD, &Subtitle);
442        }
443
444//      Track track;
445//      track.title = format;
446//      track.is_static = 1;
447//      track.pid = pid;
448//      player->manager.addSubtitleTrack(track);
449        return 1;
450}
451
452int ReadSubtitles(Context_t *context, const char *filename)
453{
454        int ret = 0;
455        if (strncmp(filename, "file://", 7))
456                return ret;
457        filename += 7;
458        ret |= ReadSubtitle(context, filename, "srt", 0xFFFF);
459        ret |= ReadSubtitle(context, filename, "ass", 0xFFFE);
460        ret |= ReadSubtitle(context, filename, "ssa", 0xFFFD);
461        ret |= ReadSubtitle(context, filename, "sub", 0xFFFC);
462        ret |= ReadSubtitle(context, filename, "idx", 0xFFFB);
463        return ret;
464}
465//obi (end)
466
467static void ffmpeg_silen_callback(void * avcl, int level, const char * fmt, va_list vl)
468{
469    return;
470}
471
472//static int32_t mutexInitialized = 0;
473
474void sel_program_id_set(const int32_t val)
475{
476    g_sel_program_id = val;
477}
478
479void wma_software_decoder_set(const int32_t val)
480{
481    wma_software_decode = val;
482}
483
484void aac_software_decoder_set(const int32_t val)
485{
486    aac_software_decode = val;
487}
488
489void aac_latm_software_decoder_set(const int32_t val)
490{
491    aac_latm_software_decode = val;
492}
493
494void ac3_software_decoder_set(const int32_t val)
495{
496    ac3_software_decode = val;
497}
498
499void eac3_software_decoder_set(const int32_t val)
500{
501    eac3_software_decode = val;
502}
503
504void dts_software_decoder_set(const int32_t val)
505{
506    dts_software_decode = val;
507}
508
509void stereo_software_decoder_set(const int32_t val)
510{
511    stereo_software_decoder = val;
512}
513
514void insert_pcm_as_lpcm_set(const int32_t val)
515{
516    insert_pcm_as_lpcm = val;
517}
518
519void pcm_resampling_set(const int32_t val)
520{
521    pcm_resampling = val;
522}
523
524void mp3_software_decoder_set(const int32_t val)
525{
526    mp3_software_decode = val;
527}
528
529void rtmp_proto_impl_set(const int32_t val)
530{
531    rtmp_proto_impl = val;
532}
533
534void flv2mpeg4_converter_set(const int32_t val)
535{
536    flv2mpeg4_converter = val;
537}
538
539int32_t ffmpeg_av_dict_set(const char *key, const char *value, int32_t flags)
540{
541    return av_dict_set(&avio_opts, key, value, flags);
542}
543
544static char* Codec2Encoding(int32_t codec_id, int32_t media_type, uint8_t *extradata, int extradata_size, int profile, int32_t *version)
545{
546    ffmpeg_printf(10, "Codec ID: %d (%.8lx)\n", codec_id, codec_id);
547    switch (codec_id)
548    {
549    case AV_CODEC_ID_MPEG1VIDEO:
550        return "V_MPEG1";
551    case AV_CODEC_ID_MPEG2VIDEO:
552        return "V_MPEG1";
553    case AV_CODEC_ID_H263:
554    case AV_CODEC_ID_H263P:
555    case AV_CODEC_ID_H263I:
556        return "V_H263";
557    case AV_CODEC_ID_FLV1:
558        return flv2mpeg4_converter ? "V_MPEG4" : "V_FLV";
559    case AV_CODEC_ID_VP5:
560    case AV_CODEC_ID_VP6:
561    case AV_CODEC_ID_VP6F:
562        return "V_VP6";
563    case AV_CODEC_ID_VP8:
564        return "V_VP8";
565#if LIBAVCODEC_VERSION_MAJOR > 54
566    case AV_CODEC_ID_VP9:
567        return "V_VP9";
568#endif
569    case AV_CODEC_ID_RV10:
570    case AV_CODEC_ID_RV20:
571        return "V_RMV";
572    case AV_CODEC_ID_MPEG4:
573        return "V_MPEG4";
574#if LIBAVCODEC_VERSION_MAJOR < 53
575    case AV_CODEC_ID_XVID:
576#endif
577    case AV_CODEC_ID_MSMPEG4V1:
578    case AV_CODEC_ID_MSMPEG4V2:
579    case AV_CODEC_ID_MSMPEG4V3:
580        return "V_DIVX3";
581    case AV_CODEC_ID_WMV1:
582        *version = 1;
583        return "V_WMV";
584    case AV_CODEC_ID_WMV2:
585        *version = 2;
586        return "V_WMV";
587    case AV_CODEC_ID_WMV3:
588        *version = 3;
589        return "V_WMV";
590    case AV_CODEC_ID_VC1:
591        return "V_VC1";
592    case AV_CODEC_ID_H264:
593#if LIBAVCODEC_VERSION_MAJOR < 54
594    case AV_CODEC_ID_FFH264:
595#endif
596        return "V_MPEG4/ISO/AVC";
597#if LIBAVCODEC_VERSION_INT > AV_VERSION_INT(55, 92, 100)
598    case AV_CODEC_ID_HEVC:
599    // case AV_CODEC_ID_H265:
600        return "V_HEVC";
601#endif
602    case AV_CODEC_ID_AVS:
603        return "V_AVS";
604    case AV_CODEC_ID_MP2:
605        return "A_MPEG/L3";
606    case AV_CODEC_ID_MP3:
607        return (mp3_software_decode) ? "A_IPCM" : "A_MP3";
608    case AV_CODEC_ID_AAC:
609        if (extradata_size >= 2)
610        {
611            MPEG4AudioConfig m4ac;
612            int off = avpriv_mpeg4audio_get_config(&m4ac, extradata, extradata_size * 8, 1);
613            ffmpeg_printf(1,"aac [%d] off[%d]\n", m4ac.object_type, off);
614            if (off < 0 || 2 != m4ac.object_type)
615            {
616                return "A_IPCM";
617            }
618        }
619        return (aac_software_decode) ? "A_IPCM" : "A_AAC"; 
620    case AV_CODEC_ID_AAC_LATM:
621        return (aac_latm_software_decode) ? "A_IPCM" : "A_AAC_LATM";
622    case AV_CODEC_ID_AC3:
623        return  (ac3_software_decode) ? "A_IPCM" : "A_AC3";
624    case AV_CODEC_ID_EAC3:
625        return  (eac3_software_decode) ? "A_IPCM" : "A_EAC3";
626    case AV_CODEC_ID_DTS:
627        return (dts_software_decode) ? "A_IPCM" : "A_DTS";
628    case AV_CODEC_ID_WMAV1:
629    case AV_CODEC_ID_WMAV2:
630            return (wma_software_decode) ? "A_IPCM" : "A_WMA";
631    case 86056:
632    case AV_CODEC_ID_WMAPRO:
633        return (wma_software_decode) ? "A_IPCM" : "A_WMA/PRO";
634    case AV_CODEC_ID_WMALOSSLESS:
635        return "A_IPCM";
636    case AV_CODEC_ID_MLP:
637        return "A_IPCM";
638    case AV_CODEC_ID_RA_144:
639        return "A_IPCM";
640    case AV_CODEC_ID_RA_288:
641        return "A_IPCM";
642    case AV_CODEC_ID_VORBIS:
643        return "A_IPCM";
644    case AV_CODEC_ID_FLAC:
645        return "A_IPCM";
646    case AV_CODEC_ID_PCM_S8:
647    case AV_CODEC_ID_PCM_U8:
648    case AV_CODEC_ID_PCM_S16LE:
649    case AV_CODEC_ID_PCM_S16BE:
650    case AV_CODEC_ID_PCM_U16LE:
651    case AV_CODEC_ID_PCM_U16BE:
652    case AV_CODEC_ID_PCM_S24LE:
653    case AV_CODEC_ID_PCM_S24BE:
654    case AV_CODEC_ID_PCM_U24LE:
655    case AV_CODEC_ID_PCM_U24BE:
656    case AV_CODEC_ID_PCM_S32LE:
657    case AV_CODEC_ID_PCM_S32BE:
658    case AV_CODEC_ID_PCM_U32LE:
659    case AV_CODEC_ID_PCM_U32BE:
660        return pcm_resampling ? "A_IPCM" : "A_PCM";
661    case AV_CODEC_ID_AMR_NB:
662        return "A_IPCM";//return "A_AMR";
663
664/* In exteplayer3 embedded text subtitle simple printed
665 * to output like other data.  Maybe worth to consider is to use
666 * linux socket or pipe to put
667 */
668
669/* subtitle */
670    case AV_CODEC_ID_SSA:
671#if LIBAVCODEC_VERSION_INT >= AV_VERSION_INT(55, 3, 100)
672    case AV_CODEC_ID_ASS:
673#endif
674        return "S_TEXT/ASS"; /* Hellmaster1024: seems to be ASS instead of SSA */
675    case AV_CODEC_ID_DVD_SUBTITLE:
676    case AV_CODEC_ID_DVB_SUBTITLE:
677    case AV_CODEC_ID_XSUB:
678    case AV_CODEC_ID_MOV_TEXT:
679    case AV_CODEC_ID_HDMV_PGS_SUBTITLE:
680    case AV_CODEC_ID_DVB_TELETEXT:
681//    case CODEC_ID_DVB_TELETEXT:
682//        return "S_TEXT/SRT"; /* fixme */
683    case AV_CODEC_ID_TEXT: ///< raw UTF-8 text
684        return "S_TEXT/UTF-8";
685    case AV_CODEC_ID_SRT:
686        return "S_TEXT/SRT";
687    case AV_CODEC_ID_SUBRIP:
688        return "S_TEXT/SUBRIP";
689    default:
690        ffmpeg_err("Codec ID %d (%.8lx) not found\n", codec_id, codec_id);
691        // Default to injected-pcm for unhandled audio types.
692        if (media_type == AVMEDIA_TYPE_AUDIO)
693        {
694            return "A_IPCM";
695        }
696        ffmpeg_err("Codec ID %d (%.8lx) not found\n", codec_id, codec_id);
697    }
698    return NULL;
699}
700
701static int64_t calcPts(uint32_t avContextIdx, AVStream *stream, int64_t pts)
702{
703    if (!stream || pts == (int64_t)AV_NOPTS_VALUE)
704    {
705        ffmpeg_err("stream / packet null\n");
706        return INVALID_PTS_VALUE;
707    }
708    else if (stream->time_base.den > 0)
709    {
710        pts = av_rescale(pts, (int64_t)stream->time_base.num * 90000, stream->time_base.den);
711    }
712   
713    if (avContextTab[avContextIdx]->start_time != AV_NOPTS_VALUE)
714    {
715        pts -= 90000 * avContextTab[avContextIdx]->start_time / AV_TIME_BASE;
716    }
717
718    if (pts & 0x8000000000000000ull)
719    {
720        pts = INVALID_PTS_VALUE;
721    }
722    else
723    {
724        pts &= 0x01FFFFFFFF; // PES header can handle only 33 bit PTS
725    }
726
727    return pts;
728}
729
730/* search for metatdata in context and stream
731 * and map it to our metadata.
732 */
733
734static char* searchMeta(void * metadata, char* ourTag)
735{
736#if LIBAVCODEC_VERSION_MAJOR < 54
737   AVMetadataTag *tag = NULL;
738#else
739   AVDictionaryEntry *tag = NULL;
740#endif
741   int i = 0;
742
743   while (metadata_map[i] != NULL)
744   {
745      if (strcmp(ourTag, metadata_map[i]) == 0)
746      {
747#if LIBAVCODEC_VERSION_MAJOR < 54
748          while ((tag = av_metadata_get(metadata, "", tag, AV_METADATA_IGNORE_SUFFIX)))
749#else
750          while ((tag = av_dict_get(metadata, "", tag, AV_DICT_IGNORE_SUFFIX)))
751#endif
752          {
753              if (strcmp(tag->key, metadata_map[ i + 1 ]) == 0)
754              {
755                  return tag->value;
756              }
757          }
758      }
759      i++;
760   }
761
762   return NULL;
763}
764
765/* **************************** */
766/* Worker Thread                */
767/* **************************** */
768
769static void FFMPEGThread(Context_t *context)
770{
771    char threadname[17];
772    strncpy(threadname, __func__, sizeof(threadname));
773    threadname[16] = 0;
774    prctl (PR_SET_NAME, (unsigned long)&threadname);
775    AVPacket   packet;
776    off_t   lastSeek = -1;
777    int64_t lastPts = -1;
778    int64_t currentVideoPts = -1;
779    int64_t currentAudioPts = -1;
780   
781    /* lastVideoDts and lastAudioDts
782     * used in isTSLiveMode
783     */
784    int64_t lastVideoDts = -1;
785    int64_t lastAudioDts = -1;
786   
787    int64_t showtime = 0;
788    int64_t bofcount = 0;
789    int32_t       err = 0;
790    AudioVideoOut_t avOut;
791   
792    g_context = context;
793
794    SwrContext *swr = NULL;
795    AVFrame *decoded_frame = NULL;
796    int32_t out_sample_rate = 44100;
797    int32_t out_channels = 2;
798    uint64_t out_channel_layout = AV_CH_LAYOUT_STEREO;
799    uint32_t cAVIdx = 0;
800
801#if LIBAVCODEC_VERSION_INT >= AV_VERSION_INT(56, 34, 100)
802    Mpeg4P2Context mpeg4p2_context;
803    memset(&mpeg4p2_context, 0, sizeof(Mpeg4P2Context));
804    AVBitStreamFilterContext *mpeg4p2_bsf_context = av_bitstream_filter_init("mpeg4_unpack_bframes");
805#endif
806#ifdef HAVE_FLV2MPEG4_CONVERTER
807    Flv2Mpeg4Context flv2mpeg4_context;
808    memset(&flv2mpeg4_context, 0, sizeof(Flv2Mpeg4Context));
809#endif
810    ffmpeg_printf(10, "\n");
811    while ( context->playback->isCreationPhase )
812    {
813        ffmpeg_err("Thread waiting for end of init phase...\n");
814        usleep(1000);
815    }
816    ffmpeg_printf(10, "Running!\n");
817
818    int8_t isWaitingForFinish = 0;
819    while ( context && context->playback && context->playback->isPlaying )
820    {
821        /* When user press PAUSE we call pause on AUDIO and VIDEO decoders,
822         * we will not wait here because we can still fill
823         * DVB drivers buffers at PAUSE time
824         *
825         * In the future we can add buffering queue before injection in to
826         * AUDIO, VIDEO decoders, so we can not wait here
827         */
828#ifdef __sh__
829        //IF MOVIE IS PAUSED, WAIT
830        if (context->playback->isPaused)
831        {
832            ffmpeg_printf(20, "paused\n");
833            reset_finish_timeout();
834            usleep(10000);
835            continue;
836        }
837#endif
838
839        if (context->playback->isSeeking)
840        {
841            ffmpeg_printf(10, "seeking\n");
842            reset_finish_timeout();
843            usleep(10000);
844            continue;
845        }
846
847        getMutex(__FILE__, __FUNCTION__,__LINE__);
848
849        if (!context->playback || !context->playback->isPlaying)
850        {
851            releaseMutex(__FILE__, __FUNCTION__,__LINE__);
852            if(!isWaitingForFinish)
853            {
854                reset_finish_timeout();
855            }
856            continue;
857        }
858
859        if (do_seek_target_seconds || do_seek_target_bytes)
860        {
861            isWaitingForFinish = 0;
862            if (do_seek_target_seconds)
863            {
864                ffmpeg_printf(10, "seek_target_seconds[%lld]\n", seek_target_seconds);
865                uint32_t i = 0;
866                for(; i<IPTV_AV_CONTEXT_MAX_NUM; i+=1)
867                {
868                    if(NULL != avContextTab[i])
869                    {
870                        if (i == 1)
871                        {
872                            prev_seek_time_sec = seek_target_seconds;
873                        }
874                        if (avContextTab[i]->start_time != AV_NOPTS_VALUE)
875                        {
876                            seek_target_seconds += avContextTab[i]->start_time;
877                            printf("SEEK SECONDS [%lld]\n", seek_target_seconds);
878                        }
879                        //av_seek_frame(avContextTab[i], -1, seek_target_seconds, 0);
880                        avformat_seek_file(avContextTab[i], -1, INT64_MIN, seek_target_seconds, INT64_MAX, 0);
881                    }
882                    else
883                    {
884                        break;
885                    }
886                }
887                reset_finish_timeout();
888            }
889            else
890            {
891                container_ffmpeg_seek_bytes(seek_target_bytes);
892            }
893            do_seek_target_seconds = 0;
894            do_seek_target_bytes = 0;
895           
896            restart_audio_resampling = 1;
897            currentVideoPts = -1;
898            currentAudioPts = -1;
899            latestPts = 0;
900            seek_target_flag = 0;
901
902            // flush streams
903            uint32_t i = 0;
904            for(i=0; i<IPTV_AV_CONTEXT_MAX_NUM; i+=1)
905            {
906                if(NULL != avContextTab[i])
907                {
908                    if (i != 1)
909                    {
910                        wrapped_avcodec_flush_buffers(i);
911                    }
912                }
913                else
914                {
915                    break;
916                }
917            }
918#if LIBAVCODEC_VERSION_INT >= AV_VERSION_INT(56, 34, 100)
919            mpeg4p2_context_reset(&mpeg4p2_context);
920            if (NULL != mpeg4p2_bsf_context)
921            {
922                av_bitstream_filter_close(mpeg4p2_bsf_context);
923                mpeg4p2_bsf_context = av_bitstream_filter_init("mpeg4_unpack_bframes");
924            }
925#endif
926#ifdef HAVE_FLV2MPEG4_CONVERTER
927            flv2mpeg4_context_reset(&flv2mpeg4_context);
928#endif
929        }
930
931        int ffmpegStatus = 0;
932        if(!isWaitingForFinish)
933        {
934            if(NULL != avContextTab[1])
935            {
936                cAVIdx = currentVideoPts <= currentAudioPts ? 0 : 1;
937                if (1 == cAVIdx && prev_seek_time_sec >= 0 )
938                {
939                    avformat_seek_file(avContextTab[1], -1, (currentVideoPts / 90000) * AV_TIME_BASE - AV_TIME_BASE, (currentVideoPts / 90000) * AV_TIME_BASE, (currentVideoPts / 90000) * AV_TIME_BASE + AV_TIME_BASE, 0);
940                    prev_seek_time_sec = -1;
941                    wrapped_avcodec_flush_buffers(1);
942                }
943            }
944            else
945            {
946                cAVIdx = 0;
947            }
948        }
949       
950        if (!isWaitingForFinish && (ffmpegStatus = av_read_frame(avContextTab[cAVIdx], &packet)) == 0 )
951        {
952            int64_t pts = 0;
953            int64_t dts = 0;
954            Track_t *videoTrack = NULL;
955            Track_t *audioTrack = NULL;
956            Track_t *subtitleTrack = NULL;
957
958            int32_t pid = avContextTab[cAVIdx]->streams[packet.stream_index]->id;
959           
960            reset_finish_timeout();
961            if(avContextTab[cAVIdx]->streams[packet.stream_index]->discard != AVDISCARD_ALL)
962            {
963                if (context->manager->video->Command(context, MANAGER_GET_TRACK, &videoTrack) < 0)
964                {
965                    ffmpeg_err("error getting video track\n");
966                }
967               
968                if (context->manager->audio->Command(context, MANAGER_GET_TRACK, &audioTrack) < 0)
969                {
970                    ffmpeg_err("error getting audio track\n");
971                }
972               
973                if (context->manager->subtitle->Command(context, MANAGER_GET_TRACK, &subtitleTrack) < 0)
974                {
975                    ffmpeg_err("error getting subtitle track\n");
976                }
977            }
978            else
979            {
980                ffmpeg_printf(1, "SKIP DISCARDED PACKET stream_index[%d] pid[%d]\n", packet.size, (int)packet.stream_index, pid);
981            }
982           
983            ffmpeg_printf(200, "packet.size %d - index %d\n", packet.size, pid);
984
985            if (videoTrack && (videoTrack->AVIdx == cAVIdx) && (videoTrack->Id == pid))
986            {
987#if LIBAVCODEC_VERSION_INT >= AV_VERSION_INT(56, 34, 100)
988                AVCodecContext *codec_context = videoTrack->avCodecCtx;
989                if (codec_context && codec_context->codec_id == AV_CODEC_ID_MPEG4 && NULL != mpeg4p2_bsf_context)
990                {
991                    // should never happen, if it does print error and exit immediately, so we can easily spot it
992                    if (filter_packet(mpeg4p2_bsf_context, codec_context, &packet) < 0)
993                    {
994                        ffmpeg_err("cannot filter mpegp2 packet\n");
995                        exit(1);
996                    }
997                    if (mpeg4p2_write_packet(context, &mpeg4p2_context, videoTrack, cAVIdx, &currentVideoPts, &latestPts, &packet) < 0)
998                    {
999                        ffmpeg_err("cannot write mpeg4p2 packet\n");
1000                        exit(1);
1001                    }
1002                    update_max_injected_pts(latestPts);
1003                }
1004                else
1005#endif
1006#ifdef HAVE_FLV2MPEG4_CONVERTER
1007                if (get_codecpar(avContextTab[cAVIdx]->streams[packet.stream_index])->codec_id == AV_CODEC_ID_FLV1 &&
1008                    0 == memcmp(videoTrack->Encoding, "V_MPEG4", 7) )
1009                {
1010                    flv2mpeg4_write_packet(context, &flv2mpeg4_context, videoTrack, cAVIdx, &currentVideoPts, &latestPts, &packet);
1011                    update_max_injected_pts(latestPts);
1012                }
1013                else
1014#endif
1015                {
1016                    uint8_t skipPacket = 0;
1017                    currentVideoPts = videoTrack->pts = pts = calcPts(cAVIdx, videoTrack->stream, packet.pts);
1018                    videoTrack->dts = dts = calcPts(cAVIdx, videoTrack->stream, packet.dts);
1019
1020                    if ((currentVideoPts != INVALID_PTS_VALUE) && (currentVideoPts > latestPts))
1021                    {
1022                        latestPts = currentVideoPts;
1023                        update_max_injected_pts(latestPts);
1024                    }
1025                   
1026                    if (context->playback->isTSLiveMode)
1027                    {
1028                        if (dts != INVALID_PTS_VALUE)
1029                        {   
1030                            if (dts > lastVideoDts)
1031                            {
1032                                lastVideoDts = dts;
1033                            }
1034                            else
1035                            {
1036                                // skip already injected VIDEO packet
1037                                ffmpeg_printf(200, "skip already injected VIDEO packet\n");
1038                                skipPacket = 1;
1039                            }
1040                        }
1041                        else
1042                        {
1043                            // skip VIDEO packet with unknown DTS
1044                            ffmpeg_printf(200, "skip VIDEO packet with unknown DTS\n");
1045                            skipPacket = 1;
1046                        }
1047                    }
1048                   
1049                    if (skipPacket)
1050                    {   
1051                        wrapped_packet_unref(&packet);
1052                        releaseMutex(__FILE__, __FUNCTION__,__LINE__);
1053                        continue;
1054                    }
1055                   
1056                    ffmpeg_printf(200, "VideoTrack index = %d %lld\n",pid, currentVideoPts);
1057
1058                    avOut.data       = packet.data;
1059                    avOut.len        = packet.size;
1060                    avOut.pts        = pts;
1061                    avOut.dts        = dts;
1062                    avOut.extradata  = videoTrack->extraData;
1063                    avOut.extralen   = videoTrack->extraSize;
1064                    avOut.frameRate  = videoTrack->frame_rate;
1065                    avOut.timeScale  = videoTrack->TimeScale;
1066                    avOut.width      = videoTrack->width;
1067                    avOut.height     = videoTrack->height;
1068                    avOut.type       = "video";
1069                   
1070                    if (avContextTab[cAVIdx]->iformat->flags & AVFMT_TS_DISCONT)
1071                    {
1072                        avOut.infoFlags = 1; // TS container
1073                    }
1074
1075                    if (Write(context->output->video->Write, context, &avOut, pts) < 0)
1076                    {
1077                        ffmpeg_err("writing data to video device failed\n");
1078                    }
1079                }
1080            }
1081            else if (audioTrack && (audioTrack->AVIdx == cAVIdx) && (audioTrack->Id == pid))
1082            {
1083                uint8_t skipPacket = 0;
1084                currentAudioPts = audioTrack->pts = pts = calcPts(cAVIdx, audioTrack->stream, packet.pts);
1085                dts = calcPts(cAVIdx, audioTrack->stream, packet.dts);
1086
1087                if ((currentAudioPts != INVALID_PTS_VALUE) && (currentAudioPts > latestPts) && (!videoTrack))
1088                {
1089                    latestPts = currentAudioPts;
1090                    update_max_injected_pts(latestPts);
1091                }
1092               
1093                if (context->playback->isTSLiveMode)
1094                {
1095                    if (dts != INVALID_PTS_VALUE)
1096                    {
1097                        if (dts > lastAudioDts)
1098                        {
1099                            lastAudioDts = dts;
1100                        }
1101                        else
1102                        {
1103                            // skip already injected AUDIO packet
1104                            ffmpeg_printf(200, "skip already injected AUDIO packet\n");
1105                            skipPacket = 1;
1106                        }
1107                    }
1108                    else
1109                    {
1110                        // skip AUDIO packet with unknown PTS
1111                        ffmpeg_printf(200, "skip AUDIO packet with unknown PTS\n");
1112                        skipPacket = 1;
1113                    }
1114                }
1115               
1116                if (skipPacket)
1117                {
1118                    wrapped_packet_unref(&packet);
1119                    releaseMutex(__FILE__, __FUNCTION__,__LINE__);
1120                    continue;
1121                }
1122               
1123                pcmPrivateData_t pcmExtradata;
1124                pcmExtradata.channels              = get_codecpar(audioTrack->stream)->channels;
1125                pcmExtradata.bits_per_coded_sample = get_codecpar(audioTrack->stream)->bits_per_coded_sample;
1126                pcmExtradata.sample_rate           = get_codecpar(audioTrack->stream)->sample_rate;
1127                pcmExtradata.bit_rate              = get_codecpar(audioTrack->stream)->bit_rate;
1128                pcmExtradata.ffmpeg_codec_id       = get_codecpar(audioTrack->stream)->codec_id;
1129                pcmExtradata.bResampling           = restart_audio_resampling;
1130               
1131                uint8_t *pAudioExtradata    = get_codecpar(audioTrack->stream)->extradata;
1132                uint32_t audioExtradataSize = get_codecpar(audioTrack->stream)->extradata_size;
1133                   
1134                ffmpeg_printf(200, "AudioTrack index = %d\n",pid);
1135                if (audioTrack->inject_raw_pcm == 1)
1136                {
1137                    ffmpeg_printf(200,"write audio raw pcm\n");
1138                    restart_audio_resampling = 0;
1139
1140                    avOut.data       = packet.data;
1141                    avOut.len        = packet.size;
1142                    avOut.pts        = pts;
1143                    avOut.extradata  = (uint8_t *) &pcmExtradata;
1144                    avOut.extralen   = sizeof(pcmExtradata);
1145                    avOut.frameRate  = 0;
1146                    avOut.timeScale  = 0;
1147                    avOut.width      = 0;
1148                    avOut.height     = 0;
1149                    avOut.type       = "audio";
1150
1151                    if (Write(context->output->audio->Write, context, &avOut, pts) < 0)
1152                    {
1153                        ffmpeg_err("(raw pcm) writing data to audio device failed\n");
1154                    }
1155                }
1156                else if (audioTrack->inject_as_pcm == 1 && audioTrack->avCodecCtx)
1157                {
1158                    AVCodecContext *c = audioTrack->avCodecCtx;
1159
1160                    if (restart_audio_resampling)
1161                    {
1162                        restart_audio_resampling = 0;
1163                        if (swr)
1164                        {
1165                            swr_free(&swr);
1166                            swr = NULL;
1167                        }
1168                        if (decoded_frame)
1169                        {
1170                            wrapped_frame_free(&decoded_frame);
1171                            decoded_frame = NULL;
1172                        }
1173                    }
1174#if (LIBAVFORMAT_VERSION_MAJOR > 57) || ((LIBAVFORMAT_VERSION_MAJOR == 57) && (LIBAVFORMAT_VERSION_MINOR > 32))
1175                    while (packet.size > 0 || (!packet.size && !packet.data))
1176#else
1177                    while(packet.size > 0)
1178#endif
1179                    {
1180                        if(do_seek_target_seconds || do_seek_target_bytes)
1181                        {
1182                            break;
1183                        }
1184                       
1185                        if (!decoded_frame)
1186                        {
1187                            decoded_frame = wrapped_frame_alloc();
1188                            if (!decoded_frame)
1189                            {
1190                                ffmpeg_err("out of memory\n");
1191                                exit(1);
1192                            }
1193                        }
1194                        else
1195                        {
1196                            wrapped_frame_unref(decoded_frame);
1197                        }
1198#if (LIBAVFORMAT_VERSION_MAJOR > 57) || ((LIBAVFORMAT_VERSION_MAJOR == 57) && (LIBAVFORMAT_VERSION_MINOR > 32))
1199                        int ret = avcodec_send_packet(c, &packet);
1200                        if (ret < 0 && ret != AVERROR(EAGAIN) && ret != AVERROR_EOF)
1201                        {
1202                            restart_audio_resampling = 1;
1203                            break;
1204                        }
1205                       
1206                        if (ret >= 0)
1207                        {
1208                            packet.size = 0;
1209                        }
1210                       
1211                        ret = avcodec_receive_frame(c, decoded_frame);
1212                        if (ret < 0)
1213                        {
1214                            if (ret != AVERROR(EAGAIN) && ret != AVERROR_EOF)
1215                            {
1216                                restart_audio_resampling = 1;
1217                                break;
1218                            }
1219                            else
1220                            {
1221                                continue;
1222                            }
1223                        }
1224#else
1225                        int32_t got_frame = 0;
1226                        int32_t len = avcodec_decode_audio4(c, decoded_frame, &got_frame, &packet);
1227                        if (len < 0)
1228                        {
1229                            ffmpeg_err("avcodec_decode_audio4: %d\n", len);
1230                            break;
1231                        }
1232
1233                        packet.data += len;
1234                        packet.size -= len;
1235                       
1236                        if (!got_frame)
1237                        {
1238                            continue;
1239                        }
1240#endif
1241                        int32_t e = 0;
1242                        if (!swr)
1243                        {
1244                            if(insert_pcm_as_lpcm)
1245                            {
1246                                out_sample_rate = 48000;
1247                            }
1248                            else
1249                            {
1250                                int32_t rates[] = { 48000, 96000, 192000, 44100, 88200, 176400, 0 };
1251                                int32_t *rate = rates;
1252                                int32_t in_rate = c->sample_rate;
1253                                while (*rate && ((*rate / in_rate) * in_rate != *rate) && (in_rate / *rate) * *rate != in_rate)
1254                                {
1255                                    rate++;
1256                                }
1257                                out_sample_rate = *rate ? *rate : 44100;
1258                            }
1259                           
1260                            swr = swr_alloc();
1261                            out_channels = c->channels;
1262                           
1263                            if (c->channel_layout == 0)
1264                            {
1265                                c->channel_layout = av_get_default_channel_layout( c->channels );
1266                            }
1267                            out_channel_layout = c->channel_layout;
1268                           
1269                            uint8_t downmix = stereo_software_decoder && out_channels > 2 ? 1 : 0;
1270#ifdef __sh__
1271                            // player2 won't play mono
1272                            if (out_channel_layout == AV_CH_LAYOUT_MONO)
1273                            {
1274                                downmix = 1;
1275                            }
1276#endif
1277                            if(downmix)
1278                            {
1279                                out_channel_layout = AV_CH_LAYOUT_STEREO_DOWNMIX;
1280                                out_channels = 2;
1281                            }
1282                           
1283                            av_opt_set_int(swr, "in_channel_layout",    c->channel_layout,      0);
1284                            av_opt_set_int(swr, "out_channel_layout",   out_channel_layout,     0);
1285                            av_opt_set_int(swr, "in_sample_rate",               c->sample_rate,         0);
1286                            av_opt_set_int(swr, "out_sample_rate",              out_sample_rate,        0);
1287                            av_opt_set_int(swr, "in_sample_fmt",                c->sample_fmt,          0);
1288                            av_opt_set_int(swr, "out_sample_fmt",               AV_SAMPLE_FMT_S16,      0);
1289       
1290
1291                            e = swr_init(swr);
1292                            if (e < 0)
1293                            {
1294                                ffmpeg_err("swr_init: %d (icl=%d ocl=%d isr=%d osr=%d isf=%d osf=%d\n",
1295                                    -e, (int32_t)c->channel_layout, (int32_t)out_channel_layout, c->sample_rate, out_sample_rate, c->sample_fmt, AV_SAMPLE_FMT_S16);
1296                                swr_free(&swr);
1297                                swr = NULL;
1298                            }
1299                        }
1300                       
1301                        uint8_t *output[8] = {NULL};
1302                        int32_t in_samples = decoded_frame->nb_samples;
1303                        int32_t out_samples = av_rescale_rnd(swr_get_delay(swr, c->sample_rate) + in_samples, out_sample_rate, c->sample_rate, AV_ROUND_UP);
1304                        e = av_samples_alloc(&output[0], NULL, out_channels, out_samples, AV_SAMPLE_FMT_S16, 1);
1305                        if (e < 0)
1306                        {
1307                            ffmpeg_err("av_samples_alloc: %d\n", -e);
1308                            continue;
1309                        }
1310                        int64_t next_in_pts = av_rescale(av_frame_get_best_effort_timestamp(decoded_frame),
1311                                         ((AVStream*) audioTrack->stream)->time_base.num * (int64_t)out_sample_rate * c->sample_rate,
1312                                         ((AVStream*) audioTrack->stream)->time_base.den);
1313                        int64_t next_out_pts = av_rescale(swr_next_pts(swr, next_in_pts),
1314                                         ((AVStream*) audioTrack->stream)->time_base.den,
1315                                         ((AVStream*) audioTrack->stream)->time_base.num * (int64_t)out_sample_rate * c->sample_rate);
1316                       
1317                        currentAudioPts = audioTrack->pts = pts = calcPts(cAVIdx, audioTrack->stream, next_out_pts);
1318                        out_samples = swr_convert(swr, &output[0], out_samples, (const uint8_t **) &decoded_frame->data[0], in_samples);
1319                       
1320                        //////////////////////////////////////////////////////////////////////
1321                        // Update pcmExtradata according to decode parameters
1322                        pcmExtradata.channels              = av_get_channel_layout_nb_channels(out_channel_layout);
1323                        pcmExtradata.bits_per_coded_sample = 16;
1324                        pcmExtradata.sample_rate           = out_sample_rate;
1325                        // The data described by the sample format is always in native-endian order
1326#ifdef WORDS_BIGENDIAN
1327                        pcmExtradata.ffmpeg_codec_id       = AV_CODEC_ID_PCM_S16BE;
1328#else
1329                        pcmExtradata.ffmpeg_codec_id       = AV_CODEC_ID_PCM_S16LE;
1330#endif
1331
1332                        //////////////////////////////////////////////////////////////////////
1333
1334                        avOut.data       = output[0];
1335                        avOut.len        = out_samples * sizeof(int16_t) * out_channels;
1336
1337                        avOut.pts        = pts;
1338                        avOut.extradata  = (unsigned char *) &pcmExtradata;
1339                        avOut.extralen   = sizeof(pcmExtradata);
1340                        avOut.frameRate  = 0;
1341                        avOut.timeScale  = 0;
1342                        avOut.width      = 0;
1343                        avOut.height     = 0;
1344                        avOut.type       = "audio";
1345
1346                        if (!context->playback->BackWard && Write(context->output->audio->Write, context, &avOut, pts) < 0)
1347                        {
1348                            ffmpeg_err("writing data to audio device failed\n");
1349                        }
1350                        av_freep(&output[0]);
1351                    }
1352                }
1353                else if (audioTrack->have_aacheader == 1)
1354                {
1355                    ffmpeg_printf(200, "write audio aac\n");
1356                    ffmpeg_printf(200, ">>>>>>> %x %x %x %x %x %x\n", packet.data[0], packet.data[1], packet.data[2], packet.data[3], packet.data[4], packet.data[5], packet.data[6]);
1357
1358                    avOut.data       = packet.data;
1359                    avOut.len        = packet.size;
1360                    avOut.pts        = pts;
1361                    avOut.extradata  = audioTrack->aacbuf;
1362                    avOut.extralen   = audioTrack->aacbuflen;
1363                    avOut.frameRate  = 0;
1364                    avOut.timeScale  = 0;
1365                    avOut.width      = 0;
1366                    avOut.height     = 0;
1367                    avOut.type       = "audio";
1368
1369                    if (!context->playback->BackWard && Write(context->output->audio->Write, context, &avOut, pts) < 0)
1370                    {
1371                        ffmpeg_err("(aac) writing data to audio device failed\n");
1372                    }
1373                }
1374                else
1375                {
1376                    avOut.data       = packet.data;
1377                    avOut.len        = packet.size;
1378                    avOut.pts        = pts;
1379                    avOut.extradata  = pAudioExtradata;
1380                    avOut.extralen   = audioExtradataSize;
1381                    avOut.frameRate  = 0;
1382                    avOut.timeScale  = 0;
1383                    avOut.width      = 0;
1384                    avOut.height     = 0;
1385                    avOut.type       = "audio";
1386
1387                    if (!context->playback->BackWard && Write(context->output->audio->Write, context, &avOut, pts) < 0)
1388                    {
1389                        ffmpeg_err("writing data to audio device failed\n");
1390                    }
1391                }
1392            }
1393            else if (subtitleTrack && (subtitleTrack->Id == pid))
1394            {
1395                int64_t duration = -1;
1396                int64_t pts = calcPts(cAVIdx, subtitleTrack->stream, packet.pts);
1397                AVStream *stream = subtitleTrack->stream;
1398               
1399                if (packet.duration != 0)
1400                {
1401                    // duration in milliseconds
1402                    duration = (int64_t)av_rescale(packet.duration, (int64_t)stream->time_base.num * 1000, stream->time_base.den);
1403                }
1404                else if(get_packet_duration(&packet) != 0 && get_packet_duration(&packet) != AV_NOPTS_VALUE )
1405                {
1406                    // duration in milliseconds
1407                    duration = (int64_t)av_rescale(get_packet_duration(&packet), (int64_t)stream->time_base.num * 1000, stream->time_base.den);
1408                }
1409
1410                if (duration > 0)
1411                {
1412//                  printf("[LIBEPLAYER3/FFMPEGThread] start\n");
1413
1414                    SubtitleOut_t subOut;
1415                    memset(&subOut, 0, sizeof(subOut));
1416                    subOut.trackId = pid;
1417                    subOut.data = (uint8_t *)packet.data;
1418                    subOut.pts = pts;
1419                    subOut.durationMS = duration;
1420                    //obi
1421                    tmptrackId = pid;
1422                    tmpdata = (uint8_t *)packet.data;
1423//                  tmpdata = (uint8_t *)&packet.data;
1424                    //tmplen;
1425                    tmppts = pts;
1426                    tmpduration = duration;
1427                    tmpdata = ostrcat(subOut.data, NULL, 0, 0);
1428
1429                    //*tmptype;
1430//                  printf("[LIBEPLAYER3/FFMPEGThread] set tmpdata=%s\n", tmpdata);
1431//                  printf("[LIBEPLAYER3/FFMPEGThread] set tmppts=%lld\n", tmppts);
1432//                  printf("[LIBEPLAYER3/FFMPEGThread] set tmpduration=%lld\n", tmpduration);
1433                    //obi (end)
1434
1435                    if (Write(context->output->subtitle->Write, context, &subOut, pts) < 0)
1436                    {
1437                        ffmpeg_err("writing data to teletext fifo failed\n");
1438                    }
1439                    //obi
1440                    char* tmpstr = NULL;
1441                    tmpstr = ostrcat(tmpstr, "duration=", 1, 0);
1442                    tmpstr = ostrcat(tmpstr, ollutoa(tmpduration), 1, 1);
1443                    tmpstr = ostrcat(tmpstr, ";pts=", 1, 0);;
1444                    tmpstr = ostrcat(tmpstr, ollutoa(tmppts), 1, 0);;
1445                    tmpstr = ostrcat(tmpstr, ";trackid=", 1, 0);;
1446                    tmpstr = ostrcat(tmpstr, oitoa(tmptrackId), 1, 0);
1447                    tmpstr = ostrcat(tmpstr, ";subtext=", 1, 0);;
1448                    tmpstr = ostrcat(tmpstr, tmpdata, 1, 0);;
1449
1450                    free(subtext), subtext = NULL;
1451                    subtext = ostrcat(subtext, tmpstr, 1, 0);
1452                    free(tmpstr), tmpstr = NULL;
1453
1454//                  tmpduration = 0;
1455                    tmppts = 0;
1456                    tmptrackId = 0;
1457
1458//                    printf("[LIBEPLAYER3/FFMPEGThread] set subtext: %s\n", subtext);
1459                    //obi (end)
1460                }
1461            }
1462        }
1463        else
1464        {
1465            if( 0 != ffmpegStatus )
1466            {
1467                static char errbuf[256];
1468               
1469                if( 0 == av_strerror(ffmpegStatus, errbuf, sizeof(errbuf)) )
1470                {
1471                    /* In this way we inform user about error within the core
1472                     */
1473                    printf("{\"log\":\"Frame read error: '%s'\"}\n", errbuf);
1474                }
1475               
1476                /*
1477                if( ffmpegStatus == AVERROR(EAGAIN) )
1478                {
1479                    continue;
1480                }
1481                */
1482                ffmpegStatus = 0;
1483            }
1484           
1485            if(!is_finish_timeout() && !context->playback->isTSLiveMode)
1486            {
1487                isWaitingForFinish = 1;
1488                update_finish_timeout();
1489                releaseMutex(__FILE__, __FUNCTION__,__LINE__);
1490                usleep(100000);
1491                continue;
1492            }
1493            else
1494            {
1495                uint8_t bEndProcess = 1;
1496                if (context->playback->isTSLiveMode)
1497                {
1498                    seek_target_bytes = 0;
1499                    do_seek_target_bytes = 1;
1500                    bEndProcess = 0;
1501                }
1502                else if( 1 == context->playback->isLoopMode )
1503                {
1504                    int64_t tmpLength = 0;
1505                    if( 0 == container_ffmpeg_get_length(context, &tmpLength) && tmpLength > 0 && get_play_pts() > 0)
1506                    {
1507#if defined(TS_BYTES_SEEKING) && TS_BYTES_SEEKING
1508                        if (avContextTab[0]->iformat->flags & AVFMT_TS_DISCONT)
1509                        {
1510                            seek_target_bytes = 0;
1511                            do_seek_target_bytes = 1;
1512                        }
1513                        else
1514#endif
1515                        {
1516                            seek_target_seconds = 0;
1517                            do_seek_target_seconds = 1;
1518                        }
1519                        bEndProcess = 0;
1520                        context->output->Command(context, OUTPUT_CLEAR, NULL);
1521                        context->output->Command(context, OUTPUT_PLAY, NULL);
1522                        printf("{\"log\":\"Loop mode: jump to the start.\"}\n");
1523                    }
1524                }
1525               
1526                // av_read_frame failed
1527                ffmpeg_err("no data ->end of file reached ? \n");
1528                wrapped_packet_unref(&packet);
1529                releaseMutex(__FILE__, __FUNCTION__,__LINE__);
1530                if( bEndProcess )
1531                {
1532                    break; // while
1533                }
1534                else
1535                {
1536                    continue;
1537                }
1538            }
1539        }
1540        wrapped_packet_unref(&packet);
1541        releaseMutex(__FILE__, __FUNCTION__,__LINE__);
1542    } /* while */
1543
1544    if (swr)
1545    {
1546        swr_free(&swr);
1547    }
1548   
1549    if (decoded_frame)
1550    {
1551        wrapped_frame_free(&decoded_frame);
1552    }
1553   
1554#if LIBAVCODEC_VERSION_INT >= AV_VERSION_INT(56, 34, 100)
1555    mpeg4p2_context_reset(&mpeg4p2_context);
1556    if (NULL != mpeg4p2_bsf_context)
1557    {
1558        av_bitstream_filter_close(mpeg4p2_bsf_context);
1559    }
1560#endif
1561
1562    hasPlayThreadStarted = 0;
1563    context->playback->isPlaying = 0;
1564    PlaybackDieNow(1);
1565    ffmpeg_printf(10, "terminating\n");
1566}
1567
1568/* **************************** */
1569/* Container part for ffmpeg    */
1570/* **************************** */
1571
1572static int32_t terminating = 0;
1573static int32_t interrupt_cb(void *ctx)
1574{
1575    PlaybackHandler_t *p = (PlaybackHandler_t *)ctx;
1576//obi
1577//    return p->abortRequested || PlaybackDieNow(0);
1578    return p->abortRequested;
1579//obi (end)
1580}
1581
1582#ifdef SAM_CUSTOM_IO
1583typedef struct CustomIOCtx_t
1584{
1585    FILE *pFile;
1586    FILE *pMoovFile;
1587    int64_t iOffset;
1588   
1589    char *szFile;
1590    uint64_t iFileSize;
1591    char *szMoovAtomFile;
1592    uint64_t iMoovAtomOffset;
1593} CustomIOCtx_t;
1594
1595CustomIOCtx_t* custom_io_tab[IPTV_AV_CONTEXT_MAX_NUM] = {NULL, NULL};
1596
1597int SAM_ReadFunc(void *ptr, uint8_t *buffer, int lSize)
1598{
1599    CustomIOCtx_t *io = (CustomIOCtx_t *)ptr;
1600    int ret = 0;
1601   
1602    if (!io->pMoovFile)
1603    {
1604        ret = (int)fread( (void *) buffer, (size_t) 1, (size_t) lSize, io->pFile );
1605    }
1606    else
1607    {
1608        if (io->iOffset < io->iMoovAtomOffset)
1609        {
1610            ret = (int)fread( (void *) buffer, (size_t) 1, (size_t) lSize, io->pFile );
1611            buffer += ret;
1612            lSize -= ret;
1613        }
1614       
1615        if (io->iOffset + ret >= io->iMoovAtomOffset)
1616        {
1617            if (ret)
1618            {
1619                if (fseeko(io->pMoovFile, io->iOffset + ret - io->iMoovAtomOffset, SEEK_SET))
1620                {
1621                    // something goes wrong
1622                    ffmpeg_err("fseeko on moov atom file fail \n");
1623                    lSize = 0;
1624                }
1625            }
1626           
1627            ret += (int)fread( (void *) buffer, (size_t) 1, (size_t) lSize, io->pMoovFile );
1628        }
1629       
1630        io->iOffset += ret;
1631    }
1632    return ret;
1633}
1634
1635// whence: SEEK_SET, SEEK_CUR, SEEK_END (like fseek) and AVSEEK_SIZE
1636int64_t SAM_SeekFunc(void *ptr, int64_t pos, int whence)
1637{   
1638    CustomIOCtx_t *io = (CustomIOCtx_t *)ptr;
1639    int64_t ret = -1;
1640    if (!io->pMoovFile)
1641    {
1642        if( AVSEEK_SIZE != whence )
1643        {
1644            ret = (int64_t)fseeko(io->pFile, (off_t)pos, whence);
1645            if(0 == ret)
1646            {
1647                ret = (int64_t)ftello(io->pFile);
1648            }
1649        }
1650    }
1651    else
1652    {
1653        switch(whence)
1654        {
1655            case SEEK_SET:
1656                ret = pos;
1657                break;
1658            case SEEK_CUR:
1659                ret += pos;
1660                break;
1661            case SEEK_END:
1662                ret = io->iFileSize + pos;
1663                break;
1664            case AVSEEK_SIZE:
1665                return io->iFileSize;
1666            default:
1667                return -1;
1668        }
1669       
1670        if (ret >= 0 && ret <= io->iFileSize)
1671        {
1672            if (ret < io->iMoovAtomOffset)
1673            {
1674                if(!fseeko(io->pFile, (off_t)ret, SEEK_SET))
1675                    io->iOffset = ret;
1676                else
1677                    ret = -1;
1678            }
1679            else
1680            {
1681                if(!fseeko(io->pMoovFile, (off_t)(ret - io->iMoovAtomOffset), SEEK_SET))
1682                    io->iOffset = ret;
1683                else
1684                    ret = -1;
1685            }
1686        }
1687        else
1688        {
1689            ret = -1;
1690        }
1691    }
1692    return ret;
1693}
1694
1695AVIOContext* container_ffmpeg_get_avio_context(CustomIOCtx_t *custom_io, size_t avio_ctx_buffer_size)
1696{
1697    if(strstr(custom_io->szFile, "file://") == custom_io->szFile)
1698        custom_io->szFile += 7;
1699   
1700    custom_io->pFile = fopen(custom_io->szFile, "rb");
1701    if(NULL == custom_io->pFile)
1702    {
1703        return NULL;
1704    }
1705   
1706    if (custom_io->szMoovAtomFile && custom_io->szMoovAtomFile[0] != '\0')
1707    {
1708        if(strstr(custom_io->szMoovAtomFile, "file://") == custom_io->szMoovAtomFile)
1709            custom_io->szMoovAtomFile += 7;
1710       
1711        custom_io->pMoovFile = fopen(custom_io->szMoovAtomFile, "rb");
1712        if(NULL == custom_io->pMoovFile)
1713        {
1714            fclose(custom_io->pFile);
1715            return NULL;
1716        }
1717    }
1718   
1719    AVIOContext *avio_ctx = NULL;
1720    uint8_t *avio_ctx_buffer = NULL;
1721   
1722    avio_ctx_buffer = av_malloc(avio_ctx_buffer_size);
1723    if (!avio_ctx_buffer)
1724    {
1725        return NULL;
1726    }
1727    avio_ctx = avio_alloc_context(avio_ctx_buffer, avio_ctx_buffer_size, 0, custom_io, &SAM_ReadFunc, NULL, &SAM_SeekFunc);
1728    if (!avio_ctx)
1729    {
1730        return NULL;
1731    }
1732    return avio_ctx;
1733}
1734#endif
1735
1736int32_t container_ffmpeg_init_av_context(Context_t *context, char *filename, uint64_t fileSize, char *moovAtomFile, uint64_t moovAtomOffset, int32_t AVIdx)
1737{
1738    int32_t err = 0;
1739    AVInputFormat *fmt = NULL;
1740    avContextTab[AVIdx] = avformat_alloc_context();
1741    avContextTab[AVIdx]->interrupt_callback.callback = interrupt_cb;
1742    avContextTab[AVIdx]->interrupt_callback.opaque = context->playback;
1743
1744#ifdef SAM_CUSTOM_IO
1745    if(0 == strstr(filename, "://") ||
1746       0 == strncmp(filename, "file://", 7))
1747    {
1748        AVIOContext *avio_ctx = NULL;
1749        custom_io_tab[AVIdx] = malloc(sizeof(CustomIOCtx_t));
1750        sizeof(custom_io_tab[AVIdx], 0x00, sizeof(CustomIOCtx_t));
1751       
1752        custom_io_tab[AVIdx]->szFile = filename;
1753        custom_io_tab[AVIdx]->iFileSize = fileSize;
1754        custom_io_tab[AVIdx]->szMoovAtomFile = moovAtomFile;
1755        custom_io_tab[AVIdx]->iMoovAtomOffset = moovAtomOffset;
1756       
1757        avio_ctx = container_ffmpeg_get_avio_context(custom_io_tab[AVIdx], 4096);
1758        if(avio_ctx)
1759        {
1760            avContextTab[AVIdx]->pb = avio_ctx;
1761            use_custom_io[AVIdx] = 1;
1762        }
1763        else
1764        {
1765            free(custom_io_tab[AVIdx]);
1766            custom_io_tab[AVIdx] = NULL;
1767            return cERR_CONTAINER_FFMPEG_OPEN;
1768        }
1769    }
1770#endif
1771
1772    AVDictionary **pavio_opts = NULL;
1773    eRTMPProtoImplType rtmpProtoImplType = RTMP_NONE;
1774    uint8_t numOfRTMPImpl = 0;
1775    if (0 == strncmp(filename, "ffrtmp", 6))
1776    {
1777        filename = filename + 2;
1778        rtmpProtoImplType = RTMP_NATIVE;
1779    }
1780   
1781    if (1 == rtmp_proto_impl)
1782    {
1783        rtmpProtoImplType = RTMP_NATIVE;
1784    }
1785    else if (2 == rtmp_proto_impl)
1786    {
1787        rtmpProtoImplType = RTMP_LIBRTMP;
1788    }
1789
1790    if (0 == strncmp(filename, "rtmp://", 7) ||
1791        0 == strncmp(filename, "rtmpe://", 8) ||
1792        0 == strncmp(filename, "rtmps://", 8) ||
1793        0 == strncmp(filename, "rtmpt://", 8) ||
1794        0 == strncmp(filename, "rtmpte://", 9) ||
1795        0 == strncmp(filename, "rtmpts://", 9))
1796    {
1797        /* At first we need to check which protocol
1798         * implementations we have
1799         */
1800        void *opaque = NULL;
1801        const char *protoName = NULL;
1802        uint8_t haveNativeProto = 0;
1803       
1804        while (protoName = avio_enum_protocols(&opaque, 1))
1805        {
1806            if (0 == strcmp("rtmp", protoName))
1807            {
1808                ++numOfRTMPImpl;
1809            }
1810            else if (0 == strcmp("ffrtmp", protoName))
1811            {
1812                // ffmpeg has patch to have both native and librtmp implementations
1813                ++numOfRTMPImpl;
1814                haveNativeProto = 2;
1815            }
1816            else if (0 == strncmp("rtmpts", protoName, 6))
1817            {
1818                // rtmpts is only available in native implementation
1819                // rtmpts is listed after rtmp
1820                haveNativeProto = 1;
1821            }
1822        }
1823       
1824        if (haveNativeProto > 0)
1825        {
1826            if (numOfRTMPImpl > 1) // we have both
1827            {
1828                if (rtmpProtoImplType == RTMP_NONE)
1829                {
1830                    /* if we have both impl, we will prefer native
1831                     * unless uri contain param wich can be understandable
1832                     * only by librtmp
1833                     */
1834                    if (strstr(filename, " token=") ||
1835                        strstr(filename, " jtv="))
1836                    {
1837                        rtmpProtoImplType = RTMP_LIBRTMP;
1838                    }
1839                    else
1840                    {
1841                        rtmpProtoImplType = RTMP_NATIVE;
1842                    }
1843                }
1844            }
1845            else
1846            {
1847                rtmpProtoImplType = RTMP_NATIVE;
1848            }
1849        }
1850        else
1851        {
1852            rtmpProtoImplType = RTMP_LIBRTMP;
1853        }
1854       
1855        if (RTMP_NATIVE == rtmpProtoImplType)
1856        {
1857            char *baseUri = strdup(filename);
1858            char *token  = NULL;
1859           
1860            // check if uri have additional params
1861            if ((token = strtok(baseUri, " ")) != NULL )
1862            {
1863                char *conn = malloc(strlen(filename));
1864                char *swfUrl = malloc(strlen(filename));
1865                char *swfVfy = malloc(strlen(filename));
1866                char *poseq, *key, *value;
1867                conn[0] = '\0';
1868                swfUrl[0] = '\0';
1869                swfVfy[0] = '\0';
1870                token = NULL;
1871                while((token = strtok(token, " ")) != NULL)
1872                {
1873                    if ((poseq = strchr(token, '=')) != NULL)
1874                    {
1875                        *poseq = '\0';
1876                        key = token;
1877                        value = poseq + 1;
1878                        ffmpeg_printf(20, "rtmp_key = \"%s\", rtmp_value = \"%s\"\n", key, value);
1879                        /* translate librtmp connection parameters to ffmpeg ones routin provided by @mx3L
1880                         *
1881                         * librtmp parameters     - https://rtmpdump.mplayerhq.hu/librtmp.3.html
1882                         * ffmpeg rtmp parameters - https://ffmpeg.org/ffmpeg-protocols.html#rtmp
1883                         */
1884                        if (!strcasecmp(key, "app"))
1885                        {
1886                            av_dict_set(&avio_opts, "rtmp_app", value, 0);
1887                        }
1888                        else if (!strcasecmp(key, "conn"))
1889                        {
1890                            if (conn[0] != '\0')
1891                            {
1892                                strcat(conn, " ");
1893                            }
1894                            strcat(conn, value);
1895                        }
1896                        else if (!strcasecmp(key, "buffer"))
1897                        {
1898                            av_dict_set(&avio_opts, "rtmp_buffer", value, 0);
1899                        }
1900                        else if (!strcasecmp(key, "flashVer"))
1901                        {
1902                            av_dict_set(&avio_opts, "rtmp_flashver", value, 0);
1903                        }
1904                        else if (!strcasecmp(key, "live"))
1905                        {
1906                            av_dict_set(&avio_opts, "rtmp_live", value, 0);
1907                        }
1908                        else if (!strcasecmp(key, "pageUrl"))
1909                        {
1910                            av_dict_set(&avio_opts, "rtmp_pageurl", value, 0);
1911                        }
1912                        else if (!strcasecmp(key, "playpath"))
1913                        {
1914                            av_dict_set(&avio_opts, "rtmp_playpath", value, 0);
1915                        }
1916                        else if (!strcasecmp(key, "subscribe"))
1917                        {
1918                            av_dict_set(&avio_opts, "rtmp_subscribe", value, 0);
1919                        }
1920                        else if (!strcasecmp(key, "swfUrl"))
1921                        {
1922                            strcpy(swfUrl, value);
1923                        }
1924                        // ffmpeg expects this value to contain url to player swf
1925                        // not a 1|0|TRUE like librtmp
1926                        else if (!strcasecmp(key, "swfVfy"))
1927                        {
1928                            strcpy(swfVfy, value);
1929                        }
1930                        else if (!strcasecmp(key, "tcUrl"))
1931                        {
1932                            av_dict_set(&avio_opts, "rtmp_tcurl", value, 0);
1933                        }
1934                        // timeout is ment for incoming connections
1935                        else if (!strcasecmp(key, "timeout"))
1936                        {
1937                        }
1938                        else
1939                        {
1940                            // threat as direct options
1941                            // for example rtmp_swfhash, rtmp_swfsize
1942                            av_dict_set(&avio_opts, key, value, 0);
1943                        }
1944                    }
1945                    token = NULL;
1946                }
1947               
1948                if (conn[0] != '\0')
1949                {
1950                    av_dict_set(&avio_opts, "rtmp_conn", conn, 0);
1951                }
1952                free(conn);
1953
1954                if (swfUrl[0] != '\0')
1955                {
1956                    if (swfVfy[0] == '1' || !strncasecmp(swfVfy, "true", 4))
1957                    {
1958                        av_dict_set(&avio_opts, "rtmp_swfverify", swfUrl, 0);
1959                    }
1960                    else
1961                    {
1962                        av_dict_set(&avio_opts, "rtmp_swfurl", swfUrl, 0);
1963                    }
1964                }
1965                free(swfUrl);
1966                free(swfVfy);
1967            }
1968           
1969            if (2 == haveNativeProto)
1970            {
1971                filename = malloc(strlen(baseUri) + 2 + 1);
1972                strncpy(filename, "ff", 2);
1973                strcpy(filename+2, baseUri);
1974                free(baseUri);
1975                // memory leak, only once, so does not matter
1976            }
1977            else
1978            {
1979                filename = baseUri;
1980                // memory leak, only once, so does not matter
1981            }
1982        }
1983    }
1984    else if(0 == strncmp(filename, "http://", 7) ||
1985            0 == strncmp(filename, "https://", 8))
1986    {
1987        av_dict_set(&avio_opts, "timeout", "20000000", 0); //20sec
1988//obi
1989                char* cookie = NULL, *tmpstr1 = NULL, *tmpstr2 = NULL, *tmpstr3 = NULL, *tmpstr4 = NULL, *headers = NULL, *useragent = NULL;
1990                int count = 0, count1 = 0, count2 = 0, count3 = 0, i = 0, i1 = 0, i2 = 0, i3 = 0, usetslivemode = 0;
1991
1992                struct splitstr* ret1 = NULL;
1993                struct splitstr* ret2 = NULL;
1994
1995                ffmpeg_printf(10, "check cookie\n");
1996
1997                if(file_exist("/mnt/network/cookies"))
1998                {
1999                        tmpstr1 = readfiletomem("/mnt/network/cookies", 1);
2000                        if(tmpstr1 != NULL)
2001                        {
2002                                tmpstr1 = string_replace_all("\t", " ", tmpstr1, 1);
2003                                string_strip_whitechars(tmpstr1);
2004                                strstrip(tmpstr1);
2005                                ret1 = strsplit(tmpstr1, "\n", &count);
2006                                for(i = 0; i < count; i++)
2007                                {
2008                                        count2 = 0;
2009                                        tmpstr2 = ostrcat((&ret1[i])->part, NULL, 0, 0);
2010                                        ret2 = strsplit(tmpstr2, " ", &count2);
2011
2012                                        if(count2 == 6)
2013                                        {
2014                                                cookie = ostrcat(cookie, (&ret2[4])->part, 1, 0);
2015                                                cookie = ostrcat(cookie, "=", 1, 0);
2016                                                cookie = ostrcat(cookie, (&ret2[5])->part, 1, 0);
2017                                                cookie = ostrcat(cookie, "; domain=", 1, 0);
2018                                                cookie = ostrcat(cookie, (&ret2[0])->part, 1, 0);
2019                                                cookie = ostrcat(cookie, "; path=", 1, 0);
2020                                                cookie = ostrcat(cookie, (&ret2[2])->part, 1, 0); 
2021                                                cookie = ostrcat(cookie, "\n", 1, 0);
2022                                        }
2023
2024                                        if(count2 == 7)
2025                                        {
2026                                                cookie = ostrcat(cookie, (&ret2[5])->part, 1, 0);
2027                                                cookie = ostrcat(cookie, "=", 1, 0);
2028                                                cookie = ostrcat(cookie, (&ret2[6])->part, 1, 0);
2029                                                cookie = ostrcat(cookie, "; domain=", 1, 0);
2030                                                cookie = ostrcat(cookie, (&ret2[0])->part, 1, 0);
2031                                                cookie = ostrcat(cookie, "; path=", 1, 0);
2032                                                cookie = ostrcat(cookie, (&ret2[2])->part, 1, 0); 
2033                                                cookie = ostrcat(cookie, "\n", 1, 0);
2034                                        }
2035                                       
2036                                        free(ret2), ret2 = NULL;
2037                                        free(tmpstr2), tmpstr2 = NULL;
2038                                }
2039                                free(ret1), ret1 = NULL;
2040                                free(tmpstr1), tmpstr1 = NULL;
2041                        }
2042                }
2043                if(cookie != NULL)
2044                {
2045                        ffmpeg_printf(10, "set cookies: %s\n", cookie);
2046                av_dict_set(&avio_opts, "cookies", cookie, 0);
2047                }
2048                else
2049                        ffmpeg_printf(10, "skip set cookies : %s\n", cookie);
2050
2051                ffmpeg_printf(10, "check user-agent and header\n");
2052
2053                if (ostrstr(filename, "&tslivemode=1") != NULL)
2054                        usetslivemode = 1;
2055
2056                if(ostrstr(filename, "|") != NULL)
2057                {
2058                        tmpstr1 = ostrcat(filename, NULL, 0, 0);
2059                        ret1 = strsplit(tmpstr1, "|", &count1);
2060               
2061                        if(ret1 != NULL)
2062                        {
2063                                for(i1 = 0; i1 < count1; i1++)
2064                                {
2065                                        if(i1 == 0) continue;
2066
2067                                        count2 = 0;
2068                                        i2 = 0;
2069
2070                                        tmpstr2 = ostrcat(ret1[i1].part, NULL, 0, 0);
2071                                        ret2 = strsplit(tmpstr2, "&", &count2);
2072
2073                                        if(ret2 != NULL)
2074                                        {
2075                                                for(i2 = 0; i2 < count2; i2++)
2076                                                {
2077                                                        count3 = 0;
2078                                                        i3 = 0;
2079                                                        struct splitstr* ret3 = NULL;
2080                                                        tmpstr3 = ostrcat(ret2[i2].part, NULL, 0, 0);
2081                                                        ret3 = strsplit(tmpstr3, "=", &count3);
2082                                       
2083                                                        if(ret3 != NULL && count3 > 0)
2084                                                        {
2085                                                                int max = count3 - 1;
2086                                                                for(i3 = 0; i3 < max; i3++)
2087                                                                {
2088                                                                        if(ostrcmp("User-Agent", ret3[i3].part) == 0)
2089                                                                        {
2090                                                                                av_dict_set(&avio_opts, "user-agent", ret3[i3 + 1].part, 0);
2091                                                                                ffmpeg_printf(10, "set user-agent: %s\n", ret3[i3 + 1].part);
2092                                                                                useragent = ostrcat(useragent, ret3[i3 + 1].part, 1, 0);
2093                                                                        }
2094                                                                        else
2095                                                                        {
2096                                                                            headers = ostrcat(headers, ret3[i3].part, 1, 0);
2097                                                                            headers = ostrcat(headers, ": ", 1, 0);
2098                                                                            headers = ostrcat(headers, ret3[i3 + 1].part, 1, 0);
2099                                                                            headers = ostrcat(headers, "\r\n", 1, 0);
2100                                                                        }
2101                                                                }
2102                                                        }
2103                                                        free(ret3), ret3 = NULL;
2104                                                        free(tmpstr3), tmpstr3 = NULL;
2105                                                }
2106                                        }
2107                                        free(ret2), ret2 = NULL;
2108                                        free(tmpstr2), tmpstr2 = NULL;
2109                                }
2110
2111                            if(headers != NULL)
2112                                {
2113                                        headers = string_replace_all("%3D", "=", headers, 1);
2114                                        headers = string_replace_all("%26", "&", headers, 1);
2115                                av_dict_set(&avio_opts, "headers", headers, 0);
2116                                        ffmpeg_printf(10, "set headers: %s\n", headers);
2117                                }
2118                                else
2119                                        ffmpeg_printf(10, "skip set headers: %s\n", headers);
2120
2121                            if(useragent == NULL)
2122                                        ffmpeg_printf(10, "skip set user-agent: %s\n", headers);
2123                        }
2124
2125                        free(useragent), useragent = NULL;
2126                        free(headers), headers = NULL;
2127                        free(ret1), ret1 = NULL;       
2128                        free(tmpstr1), tmpstr1 = NULL;
2129                        stringreplacechar(filename, '|', '\0');         
2130                        ffmpeg_printf(10, "changed filename: %s\n", filename);
2131
2132                }
2133                ffmpeg_printf(10, "check tslivemode\n");
2134
2135//              if (ostrstr(filename, ".m3u8") != NULL)
2136                if (usetslivemode == 1)
2137                {
2138                        ffmpeg_printf(10, "set tslivemode\n");
2139                        context->playback->isTSLiveMode = 1;
2140                }
2141//obi (end)
2142
2143        av_dict_set(&avio_opts, "reconnect", "1", 0);
2144        if (context->playback->isTSLiveMode) // special mode for live TS stream with skip packet
2145        {
2146            av_dict_set(&avio_opts, "seekable", "0", 0);
2147            av_dict_set(&avio_opts, "reconnect_at_eof", "1", 0);
2148            av_dict_set(&avio_opts, "reconnect_streamed", "1", 0);
2149        }
2150    }
2151
2152    pavio_opts = &avio_opts;
2153   
2154    if ((err = avformat_open_input(&avContextTab[AVIdx], filename, fmt, pavio_opts)) != 0)
2155    {
2156        if (rtmp_proto_impl == 0 && //err == AVERROR_UNKNOWN &&
2157            rtmpProtoImplType == RTMP_NATIVE &&
2158            numOfRTMPImpl > 1)
2159        {
2160            // retry with librtmp
2161            err = avformat_open_input(&avContextTab[AVIdx], filename+2, fmt, pavio_opts);
2162            // filename2 - another memory leak, and also only once, so does not matter
2163        }
2164       
2165        if (err != 0)
2166        {
2167            char error[512];
2168
2169            ffmpeg_err("avformat_open_input failed %d (%s)\n", err, filename);
2170            av_strerror(err, error, 512);
2171            fprintf(stderr, "{\"FF_ERROR\":{\"msg\":\"%s\",\"code\":%i}}\n", error, err);
2172
2173            if(avio_opts != NULL)
2174            {
2175                av_dict_free(&avio_opts);
2176            }
2177
2178            //obi
2179            ffmpeg_buf_free();
2180            //obi (end)
2181
2182            releaseMutex(__FILE__, __FUNCTION__,__LINE__);
2183            return cERR_CONTAINER_FFMPEG_OPEN;
2184        }
2185    }
2186
2187    avContextTab[AVIdx]->iformat->flags |= AVFMT_SEEK_TO_PTS;
2188    avContextTab[AVIdx]->flags = AVFMT_FLAG_GENPTS;
2189
2190    if (context->playback->noprobe)
2191    {
2192        wrapped_set_max_analyze_duration(avContextTab[AVIdx], 1);
2193    }
2194
2195    ffmpeg_printf(20, "find_streaminfo\n");
2196
2197    if (avformat_find_stream_info(avContextTab[AVIdx], NULL) < 0)
2198    {
2199        ffmpeg_err("Error avformat_find_stream_info\n");
2200    }
2201
2202//for buffered io
2203    if(avContextTab[AVIdx] != NULL && avContextTab[AVIdx]->pb != NULL && !context->playback->isTSLiveMode)
2204    {
2205        ffmpeg_real_read_org = avContextTab[AVIdx]->pb->read_packet;
2206       
2207        if(0 ==AVIdx && strstr(filename, "://") != 0 &&
2208           strncmp(filename, "file://", 7) != 0)
2209        {
2210            if(ffmpeg_buf_size > 0 && ffmpeg_buf_size > FILLBUFDIFF + FILLBUFPAKET)
2211            {
2212                if(avContextTab[AVIdx] != NULL && avContextTab[AVIdx]->pb != NULL)
2213                {
2214                    ffmpeg_buf = av_malloc(ffmpeg_buf_size);
2215
2216                    if(ffmpeg_buf != NULL)
2217                    {
2218                        ffmpeg_printf(10, "buffer size=%d\n", ffmpeg_buf_size);
2219                       
2220                        ffmpeg_read_org = avContextTab[AVIdx]->pb->read_packet;
2221                        avContextTab[AVIdx]->pb->read_packet = ffmpeg_read;
2222                        ffmpeg_seek_org = avContextTab[AVIdx]->pb->seek;
2223                        avContextTab[AVIdx]->pb->seek = ffmpeg_seek;
2224                        ffmpeg_buf_read = ffmpeg_buf;
2225                        ffmpeg_buf_write = ffmpeg_buf;
2226
2227                        //fill buffer
2228                        ffmpeg_filler(context, -1, NULL, 0);
2229                        ffmpeg_start_fillerTHREAD(context);
2230                    }
2231                }
2232            }
2233        }
2234        else if (progressive_playback)
2235        {
2236            avContextTab[AVIdx]->pb->read_packet = ffmpeg_read_wrapper;
2237        }
2238    }
2239//for buffered io (end)
2240   
2241    return 0;
2242}
2243
2244int32_t container_ffmpeg_init(Context_t *context, PlayFiles_t *playFilesNames)
2245{
2246    int32_t err = 0;
2247
2248    ffmpeg_printf(10, ">\n");
2249
2250    //obi
2251    ffmpeg_buf_free();
2252    //obi (end)
2253
2254    if (playFilesNames == NULL)
2255    {
2256        ffmpeg_err("playFilesNames NULL\n");
2257        return cERR_CONTAINER_FFMPEG_NULL;
2258    }
2259   
2260    if (playFilesNames->szFirstFile == NULL)
2261    {
2262        ffmpeg_err("playFilesNames->szFirstFile NULL\n");
2263        return cERR_CONTAINER_FFMPEG_NULL;
2264    }
2265
2266    if (context == NULL)
2267    {
2268        ffmpeg_err("context NULL\n");
2269        return cERR_CONTAINER_FFMPEG_NULL;
2270    }
2271
2272    ffmpeg_printf(10, "filename %s\n", playFilesNames->szFirstFile);
2273    if(playFilesNames->szSecondFile)
2274    {
2275        ffmpeg_printf(10, "second filename %s\n", playFilesNames->szSecondFile);
2276    }
2277
2278    if (isContainerRunning)
2279    {
2280        ffmpeg_err("ups already running?\n");
2281        releaseMutex(__FILE__, __FUNCTION__,__LINE__);
2282        return cERR_CONTAINER_FFMPEG_RUNNING;
2283    }
2284
2285    /* initialize ffmpeg */
2286    avcodec_register_all();
2287    av_register_all();
2288    avformat_network_init();
2289
2290//obi
2291    char* tmpstr = NULL;
2292    tmpstr = readfiletomem("/mnt/config/titan.cfg", 1);
2293    if(ostrstr(tmpstr, "debuglevel=99") != NULL)
2294        av_log_set_level( AV_LOG_DEBUG );
2295    else
2296        av_log_set_callback(ffmpeg_silen_callback);
2297    free(tmpstr), tmpstr = NULL;
2298//obi (end)
2299    // SULGE DEBUG ENABLED
2300    // make ffmpeg silen
2301    //av_log_set_level( AV_LOG_DEBUG );
2302    //av_log_set_callback(ffmpeg_silen_callback);
2303 
2304    context->playback->abortRequested = 0;
2305    int32_t res = container_ffmpeg_init_av_context(context, playFilesNames->szFirstFile, playFilesNames->iFirstFileSize, \
2306                                                   playFilesNames->szFirstMoovAtomFile, playFilesNames->iFirstMoovAtomOffset, 0);
2307    if(0 != res)
2308    {
2309        return res;
2310    }
2311
2312    if(playFilesNames->szSecondFile && playFilesNames->szSecondFile[0] != '\0')
2313    {
2314        res = container_ffmpeg_init_av_context(context, playFilesNames->szSecondFile, playFilesNames->iSecondFileSize, \
2315                                               playFilesNames->szSecondMoovAtomFile, playFilesNames->iSecondMoovAtomOffset, 1);
2316    }
2317   
2318    if(0 != res)
2319    {
2320        return res;
2321    }
2322   
2323    terminating = 0;
2324    latestPts = 0;
2325    isContainerRunning = 1;
2326    res = container_ffmpeg_update_tracks(context, playFilesNames->szFirstFile, 1);
2327
2328    //obi
2329    //ReadSubtitles(context, playFilesNames->szFirstFile);
2330    //obi (end)
2331    return res;
2332}
2333
2334int32_t container_ffmpeg_update_tracks(Context_t *context, char *filename, int32_t initial)
2335{
2336    Track_t *currAudioTrack = NULL;
2337    Track_t *currSubtitleTrack = NULL;
2338    uint32_t addedVideoTracksCount = 0;
2339   
2340    if (terminating)
2341    {
2342        return cERR_CONTAINER_FFMPEG_NO_ERROR;
2343    }
2344   
2345    getMutex(__FILE__, __FUNCTION__,__LINE__);
2346   
2347    if (initial && context->manager->subtitle)
2348    {
2349        context->manager->subtitle->Command(context, MANAGER_GET_TRACK, &currSubtitleTrack);
2350    }
2351
2352    if (context->manager->audio)
2353    {
2354        context->manager->audio->Command(context, MANAGER_GET_TRACK, &currAudioTrack);
2355    }
2356
2357    if (context->manager->video)
2358    {
2359        context->manager->video->Command(context, MANAGER_INIT_UPDATE, NULL);
2360    }
2361   
2362    if (context->manager->audio)
2363    {
2364        context->manager->audio->Command(context, MANAGER_INIT_UPDATE, NULL);
2365    }
2366   
2367#if 0
2368    if (context->manager->subtitle)
2369    {
2370        context->manager->subtitle->Command(context, MANAGER_INIT_UPDATE, NULL);
2371    }
2372#endif
2373
2374    ffmpeg_printf(20, "dump format\n");
2375    av_dump_format(avContextTab[0], 0, filename, 0);
2376   
2377   
2378    uint32_t cAVIdx = 0;
2379    for(cAVIdx=0; cAVIdx<IPTV_AV_CONTEXT_MAX_NUM; cAVIdx+=1)
2380    {
2381        if(NULL == avContextTab[cAVIdx])
2382        {
2383            break;
2384        }
2385        AVFormatContext *avContext = avContextTab[cAVIdx];
2386        uint32_t *stream_index = NULL;
2387        uint32_t nb_stream_indexes = 0;
2388       
2389        ffmpeg_printf(1, "cAVIdx[%d]: number of streams: %d\n", cAVIdx, avContext->nb_streams);
2390       
2391        if (avContext->nb_programs > 0)
2392        {
2393            uint32_t n = 0;
2394            ffmpeg_printf(1, "cAVIdx[%d]: stream with multi programs: num of programs %d\n", cAVIdx, avContext->nb_programs);
2395            for (n = 0; n < avContext->nb_programs && (0 == nb_stream_indexes || stream_index == NULL); n++)
2396            {
2397                AVProgram *p = avContext->programs[n];
2398                if (p->nb_stream_indexes)
2399                {
2400                    if (g_sel_program_id > 0)
2401                    {
2402                        if (g_sel_program_id == p->id)
2403                        {
2404                            stream_index = p->stream_index;
2405                            nb_stream_indexes = p->nb_stream_indexes;
2406                            ffmpeg_printf(1, "cAVIdx[%d]: select PROGRAM ID: %d\n", cAVIdx, (int32_t)p->id);
2407                            break;
2408                        }
2409                    }
2410                    else
2411                    {
2412                        uint32_t m = 0;
2413                        for (m = 0; m < p->nb_stream_indexes; m++)
2414                        {
2415                            AVStream *s = avContext->streams[p->stream_index[m]];
2416                            if (get_codecpar(s)->codec_type == AVMEDIA_TYPE_VIDEO && get_codecpar(s)->width > 0)
2417                            {
2418                                ffmpeg_printf(1, "cAVIdx[%d]: PROGRAM ID: %d, width [%d]\n", cAVIdx, (int32_t)p->id, (int32_t)get_codecpar(s)->width);
2419                                stream_index = p->stream_index;
2420                                nb_stream_indexes = p->nb_stream_indexes;
2421                                break;
2422                            }
2423                        }
2424                    }
2425                }
2426            }
2427        }
2428       
2429        int32_t n = 0;
2430        for (n = 0; n < avContext->nb_streams; n++)
2431        {
2432            Track_t track;
2433            AVStream *stream = avContext->streams[n];
2434            int32_t version = 0;
2435            char *encoding = NULL;
2436           
2437            if (nb_stream_indexes > 0 && stream_index != NULL)
2438            {
2439                uint32_t isStreamFromSelProg = 0;
2440                uint32_t m = 0;
2441                for (m = 0; m < nb_stream_indexes; m++)
2442                {
2443                    if (n == stream_index[m])
2444                    {
2445                        isStreamFromSelProg = 1;
2446                        break;
2447                    }
2448                }
2449               
2450                if (!isStreamFromSelProg) {
2451                    stream->discard = AVDISCARD_ALL;
2452                    ffmpeg_printf(1, "cAVIdx[%d]: add DISCARD flag to  stream index[%d]\n", cAVIdx, stream->index);
2453                    continue; // skip this stream
2454                }
2455            }
2456
2457            encoding = Codec2Encoding((int32_t)get_codecpar(stream)->codec_id, (int32_t)get_codecpar(stream)->codec_type, \
2458                                      (uint8_t *)get_codecpar(stream)->extradata, \
2459                                      (int)get_codecpar(stream)->extradata_size, \
2460                                      (int)get_codecpar(stream)->profile, &version);
2461           
2462            if(encoding != NULL && !strncmp(encoding, "A_IPCM", 6) && insert_pcm_as_lpcm)
2463            {
2464                encoding = "A_LPCM";
2465            }
2466
2467            if (encoding != NULL)
2468            {
2469               ffmpeg_printf(1, "%d. encoding = %s - version %d\n", n, encoding, version);
2470            }
2471
2472            if (!stream->id)
2473            {
2474                stream->id = n;
2475            }
2476
2477            /* some values in track are unset and therefor copyTrack segfaults.
2478             * so set it by default to NULL!
2479             */
2480            memset(&track, 0, sizeof(track));
2481            track.AVIdx = cAVIdx;
2482
2483            switch (get_codecpar(stream)->codec_type)
2484            {
2485            case AVMEDIA_TYPE_VIDEO:
2486                ffmpeg_printf(10, "CODEC_TYPE_VIDEO %d\n", get_codecpar(stream)->codec_type);
2487                stream->discard = AVDISCARD_ALL; /* by default we discard all video streams */
2488                if (encoding != NULL)
2489                {
2490                    track.type           = eTypeES;
2491                    track.version        = version;
2492
2493                    track.width          = get_codecpar(stream)->width;
2494                    track.height         = get_codecpar(stream)->height;
2495                   
2496                    /* We will return here PAR (Pixel Aspect Ratio) client need to calculate DAR(Display Aspect Ratio)
2497                     * example: PAR 64:45 DAR 16:9
2498                     *          Resolution 720x576
2499                     * Display aspect ratio = (720*64)/(576*45) = 16/9
2500                     * 0:1 is the value for invalid/unset aspect ratio -> https://trac.ffmpeg.org/ticket/3798
2501                     */
2502                    track.aspect_ratio_num = stream->sample_aspect_ratio.num;
2503                    track.aspect_ratio_den = stream->sample_aspect_ratio.den;
2504                    if (0 == track.aspect_ratio_num  || 0 == track.aspect_ratio_den)
2505                    {
2506                        track.aspect_ratio_num = get_codecpar(stream)->sample_aspect_ratio.num;
2507                        track.aspect_ratio_den = get_codecpar(stream)->sample_aspect_ratio.den;
2508                    }
2509
2510                    track.extraData      = get_codecpar(stream)->extradata;
2511                    track.extraSize      = get_codecpar(stream)->extradata_size;
2512
2513                    track.aacbuf         = 0;
2514                    track.have_aacheader = -1;
2515                   
2516                    AVRational rateRational = get_frame_rate(stream);
2517                    if (rateRational.den!=0)
2518                    {
2519                        track.frame_rate = (uint32_t)(1000 * (int64_t)(rateRational.num) / (int64_t)(rateRational.den));
2520                    }
2521                   
2522                    /* fixme: revise this */
2523                    if (track.frame_rate < 23970)
2524                    {
2525                        track.TimeScale = 1001;
2526                    }
2527                    else
2528                    {
2529                        track.TimeScale = 1000;
2530                    }
2531                   
2532                    ffmpeg_printf(10, "bit_rate       [%d]\n", get_codecpar(stream)->bit_rate);
2533                    ffmpeg_printf(10, "time_base.den  [%d]\n", stream->time_base.den);
2534                    ffmpeg_printf(10, "time_base.num  [%d]\n", stream->time_base.num);
2535                    ffmpeg_printf(10, "width          [%d]\n", get_codecpar(stream)->width);
2536                    ffmpeg_printf(10, "height         [%d]\n", get_codecpar(stream)->height);
2537                    ffmpeg_printf(10, "frame_rate num [%d]\n", rateRational.num);
2538                    ffmpeg_printf(10, "frame_rate den [%d]\n", rateRational.den);
2539
2540                    ffmpeg_printf(10, "frame_rate     [%u]\n", track.frame_rate);
2541                    ffmpeg_printf(10, "TimeScale      [%d]\n", track.TimeScale);
2542
2543                    track.Name      = "und";
2544                    track.Encoding  = encoding;
2545                    track.stream    = stream;
2546                    track.Id        = ((AVStream *) (track.stream))->id;
2547
2548                    track.duration = (int64_t)av_rescale(stream->duration, (int64_t)stream->time_base.num * 1000, stream->time_base.den);
2549                    if(stream->duration == AV_NOPTS_VALUE || 0 == strncmp(avContext->iformat->name, "dash", 4))
2550                    {
2551                        ffmpeg_printf(10, "Stream has no duration so we take the duration from context\n");
2552                        track.duration = (int64_t) avContext->duration / 1000;
2553                    }
2554                   
2555                    if (context->manager->video)
2556                    {
2557                        if (get_codecpar(stream)->codec_id == AV_CODEC_ID_MPEG4)
2558                        {
2559                            track.avCodecCtx = wrapped_avcodec_get_context(cAVIdx, stream);
2560                        }
2561                        ffmpeg_printf(1, "cAVIdx[%d]: MANAGER_ADD track VIDEO\n");
2562                        if( context->manager->video->Command(context, MANAGER_ADD, &track) < 0)
2563                        {
2564                            /* konfetti: fixme: is this a reason to return with error? */
2565                            ffmpeg_err("failed to add track %d\n", n);
2566                        }
2567                        else
2568                        {
2569                            if (addedVideoTracksCount == 0) /* at now we can handle only first video track */
2570                            {
2571                                stream->discard = AVDISCARD_DEFAULT;
2572                            }
2573                            addedVideoTracksCount += 1;
2574                        }
2575                    }
2576                }
2577                else
2578                {
2579                    ffmpeg_err("codec type video but codec unknown %d\n", get_codecpar(stream)->codec_id);
2580                }
2581                break;
2582            case AVMEDIA_TYPE_AUDIO:
2583                ffmpeg_printf(10, "CODEC_TYPE_AUDIO %d\n",get_codecpar(stream)->codec_type);
2584                stream->discard = AVDISCARD_ALL;
2585                if (encoding != NULL)
2586                {
2587                    AVDictionaryEntry *lang;
2588                    track.type = eTypeES;
2589
2590                    lang = av_dict_get(stream->metadata, "language", NULL, 0);
2591
2592                    track.Name = lang ? lang->value : "und";
2593
2594                    ffmpeg_printf(10, "Language %s\n", track.Name);
2595
2596                    track.Encoding       = encoding;
2597                    track.stream         = stream;
2598                    track.Id             = ((AVStream *) (track.stream))->id;
2599                    track.aacbuf         = 0;
2600                    track.have_aacheader = -1;
2601
2602                    track.duration       = (int64_t)av_rescale(stream->duration, (int64_t)stream->time_base.num * 1000, stream->time_base.den);
2603                    if(stream->duration == AV_NOPTS_VALUE)
2604                    {
2605                        ffmpeg_printf(10, "Stream has no duration so we take the duration from context\n");
2606                        track.duration = (int64_t) avContext->duration / 1000;
2607                    }
2608                   
2609                    if(!strncmp(encoding, "A_IPCM", 6) || !strncmp(encoding, "A_LPCM", 6))
2610                    {
2611                        track.inject_as_pcm = 1;
2612                        track.avCodecCtx = wrapped_avcodec_get_context(cAVIdx, stream);
2613                        if (track.avCodecCtx)
2614                        {
2615                            ffmpeg_printf(10, " Handle inject_as_pcm = %d\n", track.inject_as_pcm);
2616
2617                            AVCodec *codec = avcodec_find_decoder(get_codecpar(stream)->codec_id);
2618
2619                            int errorCode = avcodec_open2(track.avCodecCtx, codec, NULL);
2620                            if(codec != NULL && !errorCode)
2621                            {
2622                               ffmpeg_printf(10, "AVCODEC__INIT__SUCCESS\n");
2623                            }
2624                            else
2625                            {
2626                               ffmpeg_printf(10, "AVCODEC__INIT__FAILED error[%d]\n", errorCode);
2627                            }
2628                        }
2629                    }
2630                    else if(!strncmp(encoding, "A_PCM", 5))
2631                    {
2632                        track.inject_raw_pcm = 1;
2633                    }
2634                    else if (get_codecpar(stream)->codec_id == AV_CODEC_ID_AAC_LATM)
2635                    {
2636                        const char marker[] = "LATM";
2637                        track.aacbuflen = sizeof(marker)/sizeof(char);
2638                        track.aacbuf = malloc(track.aacbuflen);
2639                        memcpy(track.aacbuf, marker, track.aacbuflen);
2640                       
2641                        ffmpeg_printf(10, "AV_CODEC_ID_AAC_LATM no extradata ACC header should be available in each frame\n");
2642                        track.have_aacheader = 1;
2643                    }
2644                    else if(!strncmp(encoding, "A_AAC_LATM", 10))
2645                    {
2646                        ffmpeg_printf(10, "AV_CODEC_ID_AAC_LATM extradata will be used in aac writter\n");
2647                    }
2648                    else if (get_codecpar(stream)->codec_id == AV_CODEC_ID_AAC)
2649                    {
2650                        if( 0 == strncmp(avContext->iformat->name, "mpegts", 6) ||
2651                            0 == strncmp(avContext->iformat->name, "hls,", 4) )
2652                        {
2653                            const char marker[] = "ADTS";
2654                            track.aacbuflen = sizeof(marker)/sizeof(char);
2655                            track.aacbuf = malloc(track.aacbuflen);
2656                            memcpy(track.aacbuf, marker, track.aacbuflen);
2657                           
2658                            ffmpeg_printf(10, "AV_CODEC_ID_AAC no extradata ACC header should be available in each frame\n");
2659                            track.have_aacheader = 1;
2660                        }
2661                        else
2662                        {
2663                            ffmpeg_printf(10, "Create AAC ExtraData\n");
2664                            ffmpeg_printf(10, "get_codecpar(stream)->extradata_size %d\n", get_codecpar(stream)->extradata_size);
2665                            //Hexdump(get_codecpar(stream)->extradata, get_codecpar(stream)->extradata_size);
2666
2667                            /*  extradata:
2668                                13 10 56 e5 9d 48 00 (anderen cops)
2669                                object_type: 00010 2 = LC
2670                                sample_rate: 011 0 6 = 24000
2671                                chan_config: 0010 2 = Stereo
2672                                000 0
2673                                1010110 111 = 0x2b7
2674                                00101 = SBR
2675                                1
2676                                0011 = 48000
2677                                101 01001000 = 0x548
2678                                ps = 0
2679                                0000000
2680                            */
2681
2682                            int32_t object_type = 2; // LC
2683                            int32_t sample_index = aac_get_sample_rate_index(get_codecpar(stream)->sample_rate);
2684                            int32_t chan_config = get_codecpar(stream)->channels - 1;
2685                            ffmpeg_printf(1,"aac object_type %d\n", object_type);
2686                            ffmpeg_printf(1,"aac sample_index %d\n", sample_index);
2687                            ffmpeg_printf(1,"aac chan_config %d\n", chan_config);
2688                           
2689                            if (get_codecpar(stream)->extradata_size >= 2)
2690                            {
2691                                MPEG4AudioConfig m4ac;
2692                                int off = avpriv_mpeg4audio_get_config(&m4ac, get_codecpar(stream)->extradata, get_codecpar(stream)->extradata_size * 8, 1);
2693                                if (off >= 0)
2694                                {
2695                                    object_type  = m4ac.object_type;
2696                                    sample_index = m4ac.sampling_index;
2697                                    if (sample_index == 0x0f)
2698                                    {
2699                                        sample_index = aac_get_sample_rate_index(m4ac.sample_rate);
2700                                    }
2701                                    chan_config  = m4ac.chan_config;
2702                                }
2703                            }
2704                           
2705                            ffmpeg_printf(1,"aac object_type %d\n", object_type);
2706                            ffmpeg_printf(1,"aac sample_index %d\n", sample_index);
2707                            ffmpeg_printf(1,"aac chan_config %d\n", chan_config);
2708
2709                           
2710                            // https://wiki.multimedia.cx/index.php/ADTS
2711                            object_type -= 1; //ADTS - profile, the MPEG-4 Audio Object Type minus 1
2712                           
2713                            track.aacbuflen = AAC_HEADER_LENGTH;
2714                            track.aacbuf = malloc(8);
2715                            track.aacbuf[0] = 0xFF;
2716                            track.aacbuf[1] = 0xF1;
2717                            //track.aacbuf[1] |=0x8;
2718                            track.aacbuf[2] = ((object_type & 0x03) << 6)  | (sample_index << 2) | ((chan_config >> 2) & 0x01);
2719                            track.aacbuf[3] = (chan_config & 0x03) << 6;
2720                            //track.aacbuf[3]|= 0x10;
2721                            track.aacbuf[4] = 0x00;
2722                            track.aacbuf[5] = 0x1F;
2723                            track.aacbuf[6] = 0xFC;
2724
2725                            //printf("AAC_HEADER -> ");
2726                            //Hexdump(track.aacbuf,7);
2727                            track.have_aacheader = 1;
2728                        }
2729                        /*
2730                        else
2731                        {
2732                            ffmpeg_err("AV_CODEC_ID_AAC extradata not available\n");
2733                        }
2734                        */
2735
2736                    }
2737                    else if(get_codecpar(stream)->codec_id == AV_CODEC_ID_WMAV1
2738                        || get_codecpar(stream)->codec_id == AV_CODEC_ID_WMAV2
2739                        || get_codecpar(stream)->codec_id == AV_CODEC_ID_WMAPRO
2740                        || get_codecpar(stream)->codec_id == AV_CODEC_ID_WMALOSSLESS) //if (get_codecpar(stream)->extradata_size > 0)
2741                    {
2742                        ffmpeg_printf(10,"Create WMA ExtraData\n");
2743                        uint16_t channels = get_codecpar(stream)->channels;
2744                        uint32_t rate = get_codecpar(stream)->sample_rate;
2745                        uint32_t bitrate = get_codecpar(stream)->bit_rate;
2746                        uint16_t block_align = get_codecpar(stream)->block_align;
2747                        uint16_t depth = get_codecpar(stream)->bits_per_coded_sample;
2748                        uint32_t codec_data_size = get_codecpar(stream)->extradata_size;
2749                        uint8_t *codec_data_pointer = get_codecpar(stream)->extradata;
2750                       
2751                        // type_specific_data
2752                        #define WMA_VERSION_1           0x160
2753                        #define WMA_VERSION_2_9         0x161
2754                        #define WMA_VERSION_9_PRO       0x162
2755                        #define WMA_LOSSLESS            0x163
2756                        uint16_t codec_id = 0;
2757                        switch(get_codecpar(stream)->codec_id)
2758                        {
2759                            //TODO: What code for lossless ?
2760                            case AV_CODEC_ID_WMALOSSLESS:
2761                                codec_id = WMA_LOSSLESS;
2762                                break;
2763                            case AV_CODEC_ID_WMAPRO:
2764                                codec_id = WMA_VERSION_9_PRO;
2765                                break;
2766                            case AV_CODEC_ID_WMAV2:
2767                                codec_id = WMA_VERSION_2_9 ;
2768                                break;
2769                            case AV_CODEC_ID_WMAV1:
2770                            default:
2771                                codec_id = WMA_VERSION_1;
2772                                break;
2773                        }
2774#ifdef __sh__
2775                        track.aacbuflen = 104 + get_codecpar(stream)->extradata_size;
2776                        track.aacbuf = malloc(track.aacbuflen);
2777                        memset (track.aacbuf, 0, track.aacbuflen);
2778                       
2779                        uint8_t ASF_Stream_Properties_Object[16] =
2780                        {0x91,0x07,0xDC,0xB7,0xB7,0xA9,0xCF,0x11,0x8E,0xE6,0x00,0xC0,0x0C,0x20,0x53,0x65};
2781                       
2782                        memcpy(track.aacbuf + 0, ASF_Stream_Properties_Object, 16); // ASF_Stream_Properties_Object
2783                        memcpy(track.aacbuf + 16, &track.aacbuflen, 4); //FrameDateLength
2784
2785                        uint32_t sizehi = 0;
2786                        memcpy(track.aacbuf + 20, &sizehi, 4); // sizehi (not used)
2787
2788                        uint8_t ASF_Audio_Media[16] =
2789                        {0x40,0x9E,0x69,0xF8,0x4D,0x5B,0xCF,0x11,0xA8,0xFD,0x00,0x80,0x5F,0x5C,0x44,0x2B};
2790                       
2791                        memcpy(track.aacbuf + 24, ASF_Audio_Media, 16); //ASF_Audio_Media
2792
2793                        uint8_t ASF_Audio_Spread[16] =
2794                        {0x50,0xCD,0xC3,0xBF,0x8F,0x61,0xCF,0x11,0x8B,0xB2,0x00,0xAA,0x00,0xB4,0xE2,0x20};
2795                       
2796                        memcpy(track.aacbuf + 40, ASF_Audio_Spread, 16); //ASF_Audio_Spread
2797
2798                        memset(track.aacbuf + 56, 0, 4); // time_offset (not used)
2799                        memset(track.aacbuf + 60, 0, 4); // time_offset_hi (not used)
2800
2801                        uint8_t type_specific_data_length = 18 + get_codecpar(stream)->extradata_size;
2802                        memcpy(track.aacbuf + 64, &type_specific_data_length, 4); //type_specific_data_length
2803
2804                        uint8_t error_correction_data_length = 8;
2805                        memcpy(track.aacbuf + 68, &error_correction_data_length, 4); //error_correction_data_length
2806
2807                        uint16_t flags = 1; // stream_number
2808                        memcpy(track.aacbuf + 72, &flags, 2); //flags
2809
2810                        uint32_t reserved = 0;
2811                        memcpy(track.aacbuf + 74, &reserved, 4); // reserved
2812
2813                        memcpy(track.aacbuf + 78, &codec_id, 2); //codec_id
2814
2815                        uint16_t number_of_channels = get_codecpar(stream)->channels;
2816                        memcpy(track.aacbuf + 80, &number_of_channels, 2); //number_of_channels
2817
2818                        uint32_t samples_per_second = get_codecpar(stream)->sample_rate;
2819                        ffmpeg_printf(1, "samples_per_second = %d\n", samples_per_second);
2820                        memcpy(track.aacbuf + 82, &samples_per_second, 4); //samples_per_second
2821
2822                        uint32_t average_number_of_bytes_per_second = get_codecpar(stream)->bit_rate / 8;
2823                        ffmpeg_printf(1, "average_number_of_bytes_per_second = %d\n", average_number_of_bytes_per_second);
2824                        memcpy(track.aacbuf + 86, &average_number_of_bytes_per_second, 4); //average_number_of_bytes_per_second
2825
2826                        uint16_t block_alignment = get_codecpar(stream)->block_align;
2827                        ffmpeg_printf(1, "block_alignment = %d\n", block_alignment);
2828                        memcpy(track.aacbuf + 90, &block_alignment, 2); //block_alignment
2829
2830#if (LIBAVFORMAT_VERSION_MAJOR > 57) || ((LIBAVFORMAT_VERSION_MAJOR == 57) && (LIBAVFORMAT_VERSION_MINOR > 32))
2831                        enum AVSampleFormat sample_fmt = get_codecpar(stream)->format;
2832#else
2833                        enum AVSampleFormat sample_fmt = get_codecpar(stream)->sample_fmt;
2834#endif
2835                        uint16_t bits_per_sample = sample_fmt>=0 ? (sample_fmt+1)*8 : 8;
2836                        ffmpeg_printf(1, "bits_per_sample = %d (%d)\n", bits_per_sample, sample_fmt);
2837                        memcpy(track.aacbuf + 92, &bits_per_sample, 2); //bits_per_sample
2838
2839                        memcpy(track.aacbuf + 94, &get_codecpar(stream)->extradata_size, 2); //bits_per_sample
2840
2841                        memcpy(track.aacbuf + 96, get_codecpar(stream)->extradata, get_codecpar(stream)->extradata_size);
2842#else
2843                        track.aacbuflen = 18 + get_codecpar(stream)->extradata_size;
2844                        track.aacbuf = malloc(track.aacbuflen);
2845                        memset (track.aacbuf, 0, track.aacbuflen);
2846                       
2847                        uint8_t *data = track.aacbuf;
2848                        /* codec tag */
2849                        *(data++) = codec_id & 0xff;
2850                        *(data++) = (codec_id >> 8) & 0xff;
2851                        /* channels */
2852                        *(data++) = channels & 0xff;
2853                        *(data++) = (channels >> 8) & 0xff;
2854                        /* sample rate */
2855                        *(data++) = rate & 0xff;
2856                        *(data++) = (rate >> 8) & 0xff;
2857                        *(data++) = (rate >> 16) & 0xff;
2858                        *(data++) = (rate >> 24) & 0xff;
2859                        /* byte rate */
2860                        bitrate /= 8;
2861                        *(data++) = bitrate & 0xff;
2862                        *(data++) = (bitrate >> 8) & 0xff;
2863                        *(data++) = (bitrate >> 16) & 0xff;
2864                        *(data++) = (bitrate >> 24) & 0xff;
2865                        /* block align */
2866                        *(data++) = block_align & 0xff;
2867                        *(data++) = (block_align >> 8) & 0xff;
2868                        /* word size */
2869                        *(data++) = depth & 0xff;
2870                        *(data++) = (depth >> 8) & 0xff;
2871                        /* codec data size */
2872                        *(data++) = codec_data_size & 0xff;
2873                        *(data++) = (codec_data_size >> 8) & 0xff;
2874                        memcpy(data, codec_data_pointer, codec_data_size);
2875#endif
2876                        ffmpeg_printf(1, "aacbuf:\n");
2877                        //Hexdump(track.aacbuf, track.aacbuflen);
2878
2879                        //ffmpeg_printf(1, "priv_data:\n");
2880                        //Hexdump(get_codecpar(stream)->priv_data, track.aacbuflen);
2881
2882                        track.have_aacheader = 1;
2883                    }
2884                   
2885                    if (context->manager->audio)
2886                    {
2887                        ffmpeg_printf(1, "cAVIdx[%d]: MANAGER_ADD track AUDIO\n");
2888                        if (context->manager->audio->Command(context, MANAGER_ADD, &track) < 0)
2889                        {
2890                            /* konfetti: fixme: is this a reason to return with error? */
2891                            ffmpeg_err("failed to add track %d\n", n);
2892                        }
2893                    }
2894                }
2895                else //encoding != NULL
2896                {
2897                    ffmpeg_err("codec type audio but codec unknown %d\n", get_codecpar(stream)->codec_id);
2898                }
2899                break;
2900            case AVMEDIA_TYPE_SUBTITLE:
2901            {
2902                if (get_codecpar(stream)->codec_id != AV_CODEC_ID_SSA &&
2903#if LIBAVCODEC_VERSION_INT >= AV_VERSION_INT(55, 3, 100)
2904                    get_codecpar(stream)->codec_id != AV_CODEC_ID_ASS &&
2905#endif
2906                    get_codecpar(stream)->codec_id != AV_CODEC_ID_SUBRIP &&
2907                    get_codecpar(stream)->codec_id != AV_CODEC_ID_TEXT &&
2908                    get_codecpar(stream)->codec_id != AV_CODEC_ID_SRT)
2909                {
2910                    ffmpeg_printf(10, "subtitle with not supported codec codec_id[%u]\n", (uint32_t)get_codecpar(stream)->codec_id);
2911                }
2912                else if (initial && context->manager->subtitle)
2913                {
2914                    AVDictionaryEntry *lang = NULL;
2915                    memset(&track, 0, sizeof(track));
2916
2917                    ffmpeg_printf(10, "CODEC_TYPE_SUBTITLE %d\n", get_codecpar(stream)->codec_type);
2918                   
2919                    lang = av_dict_get(stream->metadata, "language", NULL, 0);
2920                    track.Name = lang ? lang->value : "und";
2921                    ffmpeg_printf(10, "Language %s\n", track.Name);
2922
2923                    track.Encoding       = encoding;
2924                    track.stream         = stream;
2925                    track.Id             = ((AVStream *) (track.stream))->id;
2926                    track.duration       = (int64_t)av_rescale(stream->duration, (int64_t)stream->time_base.num * 1000, stream->time_base.den);
2927                   
2928                    if(stream->duration == AV_NOPTS_VALUE)
2929                    {
2930                        ffmpeg_printf(10, "Stream has no duration so we take the duration from context\n");
2931                        track.duration = (int64_t) avContext->duration / 1000;
2932                    }
2933
2934                    track.extraData      = get_codecpar(stream)->extradata;
2935                    track.extraSize      = get_codecpar(stream)->extradata_size;
2936
2937                    ffmpeg_printf(1, "subtitle codec %d\n", get_codecpar(stream)->codec_id);
2938                    ffmpeg_printf(1, "subtitle width %d\n", get_codecpar(stream)->width);
2939                    ffmpeg_printf(1, "subtitle height %d\n", get_codecpar(stream)->height);
2940                    ffmpeg_printf(1, "subtitle stream %p\n", stream);
2941
2942                    ffmpeg_printf(10, "FOUND SUBTITLE %s\n", track.Name);
2943                   
2944                    if (context->manager->subtitle->Command(context, MANAGER_ADD, &track) < 0)
2945                    {
2946                        ffmpeg_err("failed to add subtitle track %d\n", n);
2947                    }
2948                }
2949                break;
2950            }
2951            case AVMEDIA_TYPE_UNKNOWN:
2952            case AVMEDIA_TYPE_DATA:
2953            case AVMEDIA_TYPE_ATTACHMENT:
2954            case AVMEDIA_TYPE_NB:
2955            default:
2956                stream->discard = AVDISCARD_ALL;
2957                ffmpeg_err("not handled or unknown codec_type %d\n", get_codecpar(stream)->codec_type);
2958             break;
2959            }
2960        } /* for */
2961   
2962    }
2963   
2964    if (context->manager->audio)
2965    {
2966        Track_t *Tracks = NULL;
2967        int32_t TrackCount = 0;
2968        int32_t selTrackIdx = -1;
2969       
2970        context->manager->audio->Command(context, MANAGER_REF_LIST, &Tracks);
2971        context->manager->audio->Command(context, MANAGER_REF_LIST_SIZE, &TrackCount);
2972        if (Tracks && TrackCount)
2973        {
2974            int32_t i;
2975            for (i=0; i < TrackCount; ++i)
2976            {
2977                if (Tracks[i].pending || Tracks[i].Id < 0)
2978                    continue;
2979               
2980                if (selTrackIdx == -1)
2981                    selTrackIdx = i;
2982                   
2983                if (currAudioTrack && currAudioTrack->Id == Tracks[i].Id)
2984                {
2985                    selTrackIdx = i;
2986                    break;
2987                }
2988            }
2989           
2990            if (selTrackIdx > -1)
2991            {
2992                ((AVStream*)Tracks[selTrackIdx].stream)->discard = AVDISCARD_DEFAULT;
2993                if (!currAudioTrack || currAudioTrack->Id != Tracks[selTrackIdx].Id )
2994                {
2995                    context->manager->audio->Command(context, MANAGER_SET, &Tracks[selTrackIdx].Id);
2996                }
2997            }
2998        }
2999    }
3000   
3001    releaseMutex(__FILE__, __FUNCTION__,__LINE__);
3002    return cERR_CONTAINER_FFMPEG_NO_ERROR;
3003}
3004
3005static int32_t container_ffmpeg_play(Context_t *context)
3006{
3007    int32_t error = 0;
3008    int32_t ret = 0;
3009    pthread_attr_t attr;
3010
3011    ffmpeg_printf(10, "\n");
3012
3013    if ( context && context->playback && context->playback->isPlaying )
3014    {
3015        ffmpeg_printf(10, "is Playing\n");
3016    }
3017    else
3018    {
3019        ffmpeg_printf(10, "is NOT Playing\n");
3020    }
3021
3022    if (hasPlayThreadStarted == 0)
3023    {
3024        pthread_attr_init(&attr);
3025        pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
3026
3027        if((error = pthread_create(&PlayThread, &attr, (void *)&FFMPEGThread, context)) != 0)
3028        {
3029            ffmpeg_printf(10, "Error creating thread, error:%d:%s\n", error,strerror(error));
3030
3031            hasPlayThreadStarted = 0;
3032            ret = cERR_CONTAINER_FFMPEG_ERR;
3033        }
3034        else
3035        {
3036            ffmpeg_printf(10, "Created thread\n");
3037
3038            hasPlayThreadStarted = 1;
3039        }
3040    }
3041    else
3042    {
3043        ffmpeg_printf(10, "A thread already exists!\n");
3044        ret = cERR_CONTAINER_FFMPEG_ERR;
3045    }
3046
3047    ffmpeg_printf(10, "exiting with value %d\n", ret);
3048    return ret;
3049}
3050
3051static int32_t container_ffmpeg_stop(Context_t *context)
3052{
3053    int32_t ret = cERR_CONTAINER_FFMPEG_NO_ERROR;
3054    int32_t wait_time = 10; // we give 1s to close otherwise we will force close
3055
3056    ffmpeg_printf(10, "\n");
3057
3058    if (!isContainerRunning)
3059    {
3060        ffmpeg_err("Container not running\n");
3061        return cERR_CONTAINER_FFMPEG_ERR;
3062    }
3063
3064    //obi
3065    wait_time = 100;
3066    if(hasfillerThreadStarted[hasfillerThreadStartedID] == 1)
3067        hasfillerThreadStarted[hasfillerThreadStartedID] = 2; // should end
3068    while ( (hasfillerThreadStarted[hasfillerThreadStartedID] != 0) && (--wait_time) > 0 ) {
3069        ffmpeg_printf(10, "Waiting for ffmpeg filler thread to terminate itself, will try another %d times, ID=%d\n", wait_time, hasfillerThreadStartedID);
3070        usleep(100000);
3071    }
3072
3073    if (wait_time == 0) {
3074        ffmpeg_err( "Timeout waiting for filler thread!\n");
3075
3076        ret = cERR_CONTAINER_FFMPEG_ERR;
3077    }
3078    //obi (end)
3079
3080    if (context->playback)
3081    {
3082        context->playback->isPlaying = 0;
3083    }
3084
3085    while ( (hasPlayThreadStarted != 0) && (--wait_time) > 0 )
3086    {
3087        ffmpeg_printf(10, "Waiting for ffmpeg thread to terminate itself, will try another %d times\n", wait_time);
3088        usleep(100000);
3089    }
3090
3091    if (wait_time == 0)
3092    {
3093        /* force close */
3094        ffmpeg_err( "Timeout waiting for thread!\n");
3095        ret = cERR_CONTAINER_FFMPEG_ERR;
3096        /* to speed up close - we are in separate process for the moment this process will
3097         * be closed and whole resources will be free by the system 
3098         */
3099        return ret;
3100    }
3101
3102    hasPlayThreadStarted = 0;
3103    terminating = 1;
3104
3105    getMutex(__FILE__, __FUNCTION__,__LINE__);
3106   
3107    free_all_stored_avcodec_context();
3108   
3109    uint32_t i = 0;
3110    for(i=0; i<IPTV_AV_CONTEXT_MAX_NUM; i+=1)
3111    {
3112        if(NULL != avContextTab[i])
3113        {
3114            if(0 != use_custom_io[i])
3115            {
3116                /*
3117                 * Free custom IO independently to avoid segfault/bus error
3118                 * avformat_close_input do not expect custom io, so it try
3119                 * to release incorrectly
3120                 */
3121                av_freep(&(avContextTab[i]->pb->buffer));
3122                av_freep(&(avContextTab[i]->pb));
3123                use_custom_io[i] = 0;
3124            }
3125            avformat_close_input(&avContextTab[i]);
3126            //obi
3127            ffmpeg_buf_free();
3128            //obi (end)
3129            avContextTab[i] = NULL;
3130        }
3131        else
3132        {
3133            break;
3134        }
3135    }
3136
3137    if(avio_opts != NULL)
3138    {
3139        av_dict_free(&avio_opts);
3140    }
3141
3142    isContainerRunning = 0;
3143    avformat_network_deinit();
3144    ffmpeg_buf_free();
3145
3146    releaseMutex(__FILE__, __FUNCTION__,__LINE__);
3147
3148    ffmpeg_printf(10, "ret %d\n", ret);
3149    return ret;
3150}
3151
3152static int32_t container_ffmpeg_seek_bytes(off_t pos)
3153{
3154    int32_t flag = AVSEEK_FLAG_BYTE;
3155    off_t current_pos = avio_tell(avContextTab[0]->pb);
3156
3157    ffmpeg_printf(20, "seeking to position %lld (bytes)\n", pos);
3158
3159    if (current_pos > pos)
3160    {
3161        flag |= AVSEEK_FLAG_BACKWARD;
3162    }
3163
3164    if (avformat_seek_file(avContextTab[0], -1, INT64_MIN, pos, INT64_MAX, flag) < 0)
3165    {
3166        ffmpeg_err( "Error seeking\n");
3167        return cERR_CONTAINER_FFMPEG_ERR;
3168    }
3169
3170    ffmpeg_printf(30, "current_pos after seek %lld\n", avio_tell(avContextTab[0]->pb));
3171
3172    return cERR_CONTAINER_FFMPEG_NO_ERROR;
3173}
3174
3175/* seeking relative to a given byteposition N seconds ->for reverse playback needed */
3176static int32_t container_ffmpeg_seek_rel(Context_t *context, off_t pos, int64_t pts, int64_t sec)
3177{
3178    Track_t *videoTrack = NULL;
3179    Track_t *audioTrack = NULL;
3180    Track_t *current = NULL;
3181    seek_target_flag = 0;
3182
3183    ffmpeg_printf(10, "seeking %f sec relativ to %lld\n", sec, pos);
3184
3185    context->manager->video->Command(context, MANAGER_GET_TRACK, &videoTrack);
3186    context->manager->audio->Command(context, MANAGER_GET_TRACK, &audioTrack);
3187
3188    if (videoTrack != NULL)
3189    {
3190        current = videoTrack;
3191    }
3192    else if (audioTrack != NULL)
3193    {
3194        current = audioTrack;
3195    }
3196   
3197    if (current == NULL)
3198    {
3199        ffmpeg_err( "no track avaibale to seek\n");
3200        return cERR_CONTAINER_FFMPEG_ERR;
3201    }
3202
3203    if (pos == -1)
3204    {
3205        pos = avio_tell(avContextTab[0]->pb);
3206    }
3207
3208    if (pts == -1)
3209    {
3210        pts = current->pts;
3211    }
3212   
3213    if (sec < 0)
3214    {
3215        seek_target_flag |= AVSEEK_FLAG_BACKWARD;
3216    }
3217
3218    ffmpeg_printf(10, "iformat->flags %d\n", avContextTab[0]->iformat->flags);
3219#if defined(TS_BYTES_SEEKING) && TS_BYTES_SEEKING
3220    if (avContextTab[0]->iformat->flags & AVFMT_TS_DISCONT)
3221    {
3222        if (avContextTab[0]->bit_rate)
3223        {
3224            sec *= avContextTab[0]->bit_rate / 8;
3225            ffmpeg_printf(10, "bit_rate %d\n", avContextTab[0]->bit_rate);
3226        }
3227        else
3228        {
3229            sec *= 180000;
3230        }
3231
3232        pos += sec;
3233
3234        if (pos < 0)
3235        {
3236           ffmpeg_err("end of file reached\n");
3237           releaseMutex(__FILE__, __FUNCTION__,__LINE__);
3238           return cERR_CONTAINER_FFMPEG_END_OF_FILE;
3239        }
3240
3241        ffmpeg_printf(10, "1. seeking to position %lld bytes ->sec %f\n", pos, sec);
3242
3243        seek_target_bytes = pos;
3244        do_seek_target_bytes = 1;
3245
3246        return pos;
3247    }
3248    else
3249#endif
3250    {
3251        sec += pts / 90000;
3252
3253        if (sec < 0)
3254        {
3255            sec = 0;
3256        }
3257
3258        ffmpeg_printf(10, "2. seeking to position %f sec ->time base %f %d\n", sec, av_q2d(((AVStream*) current->stream)->time_base), AV_TIME_BASE);
3259
3260        seek_target_seconds = sec * AV_TIME_BASE;
3261        do_seek_target_seconds = 1;
3262    }
3263
3264    releaseMutex(__FILE__, __FUNCTION__,__LINE__);
3265    return cERR_CONTAINER_FFMPEG_NO_ERROR;
3266}
3267
3268static int32_t container_ffmpeg_seek(Context_t *context, int64_t sec, uint8_t absolute)
3269{
3270    Track_t *videoTrack = NULL;
3271    Track_t *audioTrack = NULL;
3272    Track_t *current = NULL;
3273    seek_target_flag = 0;
3274
3275    if (!absolute)
3276    {
3277        ffmpeg_printf(10, "seeking %f sec\n", sec);
3278        if (sec == 0)
3279        {
3280            ffmpeg_err("sec = 0 ignoring\n");
3281            return cERR_CONTAINER_FFMPEG_ERR;
3282        }
3283        else
3284        {
3285            int64_t currPts = -1;
3286            int32_t ret = context->playback->Command(context, PLAYBACK_PTS, &currPts);
3287            if (ret != 0)
3288            {
3289                ffmpeg_err("fail to get current PTS\n");
3290                return cERR_CONTAINER_FFMPEG_ERR;
3291            }
3292            sec += currPts / 90000;
3293        }
3294    }
3295   
3296    ffmpeg_printf(10, "goto %d sec\n", sec);
3297    if (sec < 0)
3298    {
3299        sec = 0;
3300    }
3301   
3302    context->manager->video->Command(context, MANAGER_GET_TRACK, &videoTrack);
3303    context->manager->audio->Command(context, MANAGER_GET_TRACK, &audioTrack);
3304
3305    if (videoTrack != NULL)
3306    {
3307        current = videoTrack;
3308    }
3309    else if (audioTrack != NULL)
3310    {
3311        current = audioTrack;
3312    }
3313    else
3314    {
3315        ffmpeg_err( "no track available to seek\n");
3316        return cERR_CONTAINER_FFMPEG_ERR;
3317    }
3318
3319    if (sec < 0)
3320    {
3321        seek_target_flag |= AVSEEK_FLAG_BACKWARD;
3322    }
3323
3324//    getMutex(__FILE__, __FUNCTION__,__LINE__);
3325
3326    if (!context->playback || !context->playback->isPlaying)
3327    {
3328        releaseMutex(__FILE__, __FUNCTION__,__LINE__);
3329        return cERR_CONTAINER_FFMPEG_NO_ERROR;
3330    }
3331
3332    ffmpeg_printf(10, "iformat->flags %d\n", avContextTab[0]->iformat->flags);
3333#if defined(TS_BYTES_SEEKING) && TS_BYTES_SEEKING
3334    if (avContextTab[0]->iformat->flags & AVFMT_TS_DISCONT)
3335    {
3336        /* konfetti: for ts streams seeking frame per seconds does not work (why?).
3337        * I take this algo partly from ffplay.c.
3338        *
3339        * seeking per HTTP does still not work very good. forward seeks everytime
3340        * about 10 seconds, backward does not work.
3341        */
3342
3343        getMutex(__FILE__, __FUNCTION__,__LINE__);
3344        off_t pos = avio_tell(avContextTab[0]->pb);
3345        releaseMutex(__FILE__, __FUNCTION__,__LINE__);
3346
3347        ffmpeg_printf(10, "pos %lld %d\n", pos, avContextTab[0]->bit_rate);
3348
3349        if (avContextTab[0]->bit_rate)
3350        {
3351            sec *= avContextTab[0]->bit_rate / 8;
3352            ffmpeg_printf(10, "bit_rate %d\n", avContextTab[0]->bit_rate);
3353        }
3354        else
3355        {
3356            sec *= 180000;
3357        }
3358       
3359        pos = sec;
3360       
3361        if (pos < 0)
3362        {
3363           pos = 0;
3364        }
3365       
3366        ffmpeg_printf(10, "1. seeking to position %lld bytes ->sec %d\n", pos, sec);
3367
3368        seek_target_bytes = pos;
3369        do_seek_target_bytes = 1;
3370
3371    }
3372    else
3373#endif
3374    {
3375        seek_target_seconds = sec * AV_TIME_BASE;
3376        do_seek_target_seconds = 1;
3377    }
3378
3379//    releaseMutex(__FILE__, __FUNCTION__,__LINE__);
3380    return cERR_CONTAINER_FFMPEG_NO_ERROR;
3381}
3382
3383static int32_t container_ffmpeg_get_length(Context_t *context, int64_t *length)
3384{
3385    ffmpeg_printf(50, "\n");
3386    Track_t * videoTrack = NULL;
3387    Track_t * audioTrack = NULL;
3388    Track_t * current = NULL;
3389
3390    if (length == NULL)
3391    {
3392        ffmpeg_err( "null pointer passed\n");
3393        return cERR_CONTAINER_FFMPEG_ERR;
3394    }
3395
3396    context->manager->video->Command(context, MANAGER_GET_TRACK, &videoTrack);
3397    context->manager->audio->Command(context, MANAGER_GET_TRACK, &audioTrack);
3398
3399    if (videoTrack != NULL)
3400    {
3401        current = videoTrack;
3402    }
3403    else if (audioTrack != NULL)
3404    {
3405        current = audioTrack;
3406    }
3407   
3408    *length = 0;
3409
3410    if (current != NULL)
3411    {
3412        if (current->duration == 0)
3413        {
3414            return cERR_CONTAINER_FFMPEG_ERR;
3415        }
3416        else
3417        {
3418            *length = current->duration / 1000;
3419        }
3420    }
3421    else
3422    {
3423        if (avContextTab[0] != NULL)
3424        {
3425            *length = avContextTab[0]->duration / 1000;
3426        }
3427        else
3428        {
3429           ffmpeg_err( "no Track not context ->no problem :D\n");
3430           return cERR_CONTAINER_FFMPEG_ERR;
3431        }
3432    }
3433
3434    return cERR_CONTAINER_FFMPEG_NO_ERROR;
3435}
3436
3437static int32_t container_ffmpeg_switch_audio(Context_t *context, int32_t *arg)
3438{
3439    ffmpeg_printf(10, "track %d\n", *arg);
3440    getMutex(__FILE__, __FUNCTION__,__LINE__);
3441    if (context->manager->audio)
3442    {
3443        Track_t *Tracks = NULL;
3444        int32_t TrackCount = 0;
3445       
3446        context->manager->audio->Command(context, MANAGER_REF_LIST, &Tracks);
3447        context->manager->audio->Command(context, MANAGER_REF_LIST_SIZE, &TrackCount);
3448        if (Tracks && TrackCount)
3449        {
3450            int32_t i;
3451            for (i=0; i < TrackCount; ++i)
3452            {
3453                ((AVStream*)Tracks[i].stream)->discard = Tracks[i].Id == *arg ? AVDISCARD_DEFAULT : AVDISCARD_ALL;
3454            }
3455        }
3456    }
3457    releaseMutex(__FILE__, __FUNCTION__,__LINE__);
3458   
3459    /* Hellmaster1024: nothing to do here!*/
3460    int64_t sec = -1;
3461    context->playback->Command(context, PLAYBACK_SEEK, (void*)&sec);
3462    return cERR_CONTAINER_FFMPEG_NO_ERROR;
3463}
3464
3465static int32_t container_ffmpeg_switch_subtitle(Context_t *context, int32_t *arg)
3466{
3467    ffmpeg_printf(10, "track %d\n", *arg);
3468   
3469    /* This is made to flush inside the buffer because
3470     * subtitles frame was already read and ignored
3471     * we seek to force ffmpeg to read once again the same data
3472     * but now we will not ignore subtitle frame
3473     */
3474    int64_t sec = -1;
3475    context->playback->Command(context, PLAYBACK_SEEK, (void*)&sec);
3476    //obi
3477    enablesub = 1;
3478    //obi (end)
3479    return cERR_CONTAINER_FFMPEG_NO_ERROR;
3480}
3481
3482//obi
3483static int32_t container_ffmpeg_get_subtext(Context_t* context, char ** data)
3484{
3485
3486//    printf("[LIBEPLAYER3/container_ffmpeg_get_subtext] start\n");
3487
3488    if(enablesub == 1 && subtext != NULL)
3489    {
3490//      printf("[LIBEPLAYER3/container_ffmpeg_get_subtext] set data\n");
3491
3492        *data = ostrcat(subtext, NULL, 0, 0);
3493        free(subtext), subtext = NULL;
3494
3495    }
3496
3497
3498
3499
3500
3501
3502
3503//    printf("[LIBEPLAYER3/container_ffmpeg_get_subtext] end\n");
3504
3505
3506    return cERR_CONTAINER_FFMPEG_NO_ERROR;
3507}
3508//obi (end)
3509
3510/* konfetti comment: I dont like the mechanism of overwriting
3511 * the pointer in infostring. This lead in most cases to
3512 * user errors, like it is in the current version (libeplayer2 <-->e2->servicemp3.cpp)
3513 * From e2 there is passed a tag=strdup here and we overwrite this
3514 * strdupped tag. This lead to dangling pointers which are never freed!
3515 * I do not free the string here because this is the wrong way. The mechanism
3516 * should be changed, or e2 should pass it in a different way...
3517 */
3518static int32_t container_ffmpeg_get_info(Context_t* context, char ** infoString)
3519{
3520    Track_t *videoTrack = NULL;
3521    Track_t *audioTrack = NULL;
3522    char     *meta = NULL;
3523
3524    ffmpeg_printf(20, ">\n");
3525
3526    if (avContextTab[0] != NULL)
3527    {
3528        if ((infoString == NULL) || (*infoString == NULL))
3529        {
3530            ffmpeg_err("infostring NULL\n");
3531            return cERR_CONTAINER_FFMPEG_ERR;
3532        }
3533
3534        ffmpeg_printf(20, "%s\n", *infoString);
3535
3536        context->manager->video->Command(context, MANAGER_GET_TRACK, &videoTrack);
3537        context->manager->audio->Command(context, MANAGER_GET_TRACK, &audioTrack);
3538
3539        if ((meta = searchMeta(avContextTab[0]->metadata, *infoString)) == NULL)
3540        {
3541            if (audioTrack != NULL)
3542            {
3543                AVStream* stream = audioTrack->stream;
3544                meta = searchMeta(stream->metadata, *infoString);
3545            }
3546
3547            if ((meta == NULL) && (videoTrack != NULL))
3548            {
3549                AVStream* stream = videoTrack->stream;
3550                meta = searchMeta(stream->metadata, *infoString);
3551            }
3552        }
3553
3554        if (meta != NULL)
3555        {
3556            *infoString = strdup(meta);
3557        }
3558        else
3559        {
3560            ffmpeg_printf(1, "no metadata found for \"%s\"\n", *infoString);
3561            *infoString = strdup("not found");
3562        }
3563    }
3564    else
3565    {
3566        ffmpeg_err("avContext NULL\n");
3567        return cERR_CONTAINER_FFMPEG_ERR;
3568    }
3569
3570    return cERR_CONTAINER_FFMPEG_NO_ERROR;
3571}
3572
3573static int32_t Command(void  *_context, ContainerCmd_t command, void *argument)
3574{
3575    Context_t  *context = (Context_t*) _context;
3576    int ret = cERR_CONTAINER_FFMPEG_NO_ERROR;
3577
3578    ffmpeg_printf(50, "Command %d\n", command);
3579
3580    if(command != CONTAINER_SET_BUFFER_SEEK_TIME &&
3581       command != CONTAINER_SET_BUFFER_SIZE &&
3582       command != CONTAINER_GET_BUFFER_SIZE &&
3583       command != CONTAINER_GET_BUFFER_STATUS &&
3584       command != CONTAINER_STOP_BUFFER &&
3585       command != CONTAINER_GET_SUBTEXT &&
3586       command != CONTAINER_INIT && !avContextTab[0])
3587    {
3588        return cERR_CONTAINER_FFMPEG_ERR;
3589    }
3590   
3591   
3592    switch(command)
3593    {
3594    case CONTAINER_INIT:
3595    {
3596        PlayFiles_t *playFilesNames = (PlayFiles_t *)argument;
3597        ret = container_ffmpeg_init(context, playFilesNames);
3598        break;
3599    }
3600    case CONTAINER_PLAY: 
3601    {
3602        ret = container_ffmpeg_play(context);
3603        break;
3604    }
3605    case CONTAINER_STOP:
3606    {
3607        ret = container_ffmpeg_stop(context);
3608        break;
3609    }
3610    case CONTAINER_SEEK:
3611    {
3612        ret = container_ffmpeg_seek(context, (int64_t)*((int64_t*)argument), 0);
3613        break;
3614    }
3615    case CONTAINER_SEEK_ABS:
3616    {
3617        ret = container_ffmpeg_seek(context, (int64_t)*((int64_t*)argument), -1);
3618        break;
3619    }
3620    case CONTAINER_LENGTH:
3621    {
3622        int64_t length = 0;
3623        ret = container_ffmpeg_get_length(context, &length);
3624        *((int64_t*)argument) = (int64_t)length;
3625        break;
3626    }
3627    case CONTAINER_SWITCH_AUDIO:
3628    {
3629        ret = container_ffmpeg_switch_audio(context, (int32_t*) argument);
3630        break;
3631    }
3632    case CONTAINER_SWITCH_SUBTITLE:
3633    {
3634        ret = container_ffmpeg_switch_subtitle(context, (int32_t*) argument);
3635        break;
3636    }
3637    case CONTAINER_INFO:
3638    {
3639        ret = container_ffmpeg_get_info(context, (char **)argument);
3640        break;
3641    }
3642    case CONTAINER_STATUS:
3643    {
3644        *((int32_t*)argument) = hasPlayThreadStarted;
3645        break;
3646    }
3647    case CONTAINER_LAST_PTS:
3648    {
3649        *((int64_t*)argument) = latestPts;
3650        break;
3651    }
3652    //obi
3653    case CONTAINER_SET_BUFFER_SEEK_TIME:
3654    {
3655        ret = container_set_ffmpeg_buf_seek_time((int*) argument);
3656            break;
3657    }
3658    //obi (end)
3659    case CONTAINER_SET_BUFFER_SIZE:
3660    {
3661        ret = container_set_ffmpeg_buf_size((int32_t *) argument);
3662        break;
3663    }
3664    case CONTAINER_GET_BUFFER_SIZE:
3665    {
3666        int32_t size = 0;
3667        ret = container_get_ffmpeg_buf_size(&size);
3668        *((int32_t*)argument) = size;
3669        break;
3670    }
3671    //obi
3672    case CONTAINER_GET_BUFFER_STATUS:
3673    {
3674            int32_t size = 0;
3675            ret = container_get_fillbufstatus(&size);
3676            *((int32_t*)argument) = size;
3677            break;
3678    }
3679    case CONTAINER_STOP_BUFFER:
3680    {
3681            ret = container_stop_buffer();
3682            break;
3683    }
3684    case CONTAINER_GET_SUBTEXT:
3685    {
3686        ret = container_ffmpeg_get_subtext(context, (char **)argument);
3687
3688
3689
3690        break;
3691    }
3692    //obi (end)
3693    default:
3694        ffmpeg_err("ContainerCmd %d not supported!\n", command);
3695        ret = cERR_CONTAINER_FFMPEG_ERR;
3696        break;
3697    }
3698
3699    ffmpeg_printf(50, "exiting with value %d\n", ret);
3700    return ret;
3701}
3702
3703static char *FFMPEG_Capabilities[] = {"aac", "avi", "mkv", "mp4", "ts", "mov", "flv", "flac", "mp3", "mpg", "m2ts", "vob", "evo", "wmv","wma", "asf", "mp2", "m4v", "m4a", "fla", "divx", "dat", "mpeg", "trp", "mts", "vdr", "ogg", "wav", "wtv", "asx", "mvi", "png", "jpg", "ra", "ram", "rm", "3gp", "amr", "webm", "m3u8", "mpd", NULL };
3704
3705Container_t FFMPEGContainer = {
3706    "FFMPEG",
3707    &Command,
3708    FFMPEG_Capabilities
3709};
Note: See TracBrowser for help on using the repository browser.