예제 #1
0
static int32_t ffmpeg_read_wrapper_base(void *opaque, uint8_t *buf, int32_t buf_size, uint8_t type)
{
	int32_t len = 0;
	if (0 == PlaybackDieNow(0))
	{
		len = ffmpeg_real_read_org(opaque, buf, buf_size);
		while(len < buf_size && g_context && 0 == PlaybackDieNow(0))
		{
			if (type && len > 0)
			{
				break;
			}
			int32_t partLen = ffmpeg_real_read_org(opaque, buf+len, buf_size-len);
			if (partLen > 0)
			{
				len += partLen;
				finishTimeout = 0;
				continue;
			}
			else if (is_finish_timeout())
			{
				len = 0;
				break;
			}
			
			update_finish_timeout();
			
			usleep(100000);
			continue;
		}
	}
	//printf("len [%d] finishTimeout[%d]\n", len, finishTimeout);
	return len;
}
예제 #2
0
static int32_t ffmpeg_read(void *opaque, uint8_t *buf, int32_t buf_size)
{
	int32_t sumlen = 0;
	int32_t len = 0;
	int32_t count = 2000;

	while (sumlen < buf_size && (--count) > 0 && 0 == PlaybackDieNow(0))
	{
		len = ffmpeg_read_real(opaque, buf, buf_size - sumlen);
		sumlen += len;
		buf += len;
		if (len == 0)
		{
			usleep(10000);
		}
	}
	if (count == 0)
	{
		if (sumlen == 0)
		{
			ffmpeg_err( "Timeout waiting for buffered data (buf_size=%d sumlen=%d)!\n", buf_size, sumlen);
		}
		else
		{
			ffmpeg_err( "Timeout, not all buffered data availabel (buf_size=%d sumlen=%d)!\n", buf_size, sumlen);
		}
	}
	return sumlen;
}
예제 #3
0
파일: writer.c 프로젝트: Taapat/exteplayer3
ssize_t writev_with_retry(int fd, const struct iovec *iov, size_t ic) 
{
    ssize_t len = 0;
    int i = 0;
    for(i=0; i<ic; ++i)
    {
        write_with_retry(fd, iov[i].iov_base, iov[i].iov_len); 
        len += iov[i].iov_len;
        if(PlaybackDieNow(0))
        {
            return -1;
        }
    }
    return len;
}
예제 #4
0
파일: writer.c 프로젝트: Taapat/exteplayer3
/* ***************************** */
ssize_t write_with_retry(int fd, const void *buf, size_t size)
{
    ssize_t ret;
    int retval = 0;
    while(size > 0 && 0 == PlaybackDieNow(0))
    {
        ret = write(fd, buf, size);
        //printf("[%d] write [%lld]\n", fd, ret);
        if (ret < 0)
        {
            switch(errno)
            {
                case EINTR:
                case EAGAIN:
                    usleep(1000);
                    continue;
                default:
                    retval = -3;
                    break;
            }
            if (retval < 0)
            {
                break;
            }
        }
            
        if (ret < 0)
        {
            return ret;
        }
        
        size -= ret;
        buf += ret;
        
        if(size > 0)
        {
            if( usleep(1000) )
            {
                writer_err("usleep error \n");
            }
        }
    }
    return 0;
}
예제 #5
0
static void *TermThreadFun(void *arg)
{
    const char *socket_path = "/tmp/iptvplayer_extplayer_term_fd";
    struct sockaddr_un addr;
    int fd = -1;
    int cl = -1;
    int nfds = 1;
    fd_set readfds;
    
    unlink(socket_path);
    if ( (fd = socket(AF_UNIX, SOCK_STREAM, 0)) == -1) 
    {
        perror("TermThreadFun socket error");
        goto finish;
    }

    memset(&addr, 0, sizeof(addr));
    addr.sun_family = AF_UNIX;
    strncpy(addr.sun_path, socket_path, sizeof(addr.sun_path)-1);

    if (bind(fd, (struct sockaddr*)&addr, sizeof(addr)) == -1) 
    {
        perror("TermThreadFun bind error");
        goto finish;
    }

    if (listen(fd, 1) == -1) 
    {
        perror("TermThreadFun listen error");
        goto finish;
    }

    FD_ZERO(&readfds);
    FD_SET(g_pfd[0], &readfds);
    FD_SET(fd, &readfds);
    
    nfds = fd > g_pfd[0] ? fd + 1 : g_pfd[0] + 1;
    
    while (select(nfds, &readfds, NULL, NULL, NULL) == -1 
           && errno == EINTR)
    {
        /* Restart if interrupted by signal */
        continue;
    }
    
    if (FD_ISSET(fd, &readfds))
    {
        pthread_mutex_lock(&playbackStartMtx);
        PlaybackDieNow(1);
        if (isPlaybackStarted)
            TerminateAllSockets();
        else
            kill(getpid(), SIGINT);
        pthread_mutex_unlock(&playbackStartMtx);
    }

finish:
    close(cl);
    close(fd);
    pthread_exit(NULL);
    
}
예제 #6
0
int main(int argc, char* argv[]) 
{
    pthread_t termThread;
    int isTermThreadStarted = 0;
    
    int audioTrackIdx = -1;
    int subtitleTrackIdx = -1;
    
    uint32_t linuxDvbBufferSizeMB = 0; 
    
    char argvBuff[256];
    memset(argvBuff, '\0', sizeof(argvBuff));
    int commandRetVal = -1;
    /* inform client that we can handle additional commands */
    fprintf(stderr, "{\"EPLAYER3_EXTENDED\":{\"version\":%d}}\n", 51);

    PlayFiles_t playbackFiles;
    memset(&playbackFiles, 0x00, sizeof(playbackFiles));
    if (0 != ParseParams(argc, argv, &playbackFiles, &audioTrackIdx, &subtitleTrackIdx, &linuxDvbBufferSizeMB))
    {
        printf("Usage: exteplayer3 filePath [-u user-agent] [-c cookies] [-h headers] [-p prio] [-a] [-d] [-w] [-l] [-s] [-i] [-t audioTrackId] [-9 subtitleTrackId] [-x separateAudioUri] plabackUri\n");
        printf("[-b size] Linux DVB output buffer size in MB\n");
        printf("[-a 0|1|2|3] AAC software decoding - 1 bit - AAC ADTS, 2 - bit AAC LATM\n");
        printf("[-e] EAC3 software decoding\n");
        printf("[-3] AC3 software decoding\n");
        printf("[-d] DTS software decoding\n");
        printf("[-m] MP3 software decoding\n");
        printf("[-w] WMA1, WMA2, WMA/PRO software decoding\n");
        printf("[-l] software decoder use LPCM for injection (otherwise wav PCM will be used)\n");
        printf("[-s] software decoding as stereo [downmix]\n");
#ifdef HAVE_FLV2MPEG4_CONVERTER
        printf("[-4 0|1] - disable/enable flv2mpeg4 converter\n");
#endif
        printf("[-i] play in infinity loop\n");
        printf("[-v] switch to live TS stream mode\n");
        printf("[-n 0|1|2] rtmp force protocol implementation auto(0) native/ffmpeg(1) or librtmp(2)\n");        
        printf("[-o 0|1] set progressive download\n");
        printf("[-p value] nice value\n");
        printf("[-P value] select Program ID from multi-service stream\n");
        printf("[-t id] audio track ID switched on at start\n");
        printf("[-9 id] subtitle track ID switched on at start\n");
        printf("[-h headers] set custom HTTP headers \"Name: value\\r\\nName: value\\r\\n\"\n");
        printf("[-u user-agent] set custom http User-Agent header\n");
        printf("[-c cookies] set cookies - not working at now, please use -h instead\n");
        printf("[-x separateAudioUri]\n");
        printf("[-0 idx] video MPEG-DASH representation index\n");
        printf("[-1 idx] audio MPEG-DASH representation index\n");
        printf("[-f ffopt=ffval] any other ffmpeg option\n");
        printf("[-F path to additional file with moov atom data (used for mp4 playback in progressive download mode)\n");
        printf("[-O moov atom offset in the original file (used for mp4 playback in progressive download mode)\n");
        printf("[-S remote file size (used for mp4 playback in progressive download mode)\n");
        exit(1);
    }
    
    g_player = malloc(sizeof(Context_t));
    if(NULL == g_player)
    {
        printf("g_player allocate error\n");
        exit(1);
    }
    
    pthread_mutex_init(&playbackStartMtx, NULL);
    do 
    {
        int flags = 0;
        
        if (pipe(g_pfd) == -1)
            break;
        
        /* Make read and write ends of pipe nonblocking */
        if ((flags = fcntl(g_pfd[0], F_GETFL)) == -1)
            break;
        
        /* Make read end nonblocking */
        flags |= O_NONBLOCK;
        if (fcntl(g_pfd[0], F_SETFL, flags) == -1)
            break;
        
        if ((flags = fcntl(g_pfd[1], F_GETFL)) == -1)
            break;
        
        /* Make write end nonblocking */
        flags |= O_NONBLOCK;
        if (fcntl(g_pfd[1], F_SETFL, flags) == -1)
            break;
        
        if(0 == pthread_create(&termThread, NULL, TermThreadFun, NULL))
            isTermThreadStarted = 1;
    } while(0);
    
    g_player->playback    = &PlaybackHandler;
    g_player->output      = &OutputHandler;
    g_player->container   = &ContainerHandler;
    g_player->manager     = &ManagerHandler;

    // make sure to kill myself when parent dies
    prctl(PR_SET_PDEATHSIG, SIGKILL);

    SetBuffering();
    
    //Registrating output devices
    g_player->output->Command(g_player, OUTPUT_ADD, "audio");
    g_player->output->Command(g_player, OUTPUT_ADD, "video");
    g_player->output->Command(g_player, OUTPUT_ADD, "subtitle");
    
    //Set LINUX DVB additional write buffer size 
    if (linuxDvbBufferSizeMB)
        g_player->output->Command(g_player, OUTPUT_SET_BUFFER_SIZE, &linuxDvbBufferSizeMB);
    
    g_player->manager->video->Command(g_player, MANAGER_REGISTER_UPDATED_TRACK_INFO, UpdateVideoTrack);
    if (strncmp(playbackFiles.szFirstFile, "rtmp", 4) && strncmp(playbackFiles.szFirstFile, "ffrtmp", 4))
    {
        g_player->playback->noprobe = 1;
    }

    commandRetVal = g_player->playback->Command(g_player, PLAYBACK_OPEN, &playbackFiles);
    fprintf(stderr, "{\"PLAYBACK_OPEN\":{\"OutputName\":\"%s\", \"file\":\"%s\", \"sts\":%d}}\n", g_player->output->Name, playbackFiles.szFirstFile, commandRetVal);
    if(commandRetVal < 0)
    {
        if(NULL != g_player)
        {
            free(g_player);
        }
        return 10;
    }
    
    {
        pthread_mutex_lock(&playbackStartMtx);
        isPlaybackStarted = 1;
        pthread_mutex_unlock(&playbackStartMtx);
        
        commandRetVal = g_player->output->Command(g_player, OUTPUT_OPEN, NULL);
        fprintf(stderr, "{\"OUTPUT_OPEN\":{\"sts\":%d}}\n", commandRetVal);
        commandRetVal = g_player->playback->Command(g_player, PLAYBACK_PLAY, NULL);
        fprintf(stderr, "{\"PLAYBACK_PLAY\":{\"sts\":%d}}\n", commandRetVal);
        
        if (g_player->playback->isPlaying)
        {
            PlaybackDieNowRegisterCallback(TerminateWakeUp);
            
            HandleTracks(g_player->manager->video, (PlaybackCmd_t)-1, "vc");
            HandleTracks(g_player->manager->audio, (PlaybackCmd_t)-1, "al");
            if (audioTrackIdx >= 0)
            {
                static char cmd[128] = ""; // static to not allocate on stack
                sprintf(cmd, "ai%d\n", audioTrackIdx);
                commandRetVal = HandleTracks(g_player->manager->audio, PLAYBACK_SWITCH_AUDIO, cmd);
            }
            HandleTracks(g_player->manager->audio, (PlaybackCmd_t)-1, "ac");
            
            HandleTracks(g_player->manager->subtitle, (PlaybackCmd_t)-1, "sl");
            if (subtitleTrackIdx >= 0)
            {
                static char cmd[128] = ""; // static to not allocate on stack
                sprintf(cmd, "si%d\n", subtitleTrackIdx);
                commandRetVal = HandleTracks(g_player->manager->subtitle, PLAYBACK_SWITCH_SUBTITLE, cmd);
            }
            HandleTracks(g_player->manager->subtitle, (PlaybackCmd_t)-1, "sc");
        }

        while(g_player->playback->isPlaying && 0 == PlaybackDieNow(0))
        {
            /* we made fgets non blocking */
            if( NULL == fgets(argvBuff, sizeof(argvBuff)-1 , stdin) )
            {
                /* wait for data - max 1s */
                kbhit();
                continue;
            }

            if(0 == argvBuff[0])
            {
                continue;
            }
            
            switch(argvBuff[0])
            {
            case 'v':
            {
                HandleTracks(g_player->manager->video, (PlaybackCmd_t)-1, argvBuff);
            break;
            }
            case 'a': 
            {
                HandleTracks(g_player->manager->audio, PLAYBACK_SWITCH_AUDIO, argvBuff);
            break;
            }
            case 's': 
            {
                HandleTracks(g_player->manager->subtitle, PLAYBACK_SWITCH_SUBTITLE, argvBuff);
            break;
            }
            case 'q':
            {
                commandRetVal = g_player->playback->Command(g_player, PLAYBACK_STOP, NULL);
                fprintf(stderr, "{\"PLAYBACK_STOP\":{\"sts\":%d}}\n", commandRetVal);
                break;
            }
            case 'c':
            {
                commandRetVal = g_player->playback->Command(g_player, PLAYBACK_CONTINUE, NULL);
                fprintf(stderr, "{\"PLAYBACK_CONTINUE\":{\"sts\":%d}}\n", commandRetVal);
                break;
            }
            case 'p':
            {
                commandRetVal = g_player->playback->Command(g_player, PLAYBACK_PAUSE, NULL);
                fprintf(stderr, "{\"PLAYBACK_PAUSE\":{\"sts\":%d}}\n", commandRetVal);
                break;
            }
            case 'm':
            {
                int speed = 0;
                sscanf(argvBuff+1, "%d", &speed);

                commandRetVal = g_player->playback->Command(g_player, PLAYBACK_SLOWMOTION, &speed);
                fprintf(stderr, "{\"PLAYBACK_SLOWMOTION\":{\"speed\":%d, \"sts\":%d}}\n", speed, commandRetVal);
                break;
            }
            case 'o':
            {
                int flags = 0;
                if( 1 == sscanf(argvBuff+1, "%d", &flags) )
                {
                    progressive_playback_set(flags);
                    fprintf(stderr, "{\"PROGRESSIVE_DOWNLOAD\":{\"flags\":%d, \"sts\":0}}\n", flags);
                }
                break;
            }
            case 'f':
            {
                int speed = 0;
                sscanf(argvBuff+1, "%d", &speed);

                commandRetVal = g_player->playback->Command(g_player, PLAYBACK_FASTFORWARD, &speed);
                fprintf(stderr, "{\"PLAYBACK_FASTFORWARD\":{\"speed\":%d, \"sts\":%d}}\n", speed, commandRetVal);
                break;
            }
            case 'b': 
            {
                int speed = 0;
                sscanf(argvBuff+1, "%d", &speed);

                commandRetVal = g_player->playback->Command(g_player, PLAYBACK_FASTBACKWARD, &speed);
                fprintf(stderr, "{\"PLAYBACK_FASTBACKWARD\":{\"speed\":%d, \"sts\":%d}}\n", speed, commandRetVal);
                break;
            }
            case 'g':
            {
                int32_t gotoPos = 0;
                int64_t length = 0;
                int32_t lengthInt = 0;
                int64_t sec = 0;
                int8_t force = ('f' == argvBuff[1]) ? 1 : 0; // f - force, c - check
                
                sscanf(argvBuff+2, "%d", &gotoPos);
                if(0 <= gotoPos || force)
                {
                    commandRetVal = g_player->playback->Command(g_player, PLAYBACK_LENGTH, (void*)&length);
                    fprintf(stderr, "{\"PLAYBACK_LENGTH\":{\"length\":%"PRId64", \"sts\":%d}}\n", length, commandRetVal);

                    lengthInt = (int32_t)length;
                    if(10 <= lengthInt || force)
                    {
                        sec = gotoPos;
                        if(!force && gotoPos >= lengthInt)
                        {
                            sec = lengthInt - 10;
                        }
                        
                        commandRetVal = g_player->playback->Command(g_player, PLAYBACK_SEEK_ABS, (void*)&sec);
                        fprintf(stderr, "{\"PLAYBACK_SEEK_ABS\":{\"sec\":%"PRId64", \"sts\":%d}}\n", sec, commandRetVal);
                    }
                }
                break;
            }
            case 'k': 
            {
                int32_t seek = 0;
                int64_t length = 0;
                int32_t lengthInt = 0;
                int64_t sec = 0;
                int64_t pts = 0;
                int32_t CurrentSec = 0;
                int8_t force = ('f' == argvBuff[1]) ? 1 : 0; // f - force, c - check
                
                sscanf(argvBuff+2, "%d", &seek);
                
                commandRetVal = g_player->playback->Command(g_player, PLAYBACK_PTS, &pts);
                CurrentSec = (int32_t)(pts / 90000);
                if (0 == commandRetVal)
                {
                    fprintf(stderr, "{\"J\":{\"ms\":%"PRId64"}}\n", pts / 90);
                }
                if(0 == commandRetVal || force)
                {                    
                    commandRetVal = g_player->playback->Command(g_player, PLAYBACK_LENGTH, (void*)&length);
                    fprintf(stderr, "{\"PLAYBACK_LENGTH\":{\"length\":%"PRId64", \"sts\":%d}}\n", length, commandRetVal);
                    
                    lengthInt = (int32_t)length;
                    if(10 <= lengthInt || force )
                    {
                        int32_t ergSec = CurrentSec + seek;
                        if(!force && 0 > ergSec)
                        {
                            sec = CurrentSec * -1; // jump to start position
                        }
                        else if(!force && ergSec >= lengthInt)
                        {
                            sec = (lengthInt - CurrentSec) - 5;
                            if(0 < sec)
                            {
                                sec = 0; // no jump we are at the end
                            }
                        }
                        else
                        {
                            sec = seek;
                        }
                    }
                    commandRetVal = g_player->playback->Command(g_player, PLAYBACK_SEEK, (void*)&sec);
                    fprintf(stderr, "{\"PLAYBACK_SEEK\":{\"sec\":%"PRId64", \"sts\":%d}}\n", sec, commandRetVal);
                }
                break;
            }
            case 'l': 
            {
                int64_t length = 0;
                commandRetVal = g_player->playback->Command(g_player, PLAYBACK_LENGTH, (void*)&length);
                fprintf(stderr, "{\"PLAYBACK_LENGTH\":{\"length\":%"PRId64", \"sts\":%d}}\n", length, commandRetVal);
                break;
            }
            case 'j': 
            {
                int64_t pts = 0;
                commandRetVal = g_player->playback->Command(g_player, PLAYBACK_PTS, &pts);
                if (0 == commandRetVal)
                {
                    int64_t lastPts = 0;
                    commandRetVal = 1;
                    if (g_player->container && g_player->container->selectedContainer)
                    {
                        commandRetVal = g_player->container->selectedContainer->Command(g_player->container, CONTAINER_LAST_PTS, &lastPts);
                    }
                    
                    if (0 == commandRetVal && lastPts != INVALID_PTS_VALUE)
                    {
                        fprintf(stderr, "{\"J\":{\"ms\":%"PRId64",\"lms\":%"PRId64"}}\n", pts / 90, lastPts / 90);
                    }
                    else
                    {
                        fprintf(stderr, "{\"J\":{\"ms\":%"PRId64"}}\n", pts / 90);
                    }
                }
                break;
            }
            case 'i':
            {
                PlaybackHandler_t *ptrP = g_player->playback;
                if(ptrP)
                {
                    fprintf(stderr, "{\"PLAYBACK_INFO\":{ \"isPlaying\":%s, \"isPaused\":%s, \"isForwarding\":%s, \"isSeeking\":%s, \"isCreationPhase\":%s,", \
                    DUMP_BOOL(ptrP->isPlaying), DUMP_BOOL(ptrP->isPaused), DUMP_BOOL(ptrP->isForwarding), DUMP_BOOL(ptrP->isSeeking), DUMP_BOOL(ptrP->isCreationPhase) );
                    fprintf(stderr, "\"BackWard\":%d, \"SlowMotion\":%d, \"Speed\":%d, \"AVSync\":%d,", ptrP->BackWard, ptrP->SlowMotion, ptrP->Speed, ptrP->AVSync);
                    fprintf(stderr, " \"isVideo\":%s, \"isAudio\":%s, \"isSubtitle\":%s, \"isDvbSubtitle\":%s, \"isTeletext\":%s, \"mayWriteToFramebuffer\":%s, \"abortRequested\":%s }}\n", \
                    DUMP_BOOL(ptrP->isVideo), DUMP_BOOL(ptrP->isAudio), DUMP_BOOL(0), DUMP_BOOL(0), DUMP_BOOL(0), DUMP_BOOL(0), DUMP_BOOL(ptrP->abortRequested) );
                }
                
                break;
            }
            case 'n':
            {
                uint8_t loop = 0;
                if( '1' == argvBuff[1] || '0' == argvBuff[1] )
                {
                    PlaybackHandler_t *ptrP = g_player->playback;
                    if(ptrP)
                    {
                        ptrP->isLoopMode = '1' == argvBuff[1] ? 1 : 0;
                        fprintf(stderr, "{\"N\":{ \"isLoop\":%s }}\n", DUMP_BOOL(ptrP->isLoopMode));
                    }
                }
                break;
            }
            
            default: 
            {
                break;
            }
            }
        }

        g_player->output->Command(g_player, OUTPUT_CLOSE, NULL);
    }
    
    if(NULL != g_player)
    {
        free(g_player);
    }
    
    if (isTermThreadStarted && 1 == write(g_pfd[1], "x", 1))
    {
        pthread_join(termThread, NULL);
    }
    
    pthread_mutex_destroy(&playbackStartMtx);
    
    close(g_pfd[0]);
    close(g_pfd[1]);
    
    exit(0);
}
예제 #7
0
//flag 0: start direct
//flag 1: from thread
static void ffmpeg_filler(Context_t *context, int32_t id, int32_t* inpause, int32_t flag)
{
	int32_t len = 0;
	int32_t rwdiff = ffmpeg_buf_size;
	uint8_t buf[FILLBUFPAKET];

	if (ffmpeg_read_org == NULL || ffmpeg_seek_org == NULL)
	{
		ffmpeg_err("ffmpeg_read_org or ffmpeg_seek_org is NULL\n");
		return;
	}

	while ((flag == 0 && avContextTab[0] != NULL && avContextTab[0]->pb != NULL && rwdiff > FILLBUFDIFF)
	   ||  (flag == 1 && hasfillerThreadStarted[id] == 1 && avContextTab[0] != NULL && avContextTab[0]->pb != NULL && rwdiff > FILLBUFDIFF))
	{
		 if ( 0 == PlaybackDieNow(0))
		 {
			break;
		 }
		 if (flag == 0 && ffmpeg_buf_stop == 1)
		 {
			 ffmpeg_buf_stop = 0;
			 break;
		 }
		 getfillerMutex(__FILE__, __FUNCTION__,__LINE__);
		 //do a seek
		 if (ffmpeg_do_seek != 0)
		 {
			 ffmpeg_do_seek_ret = ffmpeg_seek_org(avContextTab[0]->pb->opaque, avContextTab[0]->pb->pos + ffmpeg_do_seek, SEEK_SET);
			 if (ffmpeg_do_seek_ret >= 0)
			 {
				 ffmpeg_buf_write = ffmpeg_buf;
				 ffmpeg_buf_read = ffmpeg_buf;
			 }
			 ffmpeg_do_seek = 0;
		 }
		 if (ffmpeg_buf_read == ffmpeg_buf_write)
		 {
			 ffmpeg_buf_valid_size = 0;
			 rwdiff = ffmpeg_buf_size;
		 }
		 if (ffmpeg_buf_read < ffmpeg_buf_write)
		 {
			 rwdiff = (ffmpeg_buf + ffmpeg_buf_size) - ffmpeg_buf_write;
			 rwdiff += ffmpeg_buf_read - ffmpeg_buf;
		 }
		 if (ffmpeg_buf_read > ffmpeg_buf_write)
		 {
			rwdiff = ffmpeg_buf_read - ffmpeg_buf_write;
		 }
		 int32_t size = FILLBUFPAKET;
		 if (rwdiff - FILLBUFDIFF < size)
		 {
			 size = (rwdiff - FILLBUFDIFF);
		 }

		 if (ffmpeg_buf_write + size > ffmpeg_buf + ffmpeg_buf_size)
		 {
			 size = (ffmpeg_buf + ffmpeg_buf_size) - ffmpeg_buf_write;
		 }
		 if (ffmpeg_buf_write == ffmpeg_buf + ffmpeg_buf_size)
		 {
			 ffmpeg_buf_write = ffmpeg_buf;
		 }
		 releasefillerMutex(__FILE__, __FUNCTION__,__LINE__);

		 if (size > 0)
		 {
			 if (flag == 1 && hasfillerThreadStarted[id] == 2)
			{
				break;
			}
			len = ffmpeg_read_org(avContextTab[0]->pb->opaque, buf, size);
			if (flag == 1 && hasfillerThreadStarted[id] == 2)
			{
				break;
			}
			ffmpeg_printf(20, "buffer-status (free buffer=%d)\n", rwdiff - FILLBUFDIFF - len);

			getfillerMutex(__FILE__, __FUNCTION__,__LINE__);
			if (len > 0)
			{
				memcpy(ffmpeg_buf_write, buf, len);
				ffmpeg_buf_write += len;
			}
			else
			{
				releasefillerMutex(__FILE__, __FUNCTION__,__LINE__);
				ffmpeg_err("read not ok ret=%d\n", len);
			 	break;
			 }
			 releasefillerMutex(__FILE__, __FUNCTION__,__LINE__);
		}
		else
		{
			//on long pause the server close the connection, so we use seek to reconnect
			if (context != NULL && context->playback != NULL && inpause != NULL)
			{
				if ((*inpause) == 0 && context->playback->isPaused)
				{
					(*inpause) = 1;
				}
				else if ((*inpause) == 1 && !context->playback->isPaused)
				{
					int32_t buflen = 0;
					(*inpause) = 0;

					getfillerMutex(__FILE__, __FUNCTION__,__LINE__);
					if (ffmpeg_buf_read < ffmpeg_buf_write)
					{
						buflen = ffmpeg_buf_write - ffmpeg_buf_read;
					}
					if (ffmpeg_buf_read > ffmpeg_buf_write)
					{
						buflen = (ffmpeg_buf + ffmpeg_buf_size) - ffmpeg_buf_read;
						buflen += ffmpeg_buf_write - ffmpeg_buf;
					} 
					ffmpeg_seek_org(avContextTab[0]->pb->opaque, avContextTab[0]->pb->pos + buflen, SEEK_SET);
					releasefillerMutex(__FILE__, __FUNCTION__,__LINE__);
				}
			}
		}
	}
}