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

Last change on this file since 44981 was 44981, checked in by obi, 20 months ago

scgubs

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