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

Last change on this file since 41219 was 41219, checked in by obi, 6 years ago

update libeplayer3 v36

File size: 114.0 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, *headers = NULL, *useragent = NULL;
1593                int count = 0, count1 = 0, count2 = 0, count3 = 0, i = 0, i1 = 0, i2 = 0, i3 = 0;
1594                struct splitstr* ret1 = NULL;
1595                struct splitstr* ret2 = NULL;
1596
1597                ffmpeg_printf(10, "check cookie\n");
1598
1599                if(file_exist("/mnt/network/cookies"))
1600                {
1601                        tmpstr1 = readfiletomem("/mnt/network/cookies", 1);
1602                        if(tmpstr1 != NULL)
1603                        {
1604                                tmpstr1 = string_replace_all("\t", " ", tmpstr1, 1);
1605                                string_strip_whitechars(tmpstr1);
1606                                strstrip(tmpstr1);
1607                                ret1 = strsplit(tmpstr1, "\n", &count);
1608                                for(i = 0; i < count; i++)
1609                                {
1610                                        count2 = 0;
1611                                        tmpstr2 = ostrcat((&ret1[i])->part, NULL, 0, 0);
1612                                        ret2 = strsplit(tmpstr2, " ", &count2);
1613
1614                                        if(count2 == 6)
1615                                        {
1616                                                cookie = ostrcat(cookie, (&ret2[4])->part, 1, 0);
1617                                                cookie = ostrcat(cookie, "=", 1, 0);
1618                                                cookie = ostrcat(cookie, (&ret2[5])->part, 1, 0);
1619                                                cookie = ostrcat(cookie, "; domain=", 1, 0);
1620                                                cookie = ostrcat(cookie, (&ret2[0])->part, 1, 0);
1621                                                cookie = ostrcat(cookie, "; path=", 1, 0);
1622                                                cookie = ostrcat(cookie, (&ret2[2])->part, 1, 0); 
1623                                                cookie = ostrcat(cookie, "\n", 1, 0);
1624                                        }
1625
1626                                        if(count2 == 7)
1627                                        {
1628                                                cookie = ostrcat(cookie, (&ret2[5])->part, 1, 0);
1629                                                cookie = ostrcat(cookie, "=", 1, 0);
1630                                                cookie = ostrcat(cookie, (&ret2[6])->part, 1, 0);
1631                                                cookie = ostrcat(cookie, "; domain=", 1, 0);
1632                                                cookie = ostrcat(cookie, (&ret2[0])->part, 1, 0);
1633                                                cookie = ostrcat(cookie, "; path=", 1, 0);
1634                                                cookie = ostrcat(cookie, (&ret2[2])->part, 1, 0); 
1635                                                cookie = ostrcat(cookie, "\n", 1, 0);
1636                                        }
1637                                       
1638                                        free(ret2), ret2 = NULL;
1639                                        free(tmpstr2), tmpstr2 = NULL;
1640                                }
1641                                free(ret1), ret1 = NULL;
1642                                free(tmpstr1), tmpstr1 = NULL;
1643                        }
1644                }
1645                if(cookie != NULL)
1646                {
1647                        ffmpeg_printf(10, "set cookies: %s\n", cookie);
1648                av_dict_set(&avio_opts, "cookies", cookie, 0);
1649                }
1650                else
1651                        ffmpeg_printf(10, "skip set cookies : %s\n", cookie);
1652
1653                ffmpeg_printf(10, "check user-agent and header\n");
1654
1655                if(ostrstr(filename, "|") != NULL)
1656                {
1657                        tmpstr1 = ostrcat(filename, NULL, 0, 0);
1658                        ret1 = strsplit(tmpstr1, "|", &count1);
1659               
1660                        if(ret1 != NULL)
1661                        {
1662                                for(i1 = 0; i1 < count1; i1++)
1663                                {
1664                                        if(i1 == 0) continue;
1665
1666                                        count2 = 0;
1667                                        i2 = 0;
1668
1669                                        tmpstr2 = ostrcat(ret1[i1].part, NULL, 0, 0);
1670                                        ret2 = strsplit(tmpstr2, "&", &count2);
1671
1672                                        if(ret2 != NULL)
1673                                        {
1674                                                for(i2 = 0; i2 < count2; i2++)
1675                                                {
1676                                                        count3 = 0;
1677                                                        i3 = 0;
1678                                                        struct splitstr* ret3 = NULL;
1679                                                        tmpstr3 = ostrcat(ret2[i2].part, NULL, 0, 0);
1680                                                        ret3 = strsplit(tmpstr3, "=", &count3);
1681                                       
1682                                                        if(ret3 != NULL && count3 > 0)
1683                                                        {
1684                                                                int max = count3 - 1;
1685                                                                for(i3 = 0; i3 < max; i3++)
1686                                                                {
1687                                                                        if(ostrcmp("User-Agent", ret3[i3].part) == 0)
1688                                                                        {
1689                                                                                av_dict_set(&avio_opts, "user-agent", ret3[i3 + 1].part, 0);
1690                                                                                ffmpeg_printf(10, "set user-agent: %s\n", ret3[i3 + 1].part);
1691                                                                                useragent = ostrcat(useragent, ret3[i3 + 1].part, 1, 0);
1692                                                                        }
1693                                                                        else
1694                                                                        {
1695                                                                            headers = ostrcat(headers, ret3[i3].part, 1, 0);
1696                                                                            headers = ostrcat(headers, ": ", 1, 0);
1697                                                                            headers = ostrcat(headers, ret3[i3 + 1].part, 1, 0);
1698                                                                            headers = ostrcat(headers, "\r\n", 1, 0);
1699                                                                        }
1700                                                                }
1701                                                        }
1702                                                        free(ret3), ret3 = NULL;
1703                                                        free(tmpstr3), tmpstr3 = NULL;
1704                                                }
1705                                        }
1706                                        free(ret2), ret2 = NULL;
1707                                        free(tmpstr2), tmpstr2 = NULL;
1708                                }
1709
1710                            if(headers != NULL)
1711                                {
1712                                av_dict_set(&avio_opts, "headers", headers, 0);
1713                                        ffmpeg_printf(10, "set headers: %s\n", headers);
1714                                }
1715                                else
1716                                        ffmpeg_printf(10, "skip set headers: %s\n", headers);
1717
1718                            if(useragent == NULL)
1719                                        ffmpeg_printf(10, "skip set user-agent: %s\n", headers);
1720                        }
1721
1722                        free(useragent), useragent = NULL;
1723                        free(headers), headers = NULL;
1724                        free(ret1), ret1 = NULL;       
1725                        free(tmpstr1), tmpstr1 = NULL;
1726                        stringreplacechar(filename, '|', '\0');         
1727                        ffmpeg_printf(10, "changed filename: %s\n", filename);
1728
1729                }
1730
1731                ffmpeg_printf(10, "check tslivemode\n");
1732
1733        if (ostrstr(filename, ".m3u8") != NULL)
1734        {
1735                        ffmpeg_printf(10, "set tslivemode\n");
1736                        context->playback->isTSLiveMode = 1;
1737                }
1738//obi (end)
1739
1740        av_dict_set(&avio_opts, "reconnect", "1", 0);
1741        if (context->playback->isTSLiveMode) // special mode for live TS stream with skip packet
1742        {
1743            av_dict_set(&avio_opts, "seekable", "0", 0);
1744            av_dict_set(&avio_opts, "reconnect_at_eof", "1", 0);
1745            av_dict_set(&avio_opts, "reconnect_streamed", "1", 0);
1746        }
1747    }
1748   
1749    pavio_opts = &avio_opts;
1750   
1751    if ((err = avformat_open_input(&avContextTab[AVIdx], filename, fmt, pavio_opts)) != 0)
1752    {
1753        if (rtmp_proto_impl == 0 && //err == AVERROR_UNKNOWN &&
1754            rtmpProtoImplType == RTMP_NATIVE &&
1755            numOfRTMPImpl > 1)
1756        {
1757            // retry with librtmp
1758            err = avformat_open_input(&avContextTab[AVIdx], filename+2, fmt, pavio_opts);
1759            // filename2 - another memory leak, and also only once, so does not matter
1760        }
1761       
1762        if (err != 0)
1763        {
1764            char error[512];
1765
1766            ffmpeg_err("avformat_open_input failed %d (%s)\n", err, filename);
1767            av_strerror(err, error, 512);
1768            fprintf(stderr, "{\"FF_ERROR\":{\"msg\":\"%s\",\"code\":%i}}\n", error, err);
1769
1770            if(avio_opts != NULL)
1771            {
1772                av_dict_free(&avio_opts);
1773            }
1774
1775            //obi
1776            ffmpeg_buf_free();
1777            //obi (end)
1778
1779            releaseMutex(__FILE__, __FUNCTION__,__LINE__);
1780            return cERR_CONTAINER_FFMPEG_OPEN;
1781        }
1782    }
1783
1784    avContextTab[AVIdx]->iformat->flags |= AVFMT_SEEK_TO_PTS;
1785    avContextTab[AVIdx]->flags = AVFMT_FLAG_GENPTS;
1786
1787    if (context->playback->noprobe)
1788    {
1789        wrapped_set_max_analyze_duration(avContextTab[AVIdx], 1);
1790    }
1791
1792    ffmpeg_printf(20, "find_streaminfo\n");
1793
1794    if (avformat_find_stream_info(avContextTab[AVIdx], NULL) < 0)
1795    {
1796        ffmpeg_err("Error avformat_find_stream_info\n");
1797    }
1798
1799//for buffered io
1800    if(avContextTab[AVIdx] != NULL && avContextTab[AVIdx]->pb != NULL && !context->playback->isTSLiveMode)
1801    {
1802        ffmpeg_real_read_org = avContextTab[AVIdx]->pb->read_packet;
1803       
1804        if(0 ==AVIdx && strstr(filename, "://") != 0 &&
1805           strncmp(filename, "file://", 7) != 0)
1806        {
1807            if(ffmpeg_buf_size > 0 && ffmpeg_buf_size > FILLBUFDIFF + FILLBUFPAKET)
1808            {
1809                if(avContextTab[AVIdx] != NULL && avContextTab[AVIdx]->pb != NULL)
1810                {
1811                    ffmpeg_buf = av_malloc(ffmpeg_buf_size);
1812
1813                    if(ffmpeg_buf != NULL)
1814                    {
1815                        ffmpeg_printf(10, "buffer size=%d\n", ffmpeg_buf_size);
1816                       
1817                        ffmpeg_read_org = avContextTab[AVIdx]->pb->read_packet;
1818                        avContextTab[AVIdx]->pb->read_packet = ffmpeg_read;
1819                        ffmpeg_seek_org = avContextTab[AVIdx]->pb->seek;
1820                        avContextTab[AVIdx]->pb->seek = ffmpeg_seek;
1821                        ffmpeg_buf_read = ffmpeg_buf;
1822                        ffmpeg_buf_write = ffmpeg_buf;
1823
1824                        //fill buffer
1825                        ffmpeg_filler(context, -1, NULL, 0);
1826                        ffmpeg_start_fillerTHREAD(context);
1827                    }
1828                }
1829            }
1830        }
1831        else if (progressive_playback)
1832        {
1833            avContextTab[AVIdx]->pb->read_packet = ffmpeg_read_wrapper;
1834        }
1835    }
1836//for buffered io (end)
1837   
1838    return 0;
1839}
1840
1841int32_t container_ffmpeg_init(Context_t *context, PlayFiles_t *playFilesNames)
1842{
1843    int32_t err = 0;
1844
1845    ffmpeg_printf(10, ">\n");
1846
1847    //obi
1848    ffmpeg_buf_free();
1849    //obi (end)
1850
1851    if (playFilesNames == NULL)
1852    {
1853        ffmpeg_err("playFilesNames NULL\n");
1854        return cERR_CONTAINER_FFMPEG_NULL;
1855    }
1856   
1857    if (playFilesNames->szFirstFile == NULL)
1858    {
1859        ffmpeg_err("playFilesNames->szFirstFile NULL\n");
1860        return cERR_CONTAINER_FFMPEG_NULL;
1861    }
1862
1863    if (context == NULL)
1864    {
1865        ffmpeg_err("context NULL\n");
1866        return cERR_CONTAINER_FFMPEG_NULL;
1867    }
1868
1869    ffmpeg_printf(10, "filename %s\n", playFilesNames->szFirstFile);
1870    if(playFilesNames->szSecondFile)
1871    {
1872        ffmpeg_printf(10, "second filename %s\n", playFilesNames->szSecondFile);
1873    }
1874
1875    if (isContainerRunning)
1876    {
1877        ffmpeg_err("ups already running?\n");
1878        releaseMutex(__FILE__, __FUNCTION__,__LINE__);
1879        return cERR_CONTAINER_FFMPEG_RUNNING;
1880    }
1881
1882    /* initialize ffmpeg */
1883    avcodec_register_all();
1884    av_register_all();
1885    avformat_network_init();
1886
1887//obi
1888    char* tmpstr = NULL;
1889    tmpstr = readfiletomem("/mnt/config/titan.cfg", 1);
1890    if(ostrstr(tmpstr, "debuglevel=99") != NULL)
1891        av_log_set_level( AV_LOG_DEBUG );
1892    else
1893        av_log_set_callback(ffmpeg_silen_callback);
1894    free(tmpstr), tmpstr = NULL;
1895//obi (end)
1896    // SULGE DEBUG ENABLED
1897    // make ffmpeg silen
1898    //av_log_set_level( AV_LOG_DEBUG );
1899    //av_log_set_callback(ffmpeg_silen_callback);
1900 
1901    context->playback->abortRequested = 0;
1902    int32_t res = container_ffmpeg_init_av_context(context, playFilesNames->szFirstFile, 0);
1903    if(0 != res)
1904    {
1905        return res;
1906    }
1907
1908    if(playFilesNames->szSecondFile)
1909    {
1910        res = container_ffmpeg_init_av_context(context, playFilesNames->szSecondFile, 1);
1911    }
1912   
1913    if(0 != res)
1914    {
1915        return res;
1916    }
1917   
1918    terminating = 0;
1919    latestPts = 0;
1920    isContainerRunning = 1;
1921    res = container_ffmpeg_update_tracks(context, playFilesNames->szFirstFile, 1);
1922    return res;
1923}
1924
1925int32_t container_ffmpeg_update_tracks(Context_t *context, char *filename, int32_t initial)
1926{
1927    Track_t *audioTrack = NULL;
1928    Track_t *subtitleTrack = NULL;
1929   
1930    if (terminating)
1931    {
1932        return cERR_CONTAINER_FFMPEG_NO_ERROR;
1933    }
1934   
1935    if (initial && context->manager->subtitle)
1936    {
1937        context->manager->subtitle->Command(context, MANAGER_GET_TRACK, &subtitleTrack);
1938    }
1939
1940    if (context->manager->audio)
1941    {
1942        context->manager->audio->Command(context, MANAGER_GET_TRACK, &audioTrack);
1943    }
1944
1945    if (context->manager->video)
1946    {
1947        context->manager->video->Command(context, MANAGER_INIT_UPDATE, NULL);
1948    }
1949   
1950    if (context->manager->audio)
1951    {
1952        context->manager->audio->Command(context, MANAGER_INIT_UPDATE, NULL);
1953    }
1954   
1955#if 0
1956    if (context->manager->subtitle)
1957    {
1958        context->manager->subtitle->Command(context, MANAGER_INIT_UPDATE, NULL);
1959    }
1960#endif
1961
1962
1963    ffmpeg_printf(20, "dump format\n");
1964    av_dump_format(avContextTab[0], 0, filename, 0);
1965   
1966   
1967    uint32_t cAVIdx = 0;
1968    for(cAVIdx=0; cAVIdx<IPTV_AV_CONTEXT_MAX_NUM; cAVIdx+=1)
1969    {
1970        if(NULL == avContextTab[cAVIdx])
1971        {
1972            break;
1973        }
1974        AVFormatContext *avContext = avContextTab[cAVIdx];
1975        uint32_t *stream_index = NULL;
1976        uint32_t nb_stream_indexes = 0;
1977       
1978        ffmpeg_printf(1, "cAVIdx[%d]: number of streams: %d\n", cAVIdx, avContext->nb_streams);
1979       
1980        if (avContext->nb_programs > 0)
1981        {
1982            uint32_t n = 0;
1983            ffmpeg_printf(1, "cAVIdx[%d]: stream with multi programs: num of programs %d\n", cAVIdx, avContext->nb_programs);
1984            for (n = 0; n < avContext->nb_programs && (0 == nb_stream_indexes || stream_index == NULL); n++)
1985            {
1986                AVProgram *p = avContext->programs[n];
1987                if (p->nb_stream_indexes)
1988                {
1989                    if (g_sel_program_id > 0)
1990                    {
1991                        if (g_sel_program_id == p->id)
1992                        {
1993                            stream_index = p->stream_index;
1994                            nb_stream_indexes = p->nb_stream_indexes;
1995                            ffmpeg_printf(1, "cAVIdx[%d]: select PROGRAM ID: %d\n", cAVIdx, (int32_t)p->id);
1996                            break;
1997                        }
1998                    }
1999                    else
2000                    {
2001                        uint32_t m = 0;
2002                        for (m = 0; m < p->nb_stream_indexes; m++)
2003                        {
2004                            AVStream *s = avContext->streams[p->stream_index[m]];
2005                            if (get_codecpar(s)->codec_type == AVMEDIA_TYPE_VIDEO && get_codecpar(s)->width > 0)
2006                            {
2007                                ffmpeg_printf(1, "cAVIdx[%d]: PROGRAM ID: %d, width [%d]\n", cAVIdx, (int32_t)p->id, (int32_t)get_codecpar(s)->width);
2008                                stream_index = p->stream_index;
2009                                nb_stream_indexes = p->nb_stream_indexes;
2010                                break;
2011                            }
2012                        }
2013                    }
2014                }
2015            }
2016        }
2017       
2018        int32_t n = 0;
2019        for (n = 0; n < avContext->nb_streams; n++)
2020        {
2021            Track_t track;
2022            AVStream *stream = avContext->streams[n];
2023            int32_t version = 0;
2024            char *encoding = NULL;
2025           
2026            if (nb_stream_indexes > 0 && stream_index != NULL)
2027            {
2028                uint32_t isStreamFromSelProg = 0;
2029                uint32_t m = 0;
2030                for (m = 0; m < nb_stream_indexes; m++)
2031                {
2032                    if (n == stream_index[m])
2033                    {
2034                        isStreamFromSelProg = 1;
2035                        break;
2036                    }
2037                }
2038               
2039                if (!isStreamFromSelProg)
2040                    continue; // skip this stream
2041            }
2042
2043            encoding = Codec2Encoding((int32_t)get_codecpar(stream)->codec_id, (int32_t)get_codecpar(stream)->codec_type, \
2044                                      (uint8_t *)get_codecpar(stream)->extradata, \
2045                                      (int)get_codecpar(stream)->extradata_size, \
2046                                      (int)get_codecpar(stream)->profile, &version);
2047           
2048            if(encoding != NULL && !strncmp(encoding, "A_IPCM", 6) && insert_pcm_as_lpcm)
2049            {
2050                encoding = "A_LPCM";
2051            }
2052
2053            if (encoding != NULL)
2054            {
2055               ffmpeg_printf(1, "%d. encoding = %s - version %d\n", n, encoding, version);
2056            }
2057
2058            if (!stream->id)
2059            {
2060                stream->id = n;
2061            }
2062
2063            /* some values in track are unset and therefor copyTrack segfaults.
2064             * so set it by default to NULL!
2065             */
2066            memset(&track, 0, sizeof(track));
2067            track.AVIdx = cAVIdx;
2068
2069            switch (get_codecpar(stream)->codec_type)
2070            {
2071            case AVMEDIA_TYPE_VIDEO:
2072                ffmpeg_printf(10, "CODEC_TYPE_VIDEO %d\n", get_codecpar(stream)->codec_type);
2073
2074                if (encoding != NULL)
2075                {
2076                    track.type           = eTypeES;
2077                    track.version        = version;
2078
2079                    track.width          = get_codecpar(stream)->width;
2080                    track.height         = get_codecpar(stream)->height;
2081                   
2082                    /* We will return here PAR (Pixel Aspect Ratio) client need to calculate DAR(Display Aspect Ratio)
2083                     * example: PAR 64:45 DAR 16:9
2084                     *          Resolution 720x576
2085                     * Display aspect ratio = (720*64)/(576*45) = 16/9
2086                     * 0:1 is the value for invalid/unset aspect ratio -> https://trac.ffmpeg.org/ticket/3798
2087                     */
2088                    track.aspect_ratio_num = stream->sample_aspect_ratio.num;
2089                    track.aspect_ratio_den = stream->sample_aspect_ratio.den;
2090                    if (0 == track.aspect_ratio_num  || 0 == track.aspect_ratio_den)
2091                    {
2092                        track.aspect_ratio_num = get_codecpar(stream)->sample_aspect_ratio.num;
2093                        track.aspect_ratio_den = get_codecpar(stream)->sample_aspect_ratio.den;
2094                    }
2095
2096                    track.extraData      = get_codecpar(stream)->extradata;
2097                    track.extraSize      = get_codecpar(stream)->extradata_size;
2098
2099                    track.aacbuf         = 0;
2100                    track.have_aacheader = -1;
2101                   
2102                    AVRational rateRational = get_frame_rate(stream);
2103                    if (rateRational.den!=0)
2104                    {
2105                        track.frame_rate = (uint32_t)(1000 * (int64_t)(rateRational.num) / (int64_t)(rateRational.den));
2106                    }
2107                   
2108                    /* fixme: revise this */
2109                    if (track.frame_rate < 23970)
2110                    {
2111                        track.TimeScale = 1001;
2112                    }
2113                    else
2114                    {
2115                        track.TimeScale = 1000;
2116                    }
2117                   
2118                    ffmpeg_printf(10, "bit_rate       [%d]\n", get_codecpar(stream)->bit_rate);
2119                    ffmpeg_printf(10, "time_base.den  [%d]\n", stream->time_base.den);
2120                    ffmpeg_printf(10, "time_base.num  [%d]\n", stream->time_base.num);
2121                    ffmpeg_printf(10, "width          [%d]\n", get_codecpar(stream)->width);
2122                    ffmpeg_printf(10, "height         [%d]\n", get_codecpar(stream)->height);
2123                    ffmpeg_printf(10, "frame_rate num [%d]\n", rateRational.num);
2124                    ffmpeg_printf(10, "frame_rate den [%d]\n", rateRational.den);
2125
2126                    ffmpeg_printf(10, "frame_rate     [%u]\n", track.frame_rate);
2127                    ffmpeg_printf(10, "TimeScale      [%d]\n", track.TimeScale);
2128
2129                    track.Name      = "und";
2130                    track.Encoding  = encoding;
2131                    track.stream    = stream;
2132                    track.Id        = ((AVStream *) (track.stream))->id;
2133
2134                    track.duration = (int64_t)av_rescale(stream->duration, (int64_t)stream->time_base.num * 1000, stream->time_base.den);
2135                    if(stream->duration == AV_NOPTS_VALUE || 0 == strncmp(avContext->iformat->name, "dash", 4))
2136                    {
2137                        ffmpeg_printf(10, "Stream has no duration so we take the duration from context\n");
2138                        track.duration = (int64_t) avContext->duration / 1000;
2139                    }
2140                   
2141                    if (context->manager->video)
2142                    {
2143                        if (get_codecpar(stream)->codec_id == AV_CODEC_ID_MPEG4)
2144                        {
2145                            track.avCodecCtx = wrapped_avcodec_get_context(cAVIdx, stream);
2146                        }
2147                        ffmpeg_printf(1, "cAVIdx[%d]: MANAGER_ADD track VIDEO\n");
2148                        if( context->manager->video->Command(context, MANAGER_ADD, &track) < 0)
2149                        {
2150                            /* konfetti: fixme: is this a reason to return with error? */
2151                            ffmpeg_err("failed to add track %d\n", n);
2152                        }
2153                    }
2154                }
2155                else
2156                {
2157                    ffmpeg_err("codec type video but codec unknown %d\n", get_codecpar(stream)->codec_id);
2158                }
2159                break;
2160            case AVMEDIA_TYPE_AUDIO:
2161                ffmpeg_printf(10, "CODEC_TYPE_AUDIO %d\n",get_codecpar(stream)->codec_type);
2162
2163                if (encoding != NULL)
2164                {
2165                    AVDictionaryEntry *lang;
2166                    track.type = eTypeES;
2167
2168                    lang = av_dict_get(stream->metadata, "language", NULL, 0);
2169
2170                    track.Name = lang ? lang->value : "und";
2171
2172                    ffmpeg_printf(10, "Language %s\n", track.Name);
2173
2174                    track.Encoding       = encoding;
2175                    track.stream         = stream;
2176                    track.Id             = ((AVStream *) (track.stream))->id;
2177                    track.aacbuf         = 0;
2178                    track.have_aacheader = -1;
2179
2180                    track.duration       = (int64_t)av_rescale(stream->duration, (int64_t)stream->time_base.num * 1000, stream->time_base.den);
2181                    if(stream->duration == AV_NOPTS_VALUE)
2182                    {
2183                        ffmpeg_printf(10, "Stream has no duration so we take the duration from context\n");
2184                        track.duration = (int64_t) avContext->duration / 1000;
2185                    }
2186                   
2187                    if(!strncmp(encoding, "A_IPCM", 6) || !strncmp(encoding, "A_LPCM", 6))
2188                    {
2189                        track.inject_as_pcm = 1;
2190                        track.avCodecCtx = wrapped_avcodec_get_context(cAVIdx, stream);
2191                        if (track.avCodecCtx)
2192                        {
2193                            ffmpeg_printf(10, " Handle inject_as_pcm = %d\n", track.inject_as_pcm);
2194
2195                            AVCodec *codec = avcodec_find_decoder(get_codecpar(stream)->codec_id);
2196
2197                            int errorCode = avcodec_open2(track.avCodecCtx, codec, NULL);
2198                            if(codec != NULL && !errorCode)
2199                            {
2200                               ffmpeg_printf(10, "AVCODEC__INIT__SUCCESS\n");
2201                            }
2202                            else
2203                            {
2204                               ffmpeg_printf(10, "AVCODEC__INIT__FAILED error[%d]\n", errorCode);
2205                            }
2206                        }
2207                    }
2208                    else if(!strncmp(encoding, "A_PCM", 5))
2209                    {
2210                        track.inject_raw_pcm = 1;
2211                    }
2212                    else if (get_codecpar(stream)->codec_id == AV_CODEC_ID_AAC_LATM)
2213                    {
2214                        const char marker[] = "LATM";
2215                        track.aacbuflen = sizeof(marker)/sizeof(char);
2216                        track.aacbuf = malloc(track.aacbuflen);
2217                        memcpy(track.aacbuf, marker, track.aacbuflen);
2218                       
2219                        ffmpeg_printf(10, "AV_CODEC_ID_AAC_LATM no extradata ACC header should be available in each frame\n");
2220                        track.have_aacheader = 1;
2221                    }
2222                    else if(!strncmp(encoding, "A_AAC_LATM", 10))
2223                    {
2224                        ffmpeg_printf(10, "AV_CODEC_ID_AAC_LATM extradata will be used in aac writter\n");
2225                    }
2226                    else if (get_codecpar(stream)->codec_id == AV_CODEC_ID_AAC)
2227                    {
2228                        if( 0 == strncmp(avContext->iformat->name, "mpegts", 6) ||
2229                            0 == strncmp(avContext->iformat->name, "hls,", 4) )
2230                        {
2231                            const char marker[] = "ADTS";
2232                            track.aacbuflen = sizeof(marker)/sizeof(char);
2233                            track.aacbuf = malloc(track.aacbuflen);
2234                            memcpy(track.aacbuf, marker, track.aacbuflen);
2235                           
2236                            ffmpeg_printf(10, "AV_CODEC_ID_AAC no extradata ACC header should be available in each frame\n");
2237                            track.have_aacheader = 1;
2238                        }
2239                        else
2240                        {
2241                            ffmpeg_printf(10, "Create AAC ExtraData\n");
2242                            ffmpeg_printf(10, "get_codecpar(stream)->extradata_size %d\n", get_codecpar(stream)->extradata_size);
2243                            //Hexdump(get_codecpar(stream)->extradata, get_codecpar(stream)->extradata_size);
2244
2245                            /*  extradata:
2246                                13 10 56 e5 9d 48 00 (anderen cops)
2247                                object_type: 00010 2 = LC
2248                                sample_rate: 011 0 6 = 24000
2249                                chan_config: 0010 2 = Stereo
2250                                000 0
2251                                1010110 111 = 0x2b7
2252                                00101 = SBR
2253                                1
2254                                0011 = 48000
2255                                101 01001000 = 0x548
2256                                ps = 0
2257                                0000000
2258                            */
2259
2260                            int32_t object_type = 2; // LC
2261                            int32_t sample_index = aac_get_sample_rate_index(get_codecpar(stream)->sample_rate);
2262                            int32_t chan_config = get_codecpar(stream)->channels - 1;
2263                            ffmpeg_printf(1,"aac object_type %d\n", object_type);
2264                            ffmpeg_printf(1,"aac sample_index %d\n", sample_index);
2265                            ffmpeg_printf(1,"aac chan_config %d\n", chan_config);
2266                           
2267                            if (get_codecpar(stream)->extradata_size >= 2)
2268                            {
2269                                MPEG4AudioConfig m4ac;
2270                                int off = avpriv_mpeg4audio_get_config(&m4ac, get_codecpar(stream)->extradata, get_codecpar(stream)->extradata_size * 8, 1);
2271                                if (off >= 0)
2272                                {
2273                                    object_type  = m4ac.object_type;
2274                                    sample_index = m4ac.sampling_index;
2275                                    if (sample_index == 0x0f)
2276                                    {
2277                                        sample_index = aac_get_sample_rate_index(m4ac.sample_rate);
2278                                    }
2279                                    chan_config  = m4ac.chan_config;
2280                                }
2281                            }
2282                           
2283                            ffmpeg_printf(1,"aac object_type %d\n", object_type);
2284                            ffmpeg_printf(1,"aac sample_index %d\n", sample_index);
2285                            ffmpeg_printf(1,"aac chan_config %d\n", chan_config);
2286
2287                           
2288                            // https://wiki.multimedia.cx/index.php/ADTS
2289                            object_type -= 1; //ADTS - profile, the MPEG-4 Audio Object Type minus 1
2290                           
2291                            track.aacbuflen = AAC_HEADER_LENGTH;
2292                            track.aacbuf = malloc(8);
2293                            track.aacbuf[0] = 0xFF;
2294                            track.aacbuf[1] = 0xF1;
2295                            //track.aacbuf[1] |=0x8;
2296                            track.aacbuf[2] = ((object_type & 0x03) << 6)  | (sample_index << 2) | ((chan_config >> 2) & 0x01);
2297                            track.aacbuf[3] = (chan_config & 0x03) << 6;
2298                            //track.aacbuf[3]|= 0x10;
2299                            track.aacbuf[4] = 0x00;
2300                            track.aacbuf[5] = 0x1F;
2301                            track.aacbuf[6] = 0xFC;
2302
2303                            //printf("AAC_HEADER -> ");
2304                            //Hexdump(track.aacbuf,7);
2305                            track.have_aacheader = 1;
2306                        }
2307                        /*
2308                        else
2309                        {
2310                            ffmpeg_err("AV_CODEC_ID_AAC extradata not available\n");
2311                        }
2312                        */
2313
2314                    }
2315                    else if(get_codecpar(stream)->codec_id == AV_CODEC_ID_WMAV1
2316                        || get_codecpar(stream)->codec_id == AV_CODEC_ID_WMAV2
2317                        || get_codecpar(stream)->codec_id == AV_CODEC_ID_WMAPRO
2318                        || get_codecpar(stream)->codec_id == AV_CODEC_ID_WMALOSSLESS) //if (get_codecpar(stream)->extradata_size > 0)
2319                    {
2320                        ffmpeg_printf(10,"Create WMA ExtraData\n");
2321                        uint16_t channels = get_codecpar(stream)->channels;
2322                        uint32_t rate = get_codecpar(stream)->sample_rate;
2323                        uint32_t bitrate = get_codecpar(stream)->bit_rate;
2324                        uint16_t block_align = get_codecpar(stream)->block_align;
2325                        uint16_t depth = get_codecpar(stream)->bits_per_coded_sample;
2326                        uint32_t codec_data_size = get_codecpar(stream)->extradata_size;
2327                        uint8_t *codec_data_pointer = get_codecpar(stream)->extradata;
2328                       
2329                        // type_specific_data
2330                        #define WMA_VERSION_1           0x160
2331                        #define WMA_VERSION_2_9         0x161
2332                        #define WMA_VERSION_9_PRO       0x162
2333                        #define WMA_LOSSLESS            0x163
2334                        uint16_t codec_id = 0;
2335                        switch(get_codecpar(stream)->codec_id)
2336                        {
2337                            //TODO: What code for lossless ?
2338                            case AV_CODEC_ID_WMALOSSLESS:
2339                                codec_id = WMA_LOSSLESS;
2340                                break;
2341                            case AV_CODEC_ID_WMAPRO:
2342                                codec_id = WMA_VERSION_9_PRO;
2343                                break;
2344                            case AV_CODEC_ID_WMAV2:
2345                                codec_id = WMA_VERSION_2_9 ;
2346                                break;
2347                            case AV_CODEC_ID_WMAV1:
2348                            default:
2349                                codec_id = WMA_VERSION_1;
2350                                break;
2351                        }
2352#ifdef __sh__
2353                        track.aacbuflen = 104 + get_codecpar(stream)->extradata_size;
2354                        track.aacbuf = malloc(track.aacbuflen);
2355                        memset (track.aacbuf, 0, track.aacbuflen);
2356                       
2357                        uint8_t ASF_Stream_Properties_Object[16] =
2358                        {0x91,0x07,0xDC,0xB7,0xB7,0xA9,0xCF,0x11,0x8E,0xE6,0x00,0xC0,0x0C,0x20,0x53,0x65};
2359                       
2360                        memcpy(track.aacbuf + 0, ASF_Stream_Properties_Object, 16); // ASF_Stream_Properties_Object
2361                        memcpy(track.aacbuf + 16, &track.aacbuflen, 4); //FrameDateLength
2362
2363                        uint32_t sizehi = 0;
2364                        memcpy(track.aacbuf + 20, &sizehi, 4); // sizehi (not used)
2365
2366                        uint8_t ASF_Audio_Media[16] =
2367                        {0x40,0x9E,0x69,0xF8,0x4D,0x5B,0xCF,0x11,0xA8,0xFD,0x00,0x80,0x5F,0x5C,0x44,0x2B};
2368                       
2369                        memcpy(track.aacbuf + 24, ASF_Audio_Media, 16); //ASF_Audio_Media
2370
2371                        uint8_t ASF_Audio_Spread[16] =
2372                        {0x50,0xCD,0xC3,0xBF,0x8F,0x61,0xCF,0x11,0x8B,0xB2,0x00,0xAA,0x00,0xB4,0xE2,0x20};
2373                       
2374                        memcpy(track.aacbuf + 40, ASF_Audio_Spread, 16); //ASF_Audio_Spread
2375
2376                        memset(track.aacbuf + 56, 0, 4); // time_offset (not used)
2377                        memset(track.aacbuf + 60, 0, 4); // time_offset_hi (not used)
2378
2379                        uint8_t type_specific_data_length = 18 + get_codecpar(stream)->extradata_size;
2380                        memcpy(track.aacbuf + 64, &type_specific_data_length, 4); //type_specific_data_length
2381
2382                        uint8_t error_correction_data_length = 8;
2383                        memcpy(track.aacbuf + 68, &error_correction_data_length, 4); //error_correction_data_length
2384
2385                        uint16_t flags = 1; // stream_number
2386                        memcpy(track.aacbuf + 72, &flags, 2); //flags
2387
2388                        uint32_t reserved = 0;
2389                        memcpy(track.aacbuf + 74, &reserved, 4); // reserved
2390
2391                        memcpy(track.aacbuf + 78, &codec_id, 2); //codec_id
2392
2393                        uint16_t number_of_channels = get_codecpar(stream)->channels;
2394                        memcpy(track.aacbuf + 80, &number_of_channels, 2); //number_of_channels
2395
2396                        uint32_t samples_per_second = get_codecpar(stream)->sample_rate;
2397                        ffmpeg_printf(1, "samples_per_second = %d\n", samples_per_second);
2398                        memcpy(track.aacbuf + 82, &samples_per_second, 4); //samples_per_second
2399
2400                        uint32_t average_number_of_bytes_per_second = get_codecpar(stream)->bit_rate / 8;
2401                        ffmpeg_printf(1, "average_number_of_bytes_per_second = %d\n", average_number_of_bytes_per_second);
2402                        memcpy(track.aacbuf + 86, &average_number_of_bytes_per_second, 4); //average_number_of_bytes_per_second
2403
2404                        uint16_t block_alignment = get_codecpar(stream)->block_align;
2405                        ffmpeg_printf(1, "block_alignment = %d\n", block_alignment);
2406                        memcpy(track.aacbuf + 90, &block_alignment, 2); //block_alignment
2407
2408#if (LIBAVFORMAT_VERSION_MAJOR > 57) || ((LIBAVFORMAT_VERSION_MAJOR == 57) && (LIBAVFORMAT_VERSION_MINOR > 32))
2409                        enum AVSampleFormat sample_fmt = get_codecpar(stream)->format;
2410#else
2411                        enum AVSampleFormat sample_fmt = get_codecpar(stream)->sample_fmt;
2412#endif
2413                        uint16_t bits_per_sample = sample_fmt>=0 ? (sample_fmt+1)*8 : 8;
2414                        ffmpeg_printf(1, "bits_per_sample = %d (%d)\n", bits_per_sample, sample_fmt);
2415                        memcpy(track.aacbuf + 92, &bits_per_sample, 2); //bits_per_sample
2416
2417                        memcpy(track.aacbuf + 94, &get_codecpar(stream)->extradata_size, 2); //bits_per_sample
2418
2419                        memcpy(track.aacbuf + 96, get_codecpar(stream)->extradata, get_codecpar(stream)->extradata_size);
2420#else
2421                        track.aacbuflen = 18 + get_codecpar(stream)->extradata_size;
2422                        track.aacbuf = malloc(track.aacbuflen);
2423                        memset (track.aacbuf, 0, track.aacbuflen);
2424                       
2425                        uint8_t *data = track.aacbuf;
2426                        /* codec tag */
2427                        *(data++) = codec_id & 0xff;
2428                        *(data++) = (codec_id >> 8) & 0xff;
2429                        /* channels */
2430                        *(data++) = channels & 0xff;
2431                        *(data++) = (channels >> 8) & 0xff;
2432                        /* sample rate */
2433                        *(data++) = rate & 0xff;
2434                        *(data++) = (rate >> 8) & 0xff;
2435                        *(data++) = (rate >> 16) & 0xff;
2436                        *(data++) = (rate >> 24) & 0xff;
2437                        /* byte rate */
2438                        bitrate /= 8;
2439                        *(data++) = bitrate & 0xff;
2440                        *(data++) = (bitrate >> 8) & 0xff;
2441                        *(data++) = (bitrate >> 16) & 0xff;
2442                        *(data++) = (bitrate >> 24) & 0xff;
2443                        /* block align */
2444                        *(data++) = block_align & 0xff;
2445                        *(data++) = (block_align >> 8) & 0xff;
2446                        /* word size */
2447                        *(data++) = depth & 0xff;
2448                        *(data++) = (depth >> 8) & 0xff;
2449                        /* codec data size */
2450                        *(data++) = codec_data_size & 0xff;
2451                        *(data++) = (codec_data_size >> 8) & 0xff;
2452                        memcpy(data, codec_data_pointer, codec_data_size);
2453#endif
2454                        ffmpeg_printf(1, "aacbuf:\n");
2455                        //Hexdump(track.aacbuf, track.aacbuflen);
2456
2457                        //ffmpeg_printf(1, "priv_data:\n");
2458                        //Hexdump(get_codecpar(stream)->priv_data, track.aacbuflen);
2459
2460                        track.have_aacheader = 1;
2461                    }
2462                   
2463                    if (context->manager->audio)
2464                    {
2465                        ffmpeg_printf(1, "cAVIdx[%d]: MANAGER_ADD track AUDIO\n");
2466                        if (context->manager->audio->Command(context, MANAGER_ADD, &track) < 0)
2467                        {
2468                            /* konfetti: fixme: is this a reason to return with error? */
2469                            ffmpeg_err("failed to add track %d\n", n);
2470                        }
2471                    }
2472                }
2473                else //encoding != NULL
2474                {
2475                    ffmpeg_err("codec type audio but codec unknown %d\n", get_codecpar(stream)->codec_id);
2476                }
2477                break;
2478            case AVMEDIA_TYPE_SUBTITLE:
2479            {
2480                if (get_codecpar(stream)->codec_id != AV_CODEC_ID_SSA &&
2481#if LIBAVCODEC_VERSION_INT >= AV_VERSION_INT(55, 3, 100)
2482                    get_codecpar(stream)->codec_id != AV_CODEC_ID_ASS &&
2483#endif
2484                    get_codecpar(stream)->codec_id != AV_CODEC_ID_SUBRIP &&
2485                    get_codecpar(stream)->codec_id != AV_CODEC_ID_TEXT &&
2486                    get_codecpar(stream)->codec_id != AV_CODEC_ID_SRT)
2487                {
2488                    ffmpeg_printf(10, "subtitle with not supported codec codec_id[%u]\n", (uint32_t)get_codecpar(stream)->codec_id);
2489                }
2490                else if (initial && context->manager->subtitle)
2491                {
2492                    AVDictionaryEntry *lang = NULL;
2493                    memset(&track, 0, sizeof(track));
2494
2495                    ffmpeg_printf(10, "CODEC_TYPE_SUBTITLE %d\n", get_codecpar(stream)->codec_type);
2496                   
2497                    lang = av_dict_get(stream->metadata, "language", NULL, 0);
2498                    track.Name = lang ? lang->value : "und";
2499                    ffmpeg_printf(10, "Language %s\n", track.Name);
2500
2501                    track.Encoding       = encoding;
2502                    track.stream         = stream;
2503                    track.Id             = ((AVStream *) (track.stream))->id;
2504                    track.duration       = (int64_t)av_rescale(stream->duration, (int64_t)stream->time_base.num * 1000, stream->time_base.den);
2505                   
2506                    if(stream->duration == AV_NOPTS_VALUE)
2507                    {
2508                        ffmpeg_printf(10, "Stream has no duration so we take the duration from context\n");
2509                        track.duration = (int64_t) avContext->duration / 1000;
2510                    }
2511
2512                    track.extraData      = get_codecpar(stream)->extradata;
2513                    track.extraSize      = get_codecpar(stream)->extradata_size;
2514
2515                    ffmpeg_printf(1, "subtitle codec %d\n", get_codecpar(stream)->codec_id);
2516                    ffmpeg_printf(1, "subtitle width %d\n", get_codecpar(stream)->width);
2517                    ffmpeg_printf(1, "subtitle height %d\n", get_codecpar(stream)->height);
2518                    ffmpeg_printf(1, "subtitle stream %p\n", stream);
2519
2520                    ffmpeg_printf(10, "FOUND SUBTITLE %s\n", track.Name);
2521                   
2522                    if (context->manager->subtitle->Command(context, MANAGER_ADD, &track) < 0)
2523                    {
2524                        ffmpeg_err("failed to add subtitle track %d\n", n);
2525                    }
2526                }
2527                break;
2528            }
2529            case AVMEDIA_TYPE_UNKNOWN:
2530            case AVMEDIA_TYPE_DATA:
2531            case AVMEDIA_TYPE_ATTACHMENT:
2532            case AVMEDIA_TYPE_NB:
2533            default:
2534                ffmpeg_err("not handled or unknown codec_type %d\n", get_codecpar(stream)->codec_type);
2535             break;
2536            }
2537        } /* for */
2538   
2539    }
2540
2541    return cERR_CONTAINER_FFMPEG_NO_ERROR;
2542}
2543
2544static int32_t container_ffmpeg_play(Context_t *context)
2545{
2546    int32_t error = 0;
2547    int32_t ret = 0;
2548    pthread_attr_t attr;
2549
2550    ffmpeg_printf(10, "\n");
2551
2552    if ( context && context->playback && context->playback->isPlaying )
2553    {
2554        ffmpeg_printf(10, "is Playing\n");
2555    }
2556    else
2557    {
2558        ffmpeg_printf(10, "is NOT Playing\n");
2559    }
2560
2561    if (hasPlayThreadStarted == 0)
2562    {
2563        pthread_attr_init(&attr);
2564        pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
2565
2566        if((error = pthread_create(&PlayThread, &attr, (void *)&FFMPEGThread, context)) != 0)
2567        {
2568            ffmpeg_printf(10, "Error creating thread, error:%d:%s\n", error,strerror(error));
2569
2570            hasPlayThreadStarted = 0;
2571            ret = cERR_CONTAINER_FFMPEG_ERR;
2572        }
2573        else
2574        {
2575            ffmpeg_printf(10, "Created thread\n");
2576
2577            hasPlayThreadStarted = 1;
2578        }
2579    }
2580    else
2581    {
2582        ffmpeg_printf(10, "A thread already exists!\n");
2583        ret = cERR_CONTAINER_FFMPEG_ERR;
2584    }
2585
2586    ffmpeg_printf(10, "exiting with value %d\n", ret);
2587    return ret;
2588}
2589
2590static int32_t container_ffmpeg_stop(Context_t *context)
2591{
2592    int32_t ret = cERR_CONTAINER_FFMPEG_NO_ERROR;
2593    int32_t wait_time = 10; // we give 1s to close otherwise we will force close
2594
2595    ffmpeg_printf(10, "\n");
2596
2597    if (!isContainerRunning)
2598    {
2599        ffmpeg_err("Container not running\n");
2600        return cERR_CONTAINER_FFMPEG_ERR;
2601    }
2602
2603    //obi
2604    wait_time = 100;
2605    if(hasfillerThreadStarted[hasfillerThreadStartedID] == 1)
2606        hasfillerThreadStarted[hasfillerThreadStartedID] = 2; // should end
2607    while ( (hasfillerThreadStarted[hasfillerThreadStartedID] != 0) && (--wait_time) > 0 ) {
2608        ffmpeg_printf(10, "Waiting for ffmpeg filler thread to terminate itself, will try another %d times, ID=%d\n", wait_time, hasfillerThreadStartedID);
2609        usleep(100000);
2610    }
2611
2612    if (wait_time == 0) {
2613        ffmpeg_err( "Timeout waiting for filler thread!\n");
2614
2615        ret = cERR_CONTAINER_FFMPEG_ERR;
2616    }
2617    //obi (end)
2618
2619    if (context->playback)
2620    {
2621        context->playback->isPlaying = 0;
2622    }
2623
2624    while ( (hasPlayThreadStarted != 0) && (--wait_time) > 0 )
2625    {
2626        ffmpeg_printf(10, "Waiting for ffmpeg thread to terminate itself, will try another %d times\n", wait_time);
2627        usleep(100000);
2628    }
2629
2630    if (wait_time == 0)
2631    {
2632        /* force close */
2633        ffmpeg_err( "Timeout waiting for thread!\n");
2634        ret = cERR_CONTAINER_FFMPEG_ERR;
2635        /* to speed up close - we are in separate process for the moment this process will
2636         * be closed and whole resources will be free by the system 
2637         */
2638        return ret;
2639    }
2640
2641    hasPlayThreadStarted = 0;
2642    terminating = 1;
2643
2644    getMutex(__FILE__, __FUNCTION__,__LINE__);
2645   
2646    free_all_stored_avcodec_context();
2647   
2648    uint32_t i = 0;
2649    for(i=0; i<IPTV_AV_CONTEXT_MAX_NUM; i+=1)
2650    {
2651        if(NULL != avContextTab[i])
2652        {
2653            if(0 != use_custom_io[i])
2654            {
2655                /*
2656                 * Free custom IO independently to avoid segfault/bus error
2657                 * avformat_close_input do not expect custom io, so it try
2658                 * to release incorrectly
2659                 */
2660                av_freep(&(avContextTab[i]->pb->buffer));
2661                av_freep(&(avContextTab[i]->pb));
2662                use_custom_io[i] = 0;
2663            }
2664            avformat_close_input(&avContextTab[i]);
2665            //obi
2666            ffmpeg_buf_free();
2667            //obi (end)
2668            avContextTab[i] = NULL;
2669        }
2670        else
2671        {
2672            break;
2673        }
2674    }
2675
2676    if(avio_opts != NULL)
2677    {
2678        av_dict_free(&avio_opts);
2679    }
2680
2681    isContainerRunning = 0;
2682    avformat_network_deinit();
2683    ffmpeg_buf_free();
2684
2685    releaseMutex(__FILE__, __FUNCTION__,__LINE__);
2686
2687    ffmpeg_printf(10, "ret %d\n", ret);
2688    return ret;
2689}
2690
2691static int32_t container_ffmpeg_seek_bytes(off_t pos)
2692{
2693    int32_t flag = AVSEEK_FLAG_BYTE;
2694    off_t current_pos = avio_tell(avContextTab[0]->pb);
2695
2696    ffmpeg_printf(20, "seeking to position %lld (bytes)\n", pos);
2697
2698    if (current_pos > pos)
2699    {
2700        flag |= AVSEEK_FLAG_BACKWARD;
2701    }
2702
2703    if (avformat_seek_file(avContextTab[0], -1, INT64_MIN, pos, INT64_MAX, flag) < 0)
2704    {
2705        ffmpeg_err( "Error seeking\n");
2706        return cERR_CONTAINER_FFMPEG_ERR;
2707    }
2708
2709    ffmpeg_printf(30, "current_pos after seek %lld\n", avio_tell(avContextTab[0]->pb));
2710
2711    return cERR_CONTAINER_FFMPEG_NO_ERROR;
2712}
2713
2714/* seeking relative to a given byteposition N seconds ->for reverse playback needed */
2715static int32_t container_ffmpeg_seek_rel(Context_t *context, off_t pos, int64_t pts, int64_t sec)
2716{
2717    Track_t *videoTrack = NULL;
2718    Track_t *audioTrack = NULL;
2719    Track_t *current = NULL;
2720    seek_target_flag = 0;
2721
2722    ffmpeg_printf(10, "seeking %f sec relativ to %lld\n", sec, pos);
2723
2724    context->manager->video->Command(context, MANAGER_GET_TRACK, &videoTrack);
2725    context->manager->audio->Command(context, MANAGER_GET_TRACK, &audioTrack);
2726
2727    if (videoTrack != NULL)
2728    {
2729        current = videoTrack;
2730    }
2731    else if (audioTrack != NULL)
2732    {
2733        current = audioTrack;
2734    }
2735   
2736    if (current == NULL)
2737    {
2738        ffmpeg_err( "no track avaibale to seek\n");
2739        return cERR_CONTAINER_FFMPEG_ERR;
2740    }
2741
2742    if (pos == -1)
2743    {
2744        pos = avio_tell(avContextTab[0]->pb);
2745    }
2746
2747    if (pts == -1)
2748    {
2749        pts = current->pts;
2750    }
2751   
2752    if (sec < 0)
2753    {
2754        seek_target_flag |= AVSEEK_FLAG_BACKWARD;
2755    }
2756
2757    ffmpeg_printf(10, "iformat->flags %d\n", avContextTab[0]->iformat->flags);
2758#if defined(TS_BYTES_SEEKING) && TS_BYTES_SEEKING
2759    if (avContextTab[0]->iformat->flags & AVFMT_TS_DISCONT)
2760    {
2761        if (avContextTab[0]->bit_rate)
2762        {
2763            sec *= avContextTab[0]->bit_rate / 8;
2764            ffmpeg_printf(10, "bit_rate %d\n", avContextTab[0]->bit_rate);
2765        }
2766        else
2767        {
2768            sec *= 180000;
2769        }
2770
2771        pos += sec;
2772
2773        if (pos < 0)
2774        {
2775           ffmpeg_err("end of file reached\n");
2776           releaseMutex(__FILE__, __FUNCTION__,__LINE__);
2777           return cERR_CONTAINER_FFMPEG_END_OF_FILE;
2778        }
2779
2780        ffmpeg_printf(10, "1. seeking to position %lld bytes ->sec %f\n", pos, sec);
2781
2782        seek_target_bytes = pos;
2783        do_seek_target_bytes = 1;
2784
2785        return pos;
2786    }
2787    else
2788#endif
2789    {
2790        sec += pts / 90000;
2791
2792        if (sec < 0)
2793        {
2794            sec = 0;
2795        }
2796
2797        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);
2798
2799        seek_target_seconds = sec * AV_TIME_BASE;
2800        do_seek_target_seconds = 1;
2801    }
2802
2803    releaseMutex(__FILE__, __FUNCTION__,__LINE__);
2804    return cERR_CONTAINER_FFMPEG_NO_ERROR;
2805}
2806
2807static int32_t container_ffmpeg_seek(Context_t *context, int64_t sec, uint8_t absolute)
2808{
2809    Track_t *videoTrack = NULL;
2810    Track_t *audioTrack = NULL;
2811    Track_t *current = NULL;
2812    seek_target_flag = 0;
2813
2814    if (!absolute)
2815    {
2816        ffmpeg_printf(10, "seeking %f sec\n", sec);
2817        if (sec == 0)
2818        {
2819            ffmpeg_err("sec = 0 ignoring\n");
2820            return cERR_CONTAINER_FFMPEG_ERR;
2821        }
2822        else
2823        {
2824            int64_t currPts = -1;
2825            int32_t ret = context->playback->Command(context, PLAYBACK_PTS, &currPts);
2826            if (ret != 0)
2827            {
2828                ffmpeg_err("fail to get current PTS\n");
2829                return cERR_CONTAINER_FFMPEG_ERR;
2830            }
2831            sec += currPts / 90000;
2832        }
2833    }
2834   
2835    ffmpeg_printf(10, "goto %d sec\n", sec);
2836    if (sec < 0)
2837    {
2838        sec = 0;
2839    }
2840   
2841    context->manager->video->Command(context, MANAGER_GET_TRACK, &videoTrack);
2842    context->manager->audio->Command(context, MANAGER_GET_TRACK, &audioTrack);
2843
2844    if (videoTrack != NULL)
2845    {
2846        current = videoTrack;
2847    }
2848    else if (audioTrack != NULL)
2849    {
2850        current = audioTrack;
2851    }
2852    else
2853    {
2854        ffmpeg_err( "no track available to seek\n");
2855        return cERR_CONTAINER_FFMPEG_ERR;
2856    }
2857
2858    if (sec < 0)
2859    {
2860        seek_target_flag |= AVSEEK_FLAG_BACKWARD;
2861    }
2862
2863    getMutex(__FILE__, __FUNCTION__,__LINE__);
2864
2865    if (!context->playback || !context->playback->isPlaying)
2866    {
2867        releaseMutex(__FILE__, __FUNCTION__,__LINE__);
2868        return cERR_CONTAINER_FFMPEG_NO_ERROR;
2869    }
2870
2871    ffmpeg_printf(10, "iformat->flags %d\n", avContextTab[0]->iformat->flags);
2872#if defined(TS_BYTES_SEEKING) && TS_BYTES_SEEKING
2873    if (avContextTab[0]->iformat->flags & AVFMT_TS_DISCONT)
2874    {
2875        /* konfetti: for ts streams seeking frame per seconds does not work (why?).
2876        * I take this algo partly from ffplay.c.
2877        *
2878        * seeking per HTTP does still not work very good. forward seeks everytime
2879        * about 10 seconds, backward does not work.
2880        */
2881
2882        off_t pos = avio_tell(avContextTab[0]->pb);
2883
2884        ffmpeg_printf(10, "pos %lld %d\n", pos, avContextTab[0]->bit_rate);
2885
2886        if (avContextTab[0]->bit_rate)
2887        {
2888            sec *= avContextTab[0]->bit_rate / 8;
2889            ffmpeg_printf(10, "bit_rate %d\n", avContextTab[0]->bit_rate);
2890        }
2891        else
2892        {
2893            sec *= 180000;
2894        }
2895       
2896        pos = sec;
2897       
2898        if (pos < 0)
2899        {
2900           pos = 0;
2901        }
2902       
2903        ffmpeg_printf(10, "1. seeking to position %lld bytes ->sec %d\n", pos, sec);
2904
2905        seek_target_bytes = pos;
2906        do_seek_target_bytes = 1;
2907
2908    }
2909    else
2910#endif
2911    {
2912        seek_target_seconds = sec * AV_TIME_BASE;
2913        do_seek_target_seconds = 1;
2914    }
2915
2916    releaseMutex(__FILE__, __FUNCTION__,__LINE__);
2917    return cERR_CONTAINER_FFMPEG_NO_ERROR;
2918}
2919
2920static int32_t container_ffmpeg_get_length(Context_t *context, int64_t *length)
2921{
2922    ffmpeg_printf(50, "\n");
2923    Track_t * videoTrack = NULL;
2924    Track_t * audioTrack = NULL;
2925    Track_t * current = NULL;
2926
2927    if (length == NULL)
2928    {
2929        ffmpeg_err( "null pointer passed\n");
2930        return cERR_CONTAINER_FFMPEG_ERR;
2931    }
2932
2933    context->manager->video->Command(context, MANAGER_GET_TRACK, &videoTrack);
2934    context->manager->audio->Command(context, MANAGER_GET_TRACK, &audioTrack);
2935
2936    if (videoTrack != NULL)
2937    {
2938        current = videoTrack;
2939    }
2940    else if (audioTrack != NULL)
2941    {
2942        current = audioTrack;
2943    }
2944   
2945    *length = 0;
2946
2947    if (current != NULL)
2948    {
2949        if (current->duration == 0)
2950        {
2951            return cERR_CONTAINER_FFMPEG_ERR;
2952        }
2953        else
2954        {
2955            *length = current->duration / 1000;
2956        }
2957    }
2958    else
2959    {
2960        if (avContextTab[0] != NULL)
2961        {
2962            *length = avContextTab[0]->duration / 1000;
2963        }
2964        else
2965        {
2966           ffmpeg_err( "no Track not context ->no problem :D\n");
2967           return cERR_CONTAINER_FFMPEG_ERR;
2968        }
2969    }
2970
2971    return cERR_CONTAINER_FFMPEG_NO_ERROR;
2972}
2973
2974static int32_t container_ffmpeg_switch_audio(Context_t *context, int32_t *arg)
2975{
2976    ffmpeg_printf(10, "track %d\n", *arg);
2977   
2978    /* Hellmaster1024: nothing to do here!*/
2979    int64_t sec = -5;
2980    context->playback->Command(context, PLAYBACK_SEEK, (void*)&sec);
2981    return cERR_CONTAINER_FFMPEG_NO_ERROR;
2982}
2983
2984static int32_t container_ffmpeg_switch_subtitle(Context_t *context, int32_t *arg)
2985{
2986    ffmpeg_printf(10, "track %d\n", *arg);
2987   
2988    /* This is made to flush inside the buffer because
2989     * subtitles frame was already read and ignored
2990     * we seek to force ffmpeg to read once again the same data
2991     * but now we will not ignore subtitle frame
2992     */
2993    int64_t sec = -5;
2994    context->playback->Command(context, PLAYBACK_SEEK, (void*)&sec);
2995    return cERR_CONTAINER_FFMPEG_NO_ERROR;
2996}
2997
2998/* konfetti comment: I dont like the mechanism of overwriting
2999 * the pointer in infostring. This lead in most cases to
3000 * user errors, like it is in the current version (libeplayer2 <-->e2->servicemp3.cpp)
3001 * From e2 there is passed a tag=strdup here and we overwrite this
3002 * strdupped tag. This lead to dangling pointers which are never freed!
3003 * I do not free the string here because this is the wrong way. The mechanism
3004 * should be changed, or e2 should pass it in a different way...
3005 */
3006static int32_t container_ffmpeg_get_info(Context_t* context, char ** infoString)
3007{
3008    Track_t *videoTrack = NULL;
3009    Track_t *audioTrack = NULL;
3010    char     *meta = NULL;
3011
3012    ffmpeg_printf(20, ">\n");
3013
3014    if (avContextTab[0] != NULL)
3015    {
3016        if ((infoString == NULL) || (*infoString == NULL))
3017        {
3018            ffmpeg_err("infostring NULL\n");
3019            return cERR_CONTAINER_FFMPEG_ERR;
3020        }
3021
3022        ffmpeg_printf(20, "%s\n", *infoString);
3023
3024        context->manager->video->Command(context, MANAGER_GET_TRACK, &videoTrack);
3025        context->manager->audio->Command(context, MANAGER_GET_TRACK, &audioTrack);
3026
3027        if ((meta = searchMeta(avContextTab[0]->metadata, *infoString)) == NULL)
3028        {
3029            if (audioTrack != NULL)
3030            {
3031                AVStream* stream = audioTrack->stream;
3032                meta = searchMeta(stream->metadata, *infoString);
3033            }
3034
3035            if ((meta == NULL) && (videoTrack != NULL))
3036            {
3037                AVStream* stream = videoTrack->stream;
3038                meta = searchMeta(stream->metadata, *infoString);
3039            }
3040        }
3041
3042        if (meta != NULL)
3043        {
3044            *infoString = strdup(meta);
3045        }
3046        else
3047        {
3048            ffmpeg_printf(1, "no metadata found for \"%s\"\n", *infoString);
3049            *infoString = strdup("not found");
3050        }
3051    }
3052    else
3053    {
3054        ffmpeg_err("avContext NULL\n");
3055        return cERR_CONTAINER_FFMPEG_ERR;
3056    }
3057
3058    return cERR_CONTAINER_FFMPEG_NO_ERROR;
3059}
3060
3061static int32_t Command(void  *_context, ContainerCmd_t command, void *argument)
3062{
3063    Context_t  *context = (Context_t*) _context;
3064    int ret = cERR_CONTAINER_FFMPEG_NO_ERROR;
3065
3066    ffmpeg_printf(50, "Command %d\n", command);
3067
3068    if(command != CONTAINER_SET_BUFFER_SEEK_TIME &&
3069       command != CONTAINER_SET_BUFFER_SIZE &&
3070       command != CONTAINER_GET_BUFFER_SIZE &&
3071       command != CONTAINER_GET_BUFFER_STATUS &&
3072       command != CONTAINER_STOP_BUFFER &&
3073       command != CONTAINER_INIT && !avContextTab[0])
3074    {
3075        return cERR_CONTAINER_FFMPEG_ERR;
3076    }
3077   
3078   
3079    switch(command)
3080    {
3081    case CONTAINER_INIT:
3082    {
3083        PlayFiles_t *playFilesNames = (PlayFiles_t *)argument;
3084        ret = container_ffmpeg_init(context, playFilesNames);
3085        break;
3086    }
3087    case CONTAINER_PLAY: 
3088    {
3089        ret = container_ffmpeg_play(context);
3090        break;
3091    }
3092    case CONTAINER_STOP:
3093    {
3094        ret = container_ffmpeg_stop(context);
3095        break;
3096    }
3097    case CONTAINER_SEEK:
3098    {
3099        ret = container_ffmpeg_seek(context, (int64_t)*((int64_t*)argument), 0);
3100        break;
3101    }
3102    case CONTAINER_SEEK_ABS:
3103    {
3104        ret = container_ffmpeg_seek(context, (int64_t)*((int64_t*)argument), -1);
3105        break;
3106    }
3107    case CONTAINER_LENGTH:
3108    {
3109        int64_t length = 0;
3110        ret = container_ffmpeg_get_length(context, &length);
3111        *((int64_t*)argument) = (int64_t)length;
3112        break;
3113    }
3114    case CONTAINER_SWITCH_AUDIO:
3115    {
3116        ret = container_ffmpeg_switch_audio(context, (int32_t*) argument);
3117        break;
3118    }
3119    case CONTAINER_SWITCH_SUBTITLE:
3120    {
3121        ret = container_ffmpeg_switch_subtitle(context, (int32_t*) argument);
3122        break;
3123    }
3124    case CONTAINER_INFO:
3125    {
3126        ret = container_ffmpeg_get_info(context, (char **)argument);
3127        break;
3128    }
3129    case CONTAINER_STATUS:
3130    {
3131        *((int32_t*)argument) = hasPlayThreadStarted;
3132        break;
3133    }
3134    case CONTAINER_LAST_PTS:
3135    {
3136        *((int64_t*)argument) = latestPts;
3137        break;
3138    }
3139    //obi
3140    case CONTAINER_SET_BUFFER_SEEK_TIME:
3141    {
3142        ret = container_set_ffmpeg_buf_seek_time((int*) argument);
3143            break;
3144    }
3145    //obi (end)
3146    case CONTAINER_SET_BUFFER_SIZE:
3147    {
3148        ret = container_set_ffmpeg_buf_size((int32_t *) argument);
3149        break;
3150    }
3151    case CONTAINER_GET_BUFFER_SIZE:
3152    {
3153        int32_t size = 0;
3154        ret = container_get_ffmpeg_buf_size(&size);
3155        *((int32_t*)argument) = size;
3156        break;
3157    }
3158    //obi
3159    case CONTAINER_GET_BUFFER_STATUS:
3160    {
3161            int32_t size = 0;
3162            ret = container_get_fillbufstatus(&size);
3163            *((int32_t*)argument) = size;
3164            break;
3165    }
3166    case CONTAINER_STOP_BUFFER:
3167    {
3168            ret = container_stop_buffer();
3169            break;
3170    }
3171    //obi (end)
3172    default:
3173        ffmpeg_err("ContainerCmd %d not supported!\n", command);
3174        ret = cERR_CONTAINER_FFMPEG_ERR;
3175        break;
3176    }
3177
3178    ffmpeg_printf(50, "exiting with value %d\n", ret);
3179    return ret;
3180}
3181
3182static 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 };
3183
3184Container_t FFMPEGContainer = {
3185    "FFMPEG",
3186    &Command,
3187    FFMPEG_Capabilities
3188};
Note: See TracBrowser for help on using the repository browser.