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

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

fix

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