mirror of
https://github.com/tuxbox-neutrino/libstb-hal.git
synced 2025-08-26 23:13:16 +02:00
libeplayer3: merge buffered IO code from TDT; implement proper audio resampling
This commit is contained in:
@@ -25,11 +25,11 @@ AM_CFLAGS += \
|
|||||||
-Wno-unused -Wno-unused-parameter -Wno-unused-function -Wno-unused-variable \
|
-Wno-unused -Wno-unused-parameter -Wno-unused-function -Wno-unused-variable \
|
||||||
-Wno-sign-compare -Wno-missing-field-initializers
|
-Wno-sign-compare -Wno-missing-field-initializers
|
||||||
# silence ffmpeg deprecation warnings
|
# silence ffmpeg deprecation warnings
|
||||||
AM_CPPFLAGS = -Dattribute_deprecated=''
|
#AM_CPPFLAGS = -Dattribute_deprecated=''
|
||||||
|
|
||||||
#libeplayer3_la_LIBADD = -lpthread -lavformat -lavcodec -lavutil -lz -lass -lm -lpng
|
#libeplayer3_la_LIBADD = -lpthread -lavformat -lavcodec -lavutil -lz -lass -lm -lpng
|
||||||
|
|
||||||
LIBEPLAYER3_LIBS = libeplayer3.la -lpthread -lavformat -lavcodec -lavutil -lz -lass -lm -lpng
|
LIBEPLAYER3_LIBS = libeplayer3.la -lpthread -lavformat -lavcodec -lavutil -lavresample -lz -lass -lm -lpng
|
||||||
bin_PROGRAMS = eplayer3 meta
|
bin_PROGRAMS = eplayer3 meta
|
||||||
eplayer3_SOURCES = tools/eplayer2.c
|
eplayer3_SOURCES = tools/eplayer2.c
|
||||||
eplayer3_LDADD = $(LIBEPLAYER3_LIBS)
|
eplayer3_LDADD = $(LIBEPLAYER3_LIBS)
|
||||||
|
@@ -42,6 +42,10 @@
|
|||||||
|
|
||||||
#include <libavutil/avutil.h>
|
#include <libavutil/avutil.h>
|
||||||
#include <libavformat/avformat.h>
|
#include <libavformat/avformat.h>
|
||||||
|
#ifdef MARTII
|
||||||
|
#include <libavresample/avresample.h>
|
||||||
|
#include <libavutil/opt.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
#include "common.h"
|
#include "common.h"
|
||||||
#include "misc.h"
|
#include "misc.h"
|
||||||
@@ -55,6 +59,34 @@
|
|||||||
/* Makros/Constants */
|
/* Makros/Constants */
|
||||||
/* ***************************** */
|
/* ***************************** */
|
||||||
|
|
||||||
|
#ifdef MARTII //TDT
|
||||||
|
//for buffered io
|
||||||
|
#define FILLBUFSIZE 1048576
|
||||||
|
#define FILLBUFDIFF 1048576
|
||||||
|
#define FILLBUFPAKET 5120
|
||||||
|
#define FILLBUFSEEKTIME 3 //sec
|
||||||
|
|
||||||
|
static int ffmpeg_buf_size = FILLBUFSIZE + FILLBUFDIFF;
|
||||||
|
#ifdef MARTII
|
||||||
|
static int ffmpeg_buf_seek_time = FILLBUFSEEKTIME;
|
||||||
|
#else
|
||||||
|
static ffmpeg_buf_seek_time = FILLBUFSEEKTIME;
|
||||||
|
#endif
|
||||||
|
static int(*ffmpeg_read_org)(void *opaque, uint8_t *buf, int buf_size) = NULL;
|
||||||
|
static int64_t(*ffmpeg_seek_org)(void *opaque, int64_t offset, int whence) = NULL;
|
||||||
|
static unsigned char* ffmpeg_buf_read = NULL;
|
||||||
|
static unsigned char* ffmpeg_buf_write = NULL;
|
||||||
|
static unsigned char* ffmpeg_buf = NULL;
|
||||||
|
static pthread_t fillerThread;
|
||||||
|
static int hasfillerThreadStarted = 0;
|
||||||
|
static pthread_mutex_t fillermutex;
|
||||||
|
static int ffmpeg_buf_valid_size = 0;
|
||||||
|
static int ffmpeg_do_seek_ret = 0;
|
||||||
|
static int ffmpeg_do_seek = 0;
|
||||||
|
static int ffmpeg_buf_stop = 0;
|
||||||
|
//for buffered io (end)
|
||||||
|
#endif
|
||||||
|
|
||||||
#define FFMPEG_DEBUG
|
#define FFMPEG_DEBUG
|
||||||
|
|
||||||
#ifdef FFMPEG_DEBUG
|
#ifdef FFMPEG_DEBUG
|
||||||
@@ -102,6 +134,9 @@ static pthread_t PlayThread;
|
|||||||
static int hasPlayThreadStarted = 0;
|
static int hasPlayThreadStarted = 0;
|
||||||
|
|
||||||
static AVFormatContext* avContext = NULL;
|
static AVFormatContext* avContext = NULL;
|
||||||
|
#ifdef MARTII //TDT
|
||||||
|
static AVDictionary *avio_opts = NULL;
|
||||||
|
#endif
|
||||||
|
|
||||||
static unsigned char isContainerRunning = 0;
|
static unsigned char isContainerRunning = 0;
|
||||||
|
|
||||||
@@ -141,6 +176,23 @@ void releaseMutex(const char *filename, const const char *function, int line) {
|
|||||||
ffmpeg_printf(100, "::%d released mutex\n", line);
|
ffmpeg_printf(100, "::%d released mutex\n", line);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef MARTII //TDT
|
||||||
|
//for buffered io
|
||||||
|
void getfillerMutex(const char *filename, const char *function, int line) {
|
||||||
|
ffmpeg_printf(100, "::%d requesting mutex\n", line);
|
||||||
|
|
||||||
|
pthread_mutex_lock(&fillermutex);
|
||||||
|
|
||||||
|
ffmpeg_printf(100, "::%d received mutex\n", line);
|
||||||
|
}
|
||||||
|
|
||||||
|
void releasefillerMutex(const char *filename, const const char *function, int line) {
|
||||||
|
pthread_mutex_unlock(&fillermutex);
|
||||||
|
|
||||||
|
ffmpeg_printf(100, "::%d released mutex\n", line);
|
||||||
|
}
|
||||||
|
//for buffered io (end)
|
||||||
|
#endif
|
||||||
static char* Codec2Encoding(enum CodecID id, int* version)
|
static char* Codec2Encoding(enum CodecID id, int* version)
|
||||||
{
|
{
|
||||||
#ifdef MARTII
|
#ifdef MARTII
|
||||||
@@ -355,7 +407,12 @@ static void FFMPEGThread(Context_t *context) {
|
|||||||
int err = 0, gotlastPts = 0, audioMute = 0;
|
int err = 0, gotlastPts = 0, audioMute = 0;
|
||||||
AudioVideoOut_t avOut;
|
AudioVideoOut_t avOut;
|
||||||
|
|
||||||
#ifndef MARTII
|
#ifdef MARTII
|
||||||
|
AVAudioResampleContext *avr = NULL;
|
||||||
|
AVFrame *decoded_frame = NULL;
|
||||||
|
int out_sample_rate = 44100;
|
||||||
|
uint64_t out_channel_layout = AV_CH_LAYOUT_STEREO;
|
||||||
|
#else
|
||||||
/* Softdecoding buffer*/
|
/* Softdecoding buffer*/
|
||||||
unsigned char *samples = NULL;
|
unsigned char *samples = NULL;
|
||||||
#endif
|
#endif
|
||||||
@@ -649,73 +706,79 @@ static void FFMPEGThread(Context_t *context) {
|
|||||||
else if (audioTrack->inject_as_pcm == 1)
|
else if (audioTrack->inject_as_pcm == 1)
|
||||||
{
|
{
|
||||||
#ifdef MARTII
|
#ifdef MARTII
|
||||||
int bytesDone = 0;
|
AVCodecContext *c = ((AVStream*)(audioTrack->stream))->codec;
|
||||||
unsigned int samples_size = AVCODEC_MAX_AUDIO_FRAME_SIZE;
|
AVPacket avpkt = packet;
|
||||||
AVPacket avpkt;
|
|
||||||
avpkt = packet;
|
|
||||||
|
|
||||||
int is_planar = av_sample_fmt_is_planar(((AVStream*) audioTrack->stream)->codec->sample_fmt);
|
|
||||||
int nc = ((AVStream*) audioTrack->stream)->codec->channels;
|
|
||||||
|
|
||||||
uint8_t *samples = (unsigned char *)malloc(samples_size);
|
|
||||||
|
|
||||||
while(avpkt.size > 0)
|
while(avpkt.size > 0)
|
||||||
{
|
{
|
||||||
int decoded_data_size = samples_size;
|
|
||||||
|
|
||||||
bytesDone = avcodec_decode_audio3(( (AVStream*) audioTrack->stream)->codec,
|
int got_frame = 0;
|
||||||
(short *)(samples), &decoded_data_size, &avpkt);
|
if (!decoded_frame) {
|
||||||
if(bytesDone < 0)
|
if (!(decoded_frame = avcodec_alloc_frame())) {
|
||||||
|
fprintf(stderr, "out of memory\n");
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
} else
|
||||||
|
avcodec_get_frame_defaults(decoded_frame);
|
||||||
|
|
||||||
|
int len = avcodec_decode_audio4(c, decoded_frame, &got_frame, &avpkt);
|
||||||
|
if (len < 0)
|
||||||
break;
|
break;
|
||||||
|
|
||||||
avpkt.data += bytesDone;
|
avpkt.data += len;
|
||||||
avpkt.size -= bytesDone;
|
avpkt.size -= len;
|
||||||
|
|
||||||
if(decoded_data_size <= 0)
|
if (!got_frame)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
if (is_planar && nc > 1) {
|
int e;
|
||||||
int ds = decoded_data_size/sizeof(float)/nc;
|
if (!avr) {
|
||||||
short *shortSamples = (short *)malloc(nc * ds * sizeof(short));
|
int rates[] = { 48000, 96000, 192000, 44100, 88200, 176400, 0 };
|
||||||
float *floatSamples = (float *)samples;
|
int *rate = rates;
|
||||||
int i, j;
|
int in_rate = c->sample_rate;
|
||||||
|
while (*rate && ((*rate / in_rate) * in_rate != *rate) && (in_rate / *rate) * *rate != in_rate)
|
||||||
|
rate++;
|
||||||
|
out_sample_rate = *rate ? *rate : 44100;
|
||||||
|
avr = avresample_alloc_context();
|
||||||
|
|
||||||
for (i = 0; i < ds; i++)
|
out_channel_layout = c->channel_layout;
|
||||||
for (j = 0; j < nc; j++)
|
// player2 won't play mono
|
||||||
shortSamples[i * nc + j] = floatSamples[j * ds + i] * 32767.0;
|
out_channel_layout = (c->channel_layout == AV_CH_LAYOUT_MONO) ? AV_CH_LAYOUT_STEREO : c->channel_layout;
|
||||||
|
|
||||||
free(samples);
|
av_opt_set_int(avr, "in_channel_layout", c->channel_layout, 0);
|
||||||
samples = (unsigned char *) shortSamples;
|
av_opt_set_int(avr, "out_channel_layout", out_channel_layout, 0);
|
||||||
} else if (nc == 1) {
|
av_opt_set_int(avr, "in_sample_rate", c->sample_rate, 0);
|
||||||
// mono doesn't seem to work ... convert to stereo
|
av_opt_set_int(avr, "out_sample_rate", out_sample_rate, 0);
|
||||||
int ds = decoded_data_size/sizeof(float);
|
av_opt_set_int(avr, "in_sample_fmt", c->sample_fmt, 0);
|
||||||
short *shortSamples = (short *)samples;
|
av_opt_set_int(avr, "out_sample_fmt", AV_SAMPLE_FMT_S16, 0);
|
||||||
float *floatSamples = (float *)samples;
|
|
||||||
int i;
|
|
||||||
|
|
||||||
for (i = 0; i < ds; i++)
|
e = avresample_open(avr);
|
||||||
shortSamples[2 * i] = shortSamples[2 * i + 1] = floatSamples[i] * 32767.0;
|
if (e < 0)
|
||||||
|
fprintf(stderr, "avresample_open: %d\n", -e);
|
||||||
decoded_data_size *= 2;
|
|
||||||
nc++;
|
|
||||||
} else {
|
|
||||||
int ds = decoded_data_size/sizeof(float);
|
|
||||||
short *shortSamples = (short *)samples;
|
|
||||||
float *floatSamples = (float *)samples;
|
|
||||||
int i;
|
|
||||||
|
|
||||||
for (i = 0; i < ds; i++)
|
|
||||||
shortSamples[i] = floatSamples[i] * 32767.0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
uint8_t *output = NULL;
|
||||||
|
int in_samples = decoded_frame->nb_samples;
|
||||||
|
int out_linesize;
|
||||||
|
int out_samples = avresample_available(avr)
|
||||||
|
+ av_rescale_rnd(avresample_get_delay(avr) + in_samples, out_sample_rate, c->sample_rate, AV_ROUND_UP);
|
||||||
|
e = av_samples_alloc(&output, &out_linesize, 2, out_samples, AV_SAMPLE_FMT_S16, 1);
|
||||||
|
if (e < 0) {
|
||||||
|
fprintf(stderr, "av_samples_alloc: %d\n", -e);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
out_samples = avresample_convert(avr, &output, out_linesize, out_samples,
|
||||||
|
&decoded_frame->data[0], decoded_frame->linesize[0], in_samples);
|
||||||
pcmPrivateData_t extradata;
|
pcmPrivateData_t extradata;
|
||||||
extradata.uNoOfChannels = nc;
|
|
||||||
extradata.uSampleRate = ((AVStream*) audioTrack->stream)->codec->sample_rate;
|
extradata.uSampleRate = out_sample_rate;
|
||||||
|
extradata.uNoOfChannels = av_get_channel_layout_nb_channels(out_channel_layout);
|
||||||
extradata.uBitsPerSample = 16;
|
extradata.uBitsPerSample = 16;
|
||||||
extradata.bLittleEndian = 1;
|
extradata.bLittleEndian = 1;
|
||||||
|
|
||||||
avOut.data = samples;
|
avOut.data = output;
|
||||||
avOut.len = (decoded_data_size * sizeof(short))/sizeof(float);
|
avOut.len = out_samples * sizeof(short) * c->channels;
|
||||||
|
|
||||||
avOut.pts = pts;
|
avOut.pts = pts;
|
||||||
avOut.extradata = (unsigned char *) &extradata;
|
avOut.extradata = (unsigned char *) &extradata;
|
||||||
@@ -731,8 +794,8 @@ static void FFMPEGThread(Context_t *context) {
|
|||||||
#endif
|
#endif
|
||||||
if (context->output->audio->Write(context, &avOut) < 0)
|
if (context->output->audio->Write(context, &avOut) < 0)
|
||||||
ffmpeg_err("writing data to audio device failed\n");
|
ffmpeg_err("writing data to audio device failed\n");
|
||||||
|
av_freep(&output);
|
||||||
}
|
}
|
||||||
free(samples);
|
|
||||||
#else
|
#else
|
||||||
int bytesDone = 0;
|
int bytesDone = 0;
|
||||||
unsigned int samples_size = AVCODEC_MAX_AUDIO_FRAME_SIZE;
|
unsigned int samples_size = AVCODEC_MAX_AUDIO_FRAME_SIZE;
|
||||||
@@ -750,6 +813,7 @@ static void FFMPEGThread(Context_t *context) {
|
|||||||
bytesDone = avcodec_decode_audio3(( (AVStream*) audioTrack->stream)->codec,
|
bytesDone = avcodec_decode_audio3(( (AVStream*) audioTrack->stream)->codec,
|
||||||
(short *)(samples), &decoded_data_size, &avpkt);
|
(short *)(samples), &decoded_data_size, &avpkt);
|
||||||
|
|
||||||
|
|
||||||
if(bytesDone < 0) // Error Happend
|
if(bytesDone < 0) // Error Happend
|
||||||
break;
|
break;
|
||||||
|
|
||||||
@@ -1019,7 +1083,14 @@ static void FFMPEGThread(Context_t *context) {
|
|||||||
|
|
||||||
} /* while */
|
} /* while */
|
||||||
|
|
||||||
#ifndef MARTII
|
#ifdef MARTII
|
||||||
|
if (avr) {
|
||||||
|
avresample_close(avr);
|
||||||
|
avresample_free(&avr);
|
||||||
|
if (decoded_frame)
|
||||||
|
avcodec_free_frame(&decoded_frame);
|
||||||
|
}
|
||||||
|
#else
|
||||||
// Freeing the allocated buffer for softdecoding
|
// Freeing the allocated buffer for softdecoding
|
||||||
if (samples != NULL) {
|
if (samples != NULL) {
|
||||||
free(samples);
|
free(samples);
|
||||||
@@ -1031,6 +1102,413 @@ static void FFMPEGThread(Context_t *context) {
|
|||||||
|
|
||||||
ffmpeg_printf(10, "terminating\n");
|
ffmpeg_printf(10, "terminating\n");
|
||||||
}
|
}
|
||||||
|
#ifdef MARTII //TDT
|
||||||
|
//for buffered io
|
||||||
|
#ifdef MARTII
|
||||||
|
int container_set_ffmpeg_buf_seek_time(int* _time)
|
||||||
|
#else
|
||||||
|
int container_set_ffmpeg_buf_seek_time(int* time)
|
||||||
|
#endif
|
||||||
|
{
|
||||||
|
#ifdef MARTII
|
||||||
|
ffmpeg_buf_seek_time = (*_time);
|
||||||
|
#else
|
||||||
|
ffmpeg_buf_seek_time = (*time);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
return cERR_CONTAINER_FFMPEG_NO_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
int container_set_ffmpeg_buf_size(int* size)
|
||||||
|
{
|
||||||
|
if(ffmpeg_buf == NULL)
|
||||||
|
{
|
||||||
|
if(*size == 0)
|
||||||
|
ffmpeg_buf_size = 0;
|
||||||
|
else
|
||||||
|
ffmpeg_buf_size = (*size) + FILLBUFDIFF;
|
||||||
|
}
|
||||||
|
|
||||||
|
return cERR_CONTAINER_FFMPEG_NO_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
int container_get_ffmpeg_buf_size(int* size)
|
||||||
|
{
|
||||||
|
*size = ffmpeg_buf_size - FILLBUFDIFF;
|
||||||
|
|
||||||
|
return cERR_CONTAINER_FFMPEG_NO_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
int container_get_fillbufstatus(int* size)
|
||||||
|
{
|
||||||
|
int rwdiff = 0;
|
||||||
|
|
||||||
|
if(ffmpeg_buf != NULL && ffmpeg_buf_read != NULL && ffmpeg_buf_write != NULL)
|
||||||
|
{
|
||||||
|
if(ffmpeg_buf_read < ffmpeg_buf_write)
|
||||||
|
rwdiff = ffmpeg_buf_write - ffmpeg_buf_read;
|
||||||
|
if(ffmpeg_buf_read > ffmpeg_buf_write)
|
||||||
|
{
|
||||||
|
rwdiff = (ffmpeg_buf + ffmpeg_buf_size) - ffmpeg_buf_read;
|
||||||
|
rwdiff += ffmpeg_buf_write - ffmpeg_buf;
|
||||||
|
}
|
||||||
|
|
||||||
|
*size = rwdiff;
|
||||||
|
}
|
||||||
|
|
||||||
|
return cERR_CONTAINER_FFMPEG_NO_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
int container_stop_buffer()
|
||||||
|
{
|
||||||
|
ffmpeg_buf_stop = 1;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
//flag 0: start direct
|
||||||
|
//flag 1: from thread
|
||||||
|
void ffmpeg_filler(Context_t *context, int* inpause, int flag)
|
||||||
|
{
|
||||||
|
int len = 0;
|
||||||
|
int 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 && avContext != NULL && avContext->pb != NULL && rwdiff > FILLBUFDIFF) || (flag == 1 && hasfillerThreadStarted != 2 && avContext != NULL && avContext->pb != NULL && rwdiff > FILLBUFDIFF) )
|
||||||
|
{
|
||||||
|
if(flag == 0 && ffmpeg_buf_stop == 1)
|
||||||
|
{
|
||||||
|
ffmpeg_buf_stop = 0;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
getfillerMutex(FILENAME, __FUNCTION__,__LINE__);
|
||||||
|
//do a seek
|
||||||
|
if(ffmpeg_do_seek != 0)
|
||||||
|
{
|
||||||
|
ffmpeg_do_seek_ret = ffmpeg_seek_org(avContext->pb->opaque, avContext->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;
|
||||||
|
|
||||||
|
int 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(FILENAME, __FUNCTION__,__LINE__);
|
||||||
|
|
||||||
|
if(size > 0)
|
||||||
|
{
|
||||||
|
if(flag == 1 && hasfillerThreadStarted == 2) break;
|
||||||
|
len = ffmpeg_read_org(avContext->pb->opaque, buf, size);
|
||||||
|
if(flag == 1 && hasfillerThreadStarted == 2) break;
|
||||||
|
|
||||||
|
ffmpeg_printf(20, "buffer-status (free buffer=%d)\n", rwdiff - FILLBUFDIFF - len);
|
||||||
|
|
||||||
|
getfillerMutex(FILENAME, __FUNCTION__,__LINE__);
|
||||||
|
if(len > 0)
|
||||||
|
{
|
||||||
|
memcpy(ffmpeg_buf_write, buf, len);
|
||||||
|
ffmpeg_buf_write += len;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
releasefillerMutex(FILENAME, __FUNCTION__,__LINE__);
|
||||||
|
ffmpeg_err("read not ok ret=%d\n", len);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
releasefillerMutex(FILENAME, __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)
|
||||||
|
{
|
||||||
|
int buflen = 0;
|
||||||
|
(*inpause) = 0;
|
||||||
|
|
||||||
|
getfillerMutex(FILENAME, __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(avContext->pb->opaque, avContext->pb->pos + buflen, SEEK_SET);
|
||||||
|
releasefillerMutex(FILENAME, __FUNCTION__,__LINE__);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void ffmpeg_fillerTHREAD(Context_t *context)
|
||||||
|
{
|
||||||
|
ffmpeg_printf(10, "Running!\n");
|
||||||
|
int inpause = 0;
|
||||||
|
|
||||||
|
while(hasfillerThreadStarted != 2)
|
||||||
|
{
|
||||||
|
ffmpeg_filler(context, &inpause, 1);
|
||||||
|
usleep(10000);
|
||||||
|
}
|
||||||
|
|
||||||
|
hasfillerThreadStarted = 0;
|
||||||
|
|
||||||
|
ffmpeg_printf(10, "terminating\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
static int ffmpeg_start_fillerTHREAD(Context_t *context)
|
||||||
|
{
|
||||||
|
int error;
|
||||||
|
int ret = 0;
|
||||||
|
pthread_attr_t attr;
|
||||||
|
|
||||||
|
ffmpeg_printf(10, "\n");
|
||||||
|
|
||||||
|
if ( context && context->playback && context->playback->isPlaying )
|
||||||
|
ffmpeg_printf(10, "is Playing\n");
|
||||||
|
else
|
||||||
|
ffmpeg_printf(10, "is NOT Playing\n");
|
||||||
|
|
||||||
|
if (hasfillerThreadStarted == 0)
|
||||||
|
{
|
||||||
|
pthread_attr_init(&attr);
|
||||||
|
pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
|
||||||
|
|
||||||
|
if((error = pthread_create(&fillerThread, &attr, (void *)&ffmpeg_fillerTHREAD, context)) != 0)
|
||||||
|
{
|
||||||
|
ffmpeg_printf(10, "Error creating filler thread, error:%d:%s\n", error,strerror(error));
|
||||||
|
|
||||||
|
hasfillerThreadStarted = 0;
|
||||||
|
ret = cERR_CONTAINER_FFMPEG_ERR;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
ffmpeg_printf(10, "Created filler thread\n");
|
||||||
|
|
||||||
|
hasfillerThreadStarted = 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
ffmpeg_printf(10, "A filler thread already exists!\n");
|
||||||
|
|
||||||
|
ret = cERR_CONTAINER_FFMPEG_ERR;
|
||||||
|
}
|
||||||
|
|
||||||
|
ffmpeg_printf(10, "exiting with value %d\n", ret);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
int ffmpeg_read_real(void *opaque, uint8_t *buf, int buf_size)
|
||||||
|
{
|
||||||
|
int len = buf_size;
|
||||||
|
int rwdiff = 0;
|
||||||
|
|
||||||
|
if(buf_size > 0)
|
||||||
|
{
|
||||||
|
getfillerMutex(FILENAME, __FUNCTION__,__LINE__);
|
||||||
|
|
||||||
|
if(ffmpeg_buf_read < ffmpeg_buf_write)
|
||||||
|
rwdiff = ffmpeg_buf_write - ffmpeg_buf_read;
|
||||||
|
if(ffmpeg_buf_read > ffmpeg_buf_write)
|
||||||
|
{
|
||||||
|
rwdiff = (ffmpeg_buf + ffmpeg_buf_size) - ffmpeg_buf_read;
|
||||||
|
rwdiff += ffmpeg_buf_write - ffmpeg_buf;
|
||||||
|
}
|
||||||
|
rwdiff--;
|
||||||
|
|
||||||
|
if(len > rwdiff)
|
||||||
|
len = rwdiff;
|
||||||
|
|
||||||
|
if(ffmpeg_buf_read + len > ffmpeg_buf + ffmpeg_buf_size)
|
||||||
|
len = (ffmpeg_buf + ffmpeg_buf_size) - ffmpeg_buf_read;
|
||||||
|
|
||||||
|
if(len > 0)
|
||||||
|
{
|
||||||
|
memcpy(buf, ffmpeg_buf_read, len);
|
||||||
|
ffmpeg_buf_read += len;
|
||||||
|
|
||||||
|
if(ffmpeg_buf_valid_size < FILLBUFDIFF)
|
||||||
|
{
|
||||||
|
if(ffmpeg_buf_valid_size + len > FILLBUFDIFF)
|
||||||
|
ffmpeg_buf_valid_size = FILLBUFDIFF;
|
||||||
|
else
|
||||||
|
ffmpeg_buf_valid_size += len;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(ffmpeg_buf_read == ffmpeg_buf + ffmpeg_buf_size)
|
||||||
|
ffmpeg_buf_read = ffmpeg_buf;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
len = 0;
|
||||||
|
|
||||||
|
releasefillerMutex(FILENAME, __FUNCTION__,__LINE__);
|
||||||
|
}
|
||||||
|
|
||||||
|
return len;
|
||||||
|
}
|
||||||
|
|
||||||
|
int ffmpeg_read(void *opaque, uint8_t *buf, int buf_size)
|
||||||
|
{
|
||||||
|
int sumlen = 0;
|
||||||
|
int len = 0;
|
||||||
|
int count = 2000;
|
||||||
|
|
||||||
|
while(sumlen < buf_size && (--count) > 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;
|
||||||
|
}
|
||||||
|
|
||||||
|
int64_t ffmpeg_seek(void *opaque, int64_t offset, int whence)
|
||||||
|
{
|
||||||
|
int64_t diff;
|
||||||
|
int rwdiff = 0;
|
||||||
|
whence &= ~AVSEEK_FORCE;
|
||||||
|
|
||||||
|
if(whence != SEEK_CUR && whence != SEEK_SET)
|
||||||
|
return AVERROR(EINVAL);
|
||||||
|
|
||||||
|
if(whence == SEEK_CUR)
|
||||||
|
diff = offset;
|
||||||
|
else
|
||||||
|
diff = offset - avContext->pb->pos;
|
||||||
|
|
||||||
|
if(diff == 0)
|
||||||
|
return avContext->pb->pos;
|
||||||
|
|
||||||
|
getfillerMutex(FILENAME, __FUNCTION__,__LINE__);
|
||||||
|
|
||||||
|
if(ffmpeg_buf_read < ffmpeg_buf_write)
|
||||||
|
rwdiff = ffmpeg_buf_write - ffmpeg_buf_read;
|
||||||
|
if(ffmpeg_buf_read > ffmpeg_buf_write)
|
||||||
|
{
|
||||||
|
rwdiff = (ffmpeg_buf + ffmpeg_buf_size) - ffmpeg_buf_read;
|
||||||
|
rwdiff += ffmpeg_buf_write - ffmpeg_buf;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(diff > 0 && diff < rwdiff)
|
||||||
|
{
|
||||||
|
/* can do the seek inside the buffer */
|
||||||
|
ffmpeg_printf(20, "buffer-seek diff=%lld\n", diff);
|
||||||
|
if(diff > (ffmpeg_buf + ffmpeg_buf_size) - ffmpeg_buf_read)
|
||||||
|
ffmpeg_buf_read = ffmpeg_buf + (diff - ((ffmpeg_buf + ffmpeg_buf_size) - ffmpeg_buf_read));
|
||||||
|
else
|
||||||
|
ffmpeg_buf_read = ffmpeg_buf_read + diff;
|
||||||
|
}
|
||||||
|
else if(diff < 0 && diff * -1 < ffmpeg_buf_valid_size)
|
||||||
|
{
|
||||||
|
/* can do the seek inside the buffer */
|
||||||
|
ffmpeg_printf(20, "buffer-seek diff=%lld\n", diff);
|
||||||
|
int tmpdiff = diff * -1;
|
||||||
|
if(tmpdiff > ffmpeg_buf_read - ffmpeg_buf)
|
||||||
|
ffmpeg_buf_read = (ffmpeg_buf + ffmpeg_buf_size) - (tmpdiff - (ffmpeg_buf_read - ffmpeg_buf));
|
||||||
|
else
|
||||||
|
ffmpeg_buf_read = ffmpeg_buf_read - tmpdiff;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
releasefillerMutex(FILENAME, __FUNCTION__,__LINE__);
|
||||||
|
ffmpeg_printf(20, "real-seek diff=%lld\n", diff);
|
||||||
|
|
||||||
|
ffmpeg_do_seek_ret = 0;
|
||||||
|
ffmpeg_do_seek = diff;
|
||||||
|
while(ffmpeg_do_seek != 0)
|
||||||
|
usleep(100000);
|
||||||
|
|
||||||
|
ffmpeg_do_seek = 0;
|
||||||
|
if(ffmpeg_do_seek_ret < 0)
|
||||||
|
{
|
||||||
|
ffmpeg_err("seek not ok ret=%d\n", ffmpeg_do_seek_ret);
|
||||||
|
return ffmpeg_do_seek_ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
//fill buffer
|
||||||
|
int count = ffmpeg_buf_seek_time * 10;
|
||||||
|
int size = 0;
|
||||||
|
|
||||||
|
container_get_fillbufstatus(&size);
|
||||||
|
while(size < ffmpeg_buf_size - FILLBUFDIFF && (--count) > 0)
|
||||||
|
{
|
||||||
|
usleep(100000);
|
||||||
|
container_get_fillbufstatus(&size);
|
||||||
|
}
|
||||||
|
|
||||||
|
return avContext->pb->pos + diff;
|
||||||
|
}
|
||||||
|
|
||||||
|
releasefillerMutex(FILENAME, __FUNCTION__,__LINE__);
|
||||||
|
return avContext->pb->pos + diff;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void ffmpeg_buf_free()
|
||||||
|
{
|
||||||
|
ffmpeg_read_org = NULL;
|
||||||
|
ffmpeg_seek_org = NULL;
|
||||||
|
ffmpeg_buf_read = NULL;
|
||||||
|
ffmpeg_buf_write = NULL;
|
||||||
|
free(ffmpeg_buf);
|
||||||
|
ffmpeg_buf = NULL;
|
||||||
|
ffmpeg_buf_valid_size = 0;
|
||||||
|
ffmpeg_do_seek_ret = 0;
|
||||||
|
ffmpeg_do_seek = 0;
|
||||||
|
ffmpeg_buf_stop = 0;
|
||||||
|
}
|
||||||
|
//for buffered io (end)
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
/* **************************** */
|
/* **************************** */
|
||||||
/* Container part for ffmpeg */
|
/* Container part for ffmpeg */
|
||||||
@@ -1067,6 +1545,9 @@ int container_ffmpeg_init(Context_t *context, char * filename)
|
|||||||
/* initialize ffmpeg */
|
/* initialize ffmpeg */
|
||||||
avcodec_register_all();
|
avcodec_register_all();
|
||||||
av_register_all();
|
av_register_all();
|
||||||
|
#ifdef MARTII //TDT
|
||||||
|
avformat_network_init();
|
||||||
|
#endif
|
||||||
|
|
||||||
#if LIBAVCODEC_VERSION_MAJOR < 54
|
#if LIBAVCODEC_VERSION_MAJOR < 54
|
||||||
if ((err = av_open_input_file(&avContext, filename, NULL, 0, NULL)) != 0) {
|
if ((err = av_open_input_file(&avContext, filename, NULL, 0, NULL)) != 0) {
|
||||||
@@ -1083,6 +1564,12 @@ int container_ffmpeg_init(Context_t *context, char * filename)
|
|||||||
av_strerror(err, error, 512);
|
av_strerror(err, error, 512);
|
||||||
ffmpeg_err("Cause: %s\n", error);
|
ffmpeg_err("Cause: %s\n", error);
|
||||||
|
|
||||||
|
#ifdef MARTII //TDT
|
||||||
|
if(avio_opts != NULL) av_dict_free(&avio_opts);
|
||||||
|
//for buffered io
|
||||||
|
ffmpeg_buf_free();
|
||||||
|
//for buffered io (end)
|
||||||
|
#endif
|
||||||
releaseMutex(FILENAME, __FUNCTION__,__LINE__);
|
releaseMutex(FILENAME, __FUNCTION__,__LINE__);
|
||||||
return cERR_CONTAINER_FFMPEG_OPEN;
|
return cERR_CONTAINER_FFMPEG_OPEN;
|
||||||
}
|
}
|
||||||
@@ -1107,12 +1594,61 @@ int container_ffmpeg_init(Context_t *context, char * filename)
|
|||||||
* but the file is played back well. so remove this
|
* but the file is played back well. so remove this
|
||||||
* until other works are done and we can prove this.
|
* until other works are done and we can prove this.
|
||||||
*/
|
*/
|
||||||
|
#ifdef MARTII
|
||||||
|
avformat_close_input(&avContext);
|
||||||
|
#else
|
||||||
av_close_input_file(avContext);
|
av_close_input_file(avContext);
|
||||||
|
#endif
|
||||||
|
//for buffered io
|
||||||
|
ffmpeg_buf_free();
|
||||||
|
//for buffered io (end)
|
||||||
releaseMutex(FILENAME, __FUNCTION__,__LINE__);
|
releaseMutex(FILENAME, __FUNCTION__,__LINE__);
|
||||||
return cERR_CONTAINER_FFMPEG_STREAM;
|
return cERR_CONTAINER_FFMPEG_STREAM;
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef MARTII //TDT
|
||||||
|
//for buffered io
|
||||||
|
#if LIBAVCODEC_VERSION_MAJOR >= 54
|
||||||
|
ffmpeg_read_org = NULL;
|
||||||
|
ffmpeg_seek_org = NULL;
|
||||||
|
ffmpeg_buf_read = NULL;
|
||||||
|
ffmpeg_buf_write = NULL;
|
||||||
|
ffmpeg_buf = NULL;
|
||||||
|
ffmpeg_buf_valid_size = 0;
|
||||||
|
ffmpeg_do_seek_ret = 0;
|
||||||
|
ffmpeg_do_seek = 0;
|
||||||
|
ffmpeg_buf_stop = 0;
|
||||||
|
|
||||||
|
if(strstr(filename, "http://") == filename)
|
||||||
|
{
|
||||||
|
if(ffmpeg_buf_size > 0 && ffmpeg_buf_size > FILLBUFDIFF + FILLBUFPAKET)
|
||||||
|
{
|
||||||
|
if(avContext != NULL && avContext->pb != NULL)
|
||||||
|
{
|
||||||
|
ffmpeg_buf = av_malloc(ffmpeg_buf_size);
|
||||||
|
|
||||||
|
if(ffmpeg_buf != NULL)
|
||||||
|
{
|
||||||
|
ffmpeg_printf(10, "buffer size=%d\n", ffmpeg_buf_size);
|
||||||
|
|
||||||
|
ffmpeg_read_org = avContext->pb->read_packet;
|
||||||
|
avContext->pb->read_packet = ffmpeg_read;
|
||||||
|
ffmpeg_seek_org = avContext->pb->seek;
|
||||||
|
avContext->pb->seek = ffmpeg_seek;
|
||||||
|
ffmpeg_buf_read = ffmpeg_buf;
|
||||||
|
ffmpeg_buf_write = ffmpeg_buf;
|
||||||
|
|
||||||
|
//fill buffer
|
||||||
|
ffmpeg_filler(context, NULL, 0);
|
||||||
|
ffmpeg_start_fillerTHREAD(context);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
//for buffered io (end)
|
||||||
|
#endif
|
||||||
ffmpeg_printf(20, "dump format\n");
|
ffmpeg_printf(20, "dump format\n");
|
||||||
|
|
||||||
#if LIBAVCODEC_VERSION_MAJOR < 54
|
#if LIBAVCODEC_VERSION_MAJOR < 54
|
||||||
@@ -1255,7 +1791,11 @@ int container_ffmpeg_init(Context_t *context, char * filename)
|
|||||||
AVCodec *codec = avcodec_find_decoder(stream->codec->codec_id);
|
AVCodec *codec = avcodec_find_decoder(stream->codec->codec_id);
|
||||||
|
|
||||||
//( (AVStream*) audioTrack->stream)->codec->flags |= CODEC_FLAG_TRUNCATED;
|
//( (AVStream*) audioTrack->stream)->codec->flags |= CODEC_FLAG_TRUNCATED;
|
||||||
|
#ifdef MARTII
|
||||||
|
if(codec != NULL && !avcodec_open2(stream->codec, codec, NULL))
|
||||||
|
#else
|
||||||
if(codec != NULL && !avcodec_open(stream->codec, codec))
|
if(codec != NULL && !avcodec_open(stream->codec, codec))
|
||||||
|
#endif
|
||||||
printf("AVCODEC__INIT__SUCCESS\n");
|
printf("AVCODEC__INIT__SUCCESS\n");
|
||||||
else
|
else
|
||||||
printf("AVCODEC__INIT__FAILED\n");
|
printf("AVCODEC__INIT__FAILED\n");
|
||||||
@@ -1565,6 +2105,28 @@ static int container_ffmpeg_stop(Context_t *context) {
|
|||||||
context->playback->isPlaying = 0;
|
context->playback->isPlaying = 0;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#ifdef MARTII //TDT
|
||||||
|
//for buffered io
|
||||||
|
wait_time = 100;
|
||||||
|
if(hasfillerThreadStarted == 1)
|
||||||
|
hasfillerThreadStarted = 2; // should end
|
||||||
|
while ( (hasfillerThreadStarted != 0) && (--wait_time) > 0 ) {
|
||||||
|
ffmpeg_printf(10, "Waiting for ffmpeg filler thread to terminate itself, will try another %d times\n", wait_time);
|
||||||
|
|
||||||
|
usleep(100000);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (wait_time == 0) {
|
||||||
|
ffmpeg_err( "Timeout waiting for filler thread!\n");
|
||||||
|
|
||||||
|
ret = cERR_CONTAINER_FFMPEG_ERR;
|
||||||
|
}
|
||||||
|
|
||||||
|
hasfillerThreadStarted = 0;
|
||||||
|
//for buffered io (end)
|
||||||
|
|
||||||
|
wait_time = 100;
|
||||||
|
#endif
|
||||||
while ( (hasPlayThreadStarted != 0) && (--wait_time) > 0 ) {
|
while ( (hasPlayThreadStarted != 0) && (--wait_time) > 0 ) {
|
||||||
ffmpeg_printf(10, "Waiting for ffmpeg thread to terminate itself, will try another %d times\n", wait_time);
|
ffmpeg_printf(10, "Waiting for ffmpeg thread to terminate itself, will try another %d times\n", wait_time);
|
||||||
|
|
||||||
@@ -1581,12 +2143,26 @@ static int container_ffmpeg_stop(Context_t *context) {
|
|||||||
|
|
||||||
getMutex(FILENAME, __FUNCTION__,__LINE__);
|
getMutex(FILENAME, __FUNCTION__,__LINE__);
|
||||||
|
|
||||||
|
#ifdef MARTII
|
||||||
|
avformat_close_input(&avContext);
|
||||||
|
#else
|
||||||
if (avContext != NULL) {
|
if (avContext != NULL) {
|
||||||
av_close_input_file(avContext);
|
av_close_input_file(avContext);
|
||||||
avContext = NULL;
|
avContext = NULL;
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef MARTII //TDT
|
||||||
|
if(avio_opts != NULL) av_dict_free(&avio_opts);
|
||||||
|
|
||||||
|
//for buffered io
|
||||||
|
ffmpeg_buf_free();
|
||||||
|
//for buffered io (end)
|
||||||
|
#endif
|
||||||
isContainerRunning = 0;
|
isContainerRunning = 0;
|
||||||
|
#ifdef MARTII //TDT
|
||||||
|
avformat_network_deinit();
|
||||||
|
#endif
|
||||||
|
|
||||||
releaseMutex(FILENAME, __FUNCTION__,__LINE__);
|
releaseMutex(FILENAME, __FUNCTION__,__LINE__);
|
||||||
|
|
||||||
@@ -2134,6 +2710,32 @@ static int Command(void *_context, ContainerCmd_t command, void * argument)
|
|||||||
ret = container_ffmpeg_switch_teletext(context, (int*) argument);
|
ret = container_ffmpeg_switch_teletext(context, (int*) argument);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
#ifdef MARTII //TDT
|
||||||
|
case CONTAINER_SET_BUFFER_SEEK_TIME: {
|
||||||
|
ret = container_set_ffmpeg_buf_seek_time((int*) argument);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case CONTAINER_SET_BUFFER_SIZE: {
|
||||||
|
ret = container_set_ffmpeg_buf_size((int*) argument);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case CONTAINER_GET_BUFFER_SIZE: {
|
||||||
|
int size = 0;
|
||||||
|
ret = container_get_ffmpeg_buf_size(&size);
|
||||||
|
*((int*)argument) = size;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case CONTAINER_GET_BUFFER_STATUS: {
|
||||||
|
int size = 0;
|
||||||
|
ret = container_get_fillbufstatus(&size);
|
||||||
|
*((int*)argument) = size;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case CONTAINER_STOP_BUFFER: {
|
||||||
|
ret = container_stop_buffer();
|
||||||
|
break;
|
||||||
|
}
|
||||||
#endif
|
#endif
|
||||||
default:
|
default:
|
||||||
ffmpeg_err("ContainerCmd %d not supported!\n", command);
|
ffmpeg_err("ContainerCmd %d not supported!\n", command);
|
||||||
|
@@ -24,6 +24,13 @@ CONTAINER_SWITCH_TELETEXT,
|
|||||||
CONTAINER_INFO,
|
CONTAINER_INFO,
|
||||||
CONTAINER_STATUS,
|
CONTAINER_STATUS,
|
||||||
CONTAINER_LAST_PTS,
|
CONTAINER_LAST_PTS,
|
||||||
|
#ifdef MARTII //TDT
|
||||||
|
CONTAINER_SET_BUFFER_SEEK_TIME,
|
||||||
|
CONTAINER_SET_BUFFER_SIZE,
|
||||||
|
CONTAINER_GET_BUFFER_SIZE,
|
||||||
|
CONTAINER_GET_BUFFER_STATUS,
|
||||||
|
CONTAINER_STOP_BUFFER,
|
||||||
|
#endif
|
||||||
CONTAINER_DATA
|
CONTAINER_DATA
|
||||||
} ContainerCmd_t;
|
} ContainerCmd_t;
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user