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

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

libeplayer3 / titan add internal subs support and srt listing

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