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

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

libeplayer3 add obi marked comments für bufferio and working playback mipsel/arm/sh4

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