Set discard flag to all not active streams, do not process packets from discarded streams

Conflicts:
	libeplayer3-arm/container/container_ffmpeg.c
This commit is contained in:
samsamsam
2018-03-18 01:16:08 +01:00
committed by Thilo Graf
parent 8aa8152d09
commit c150fe7bd6
7 changed files with 152 additions and 53 deletions

View File

@@ -136,6 +136,8 @@ static int64_t prev_seek_time_sec = -1;
static int32_t seek_target_flag = 0; static int32_t seek_target_flag = 0;
static int32_t mutexInitialized = 0;
/* ***************************** */ /* ***************************** */
/* Prototypes */ /* Prototypes */
/* ***************************** */ /* ***************************** */
@@ -155,6 +157,43 @@ void progressive_playback_set(int32_t val)
progressive_playback = val; progressive_playback = val;
} }
static void initMutex(void)
{
pthread_mutex_init(&mutex, NULL);
mutexInitialized = 1;
}
static void getMutex(const char *filename __attribute__((unused)), const char *function __attribute__((unused)), int32_t line __attribute__((unused)))
{
ffmpeg_printf(100, "::%d requesting mutex\n", line);
if (!mutexInitialized)
{
initMutex();
}
pthread_mutex_lock(&mutex);
ffmpeg_printf(100, "::%d received mutex\n", line);
}
static void releaseMutex(const char *filename __attribute__((unused)), const const char *function __attribute__((unused)), int32_t line __attribute__((unused)))
{
pthread_mutex_unlock(&mutex);
ffmpeg_printf(100, "::%d released mutex\n", line);
}
typedef int32_t (* Write_FN)(void *, void *);
static int32_t Write(Write_FN WriteFun, void *context, void *privateData)
{
/* Because Write is blocking we will release mutex which protect
* avformat structures, during write time
*/
int32_t ret = 0;
releaseMutex(__FILE__, __FUNCTION__, __LINE__);
ret = WriteFun(context, privateData);
getMutex(__FILE__, __FUNCTION__, __LINE__);
return ret;
}
#include "buff_ffmpeg.c" #include "buff_ffmpeg.c"
#include "wrapped_ffmpeg.c" #include "wrapped_ffmpeg.c"
#if LIBAVCODEC_VERSION_INT >= AV_VERSION_INT(56, 34, 100) #if LIBAVCODEC_VERSION_INT >= AV_VERSION_INT(56, 34, 100)
@@ -203,8 +242,6 @@ static void ffmpeg_silen_callback(void *avcl __attribute__((unused)), int level
return; return;
} }
static int32_t mutexInitialized = 0;
void sel_program_id_set(const int32_t val) void sel_program_id_set(const int32_t val)
{ {
g_sel_program_id = val; g_sel_program_id = val;
@@ -275,29 +312,6 @@ int32_t ffmpeg_av_dict_set(const char *key, const char *value, int32_t flags)
return av_dict_set(&avio_opts, key, value, flags); return av_dict_set(&avio_opts, key, value, flags);
} }
static void initMutex(void)
{
pthread_mutex_init(&mutex, NULL);
mutexInitialized = 1;
}
static void getMutex(const char *filename __attribute__((unused)), const char *function __attribute__((unused)), int32_t line __attribute__((unused)))
{
ffmpeg_printf(100, "::%d requesting mutex\n", line);
if (!mutexInitialized)
{
initMutex();
}
pthread_mutex_lock(&mutex);
ffmpeg_printf(100, "::%d received mutex\n", line);
}
static void releaseMutex(const char *filename __attribute__((unused)), const const char *function __attribute__((unused)), int32_t line __attribute__((unused)))
{
pthread_mutex_unlock(&mutex);
ffmpeg_printf(100, "::%d released mutex\n", line);
}
static char *Codec2Encoding(int32_t codec_id, int32_t media_type, uint8_t *extradata, int extradata_size, int profile __attribute__((unused)), int32_t *version) static char *Codec2Encoding(int32_t codec_id, int32_t media_type, uint8_t *extradata, int extradata_size, int profile __attribute__((unused)), int32_t *version)
{ {
ffmpeg_printf(10, "Codec ID: %d (%.8lx)\n", codec_id, codec_id); ffmpeg_printf(10, "Codec ID: %d (%.8lx)\n", codec_id, codec_id);
@@ -677,17 +691,24 @@ static void FFMPEGThread(Context_t *context)
Track_t *subtitleTrack = NULL; Track_t *subtitleTrack = NULL;
int32_t pid = avContextTab[cAVIdx]->streams[packet.stream_index]->id; int32_t pid = avContextTab[cAVIdx]->streams[packet.stream_index]->id;
reset_finish_timeout(); reset_finish_timeout();
if (context->manager->video->Command(context, MANAGER_GET_TRACK, &videoTrack) < 0) if (avContextTab[cAVIdx]->streams[packet.stream_index]->discard != AVDISCARD_ALL)
{ {
ffmpeg_err("error getting video track\n"); if (context->manager->video->Command(context, MANAGER_GET_TRACK, &videoTrack) < 0)
{
ffmpeg_err("error getting video track\n");
}
if (context->manager->audio->Command(context, MANAGER_GET_TRACK, &audioTrack) < 0)
{
ffmpeg_err("error getting audio track\n");
}
if (context->manager->subtitle->Command(context, MANAGER_GET_TRACK, &subtitleTrack) < 0)
{
ffmpeg_err("error getting subtitle track\n");
}
} }
if (context->manager->audio->Command(context, MANAGER_GET_TRACK, &audioTrack) < 0) else
{ {
ffmpeg_err("error getting audio track\n"); ffmpeg_printf(1, "SKIP DISCARDED PACKET stream_index[%d] pid[%d]\n", packet.size, (int)packet.stream_index, pid);
}
if (context->manager->subtitle->Command(context, MANAGER_GET_TRACK, &subtitleTrack) < 0)
{
ffmpeg_err("error getting subtitle track\n");
} }
ffmpeg_printf(200, "packet.size %d - index %d\n", packet.size, pid); ffmpeg_printf(200, "packet.size %d - index %d\n", packet.size, pid);
if (videoTrack && (videoTrack->AVIdx == (int)cAVIdx) && (videoTrack->Id == pid)) if (videoTrack && (videoTrack->AVIdx == (int)cAVIdx) && (videoTrack->Id == pid))
@@ -773,7 +794,7 @@ static void FFMPEGThread(Context_t *context)
{ {
avOut.infoFlags = 1; // TS container avOut.infoFlags = 1; // TS container
} }
if (context->output->video->Write(context, &avOut) < 0) if (Write(context->output->video->Write, context, &avOut) < 0)
{ {
ffmpeg_err("writing data to video device failed\n"); ffmpeg_err("writing data to video device failed\n");
} }
@@ -841,7 +862,7 @@ static void FFMPEGThread(Context_t *context)
avOut.width = 0; avOut.width = 0;
avOut.height = 0; avOut.height = 0;
avOut.type = "audio"; avOut.type = "audio";
if (context->output->audio->Write(context, &avOut) < 0) if (Write(context->output->audio->Write, context, &avOut) < 0)
{ {
ffmpeg_err("(raw pcm) writing data to audio device failed\n"); ffmpeg_err("(raw pcm) writing data to audio device failed\n");
} }
@@ -1017,7 +1038,7 @@ static void FFMPEGThread(Context_t *context)
avOut.width = 0; avOut.width = 0;
avOut.height = 0; avOut.height = 0;
avOut.type = "audio"; avOut.type = "audio";
if (!context->playback->BackWard && context->output->audio->Write(context, &avOut) < 0) if (!context->playback->BackWard && Write(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");
} }
@@ -1038,7 +1059,7 @@ static void FFMPEGThread(Context_t *context)
avOut.width = 0; avOut.width = 0;
avOut.height = 0; avOut.height = 0;
avOut.type = "audio"; avOut.type = "audio";
if (!context->playback->BackWard && context->output->audio->Write(context, &avOut) < 0) if (!context->playback->BackWard && Write(context->output->audio->Write, context, &avOut) < 0)
{ {
ffmpeg_err("(aac) writing data to audio device failed\n"); ffmpeg_err("(aac) writing data to audio device failed\n");
} }
@@ -1055,7 +1076,7 @@ static void FFMPEGThread(Context_t *context)
avOut.width = 0; avOut.width = 0;
avOut.height = 0; avOut.height = 0;
avOut.type = "audio"; avOut.type = "audio";
if (!context->playback->BackWard && context->output->audio->Write(context, &avOut) < 0) if (!context->playback->BackWard && Write(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");
} }
@@ -1084,7 +1105,7 @@ static void FFMPEGThread(Context_t *context)
subOut.data = (uint8_t *)packet.data; subOut.data = (uint8_t *)packet.data;
subOut.pts = pts; subOut.pts = pts;
subOut.durationMS = duration; subOut.durationMS = duration;
if (context->output->subtitle->Write(context, &subOut) < 0) if (Write(context->output->subtitle->Write, context, &subOut) < 0)
{ {
ffmpeg_err("writing data to teletext fifo failed\n"); ffmpeg_err("writing data to teletext fifo failed\n");
} }
@@ -1609,19 +1630,21 @@ int32_t container_ffmpeg_init(Context_t *context, PlayFiles_t *playFilesNames)
int32_t container_ffmpeg_update_tracks(Context_t *context, char *filename, int32_t initial) int32_t container_ffmpeg_update_tracks(Context_t *context, char *filename, int32_t initial)
{ {
Track_t *audioTrack = NULL; Track_t *currAudioTrack = NULL;
Track_t *subtitleTrack = NULL; Track_t *currSubtitleTrack = NULL;
uint32_t addedVideoTracksCount = 0;
if (terminating) if (terminating)
{ {
return cERR_CONTAINER_FFMPEG_NO_ERROR; return cERR_CONTAINER_FFMPEG_NO_ERROR;
} }
getMutex(__FILE__, __FUNCTION__, __LINE__);
if (initial && context->manager->subtitle) if (initial && context->manager->subtitle)
{ {
context->manager->subtitle->Command(context, MANAGER_GET_TRACK, &subtitleTrack); context->manager->subtitle->Command(context, MANAGER_GET_TRACK, &currSubtitleTrack);
} }
if (context->manager->audio) if (context->manager->audio)
{ {
context->manager->audio->Command(context, MANAGER_GET_TRACK, &audioTrack); context->manager->audio->Command(context, MANAGER_GET_TRACK, &currAudioTrack);
} }
if (context->manager->video) if (context->manager->video)
{ {
@@ -1707,7 +1730,11 @@ int32_t container_ffmpeg_update_tracks(Context_t *context, char *filename, int32
} }
} }
if (!isStreamFromSelProg) if (!isStreamFromSelProg)
{
stream->discard = AVDISCARD_ALL;
ffmpeg_printf(1, "cAVIdx[%d]: add DISCARD flag to stream index[%d]\n", cAVIdx, stream->index);
continue; // skip this stream continue; // skip this stream
}
} }
encoding = Codec2Encoding((int32_t)get_codecpar(stream)->codec_id, (int32_t)get_codecpar(stream)->codec_type, \ encoding = Codec2Encoding((int32_t)get_codecpar(stream)->codec_id, (int32_t)get_codecpar(stream)->codec_type, \
(uint8_t *)get_codecpar(stream)->extradata, \ (uint8_t *)get_codecpar(stream)->extradata, \
@@ -1734,6 +1761,7 @@ int32_t container_ffmpeg_update_tracks(Context_t *context, char *filename, int32
{ {
case AVMEDIA_TYPE_VIDEO: case AVMEDIA_TYPE_VIDEO:
ffmpeg_printf(10, "CODEC_TYPE_VIDEO %d\n", get_codecpar(stream)->codec_type); ffmpeg_printf(10, "CODEC_TYPE_VIDEO %d\n", get_codecpar(stream)->codec_type);
stream->discard = AVDISCARD_ALL; /* by default we discard all video streams */
if (encoding != NULL) if (encoding != NULL)
{ {
track.type = eTypeES; track.type = eTypeES;
@@ -1802,6 +1830,14 @@ int32_t container_ffmpeg_update_tracks(Context_t *context, char *filename, int32
/* konfetti: fixme: is this a reason to return with error? */ /* konfetti: fixme: is this a reason to return with error? */
ffmpeg_err("failed to add track %d\n", n); ffmpeg_err("failed to add track %d\n", n);
} }
else
{
if (addedVideoTracksCount == 0) /* at now we can handle only first video track */
{
stream->discard = AVDISCARD_DEFAULT;
}
addedVideoTracksCount += 1;
}
} }
} }
else else
@@ -1811,6 +1847,7 @@ int32_t container_ffmpeg_update_tracks(Context_t *context, char *filename, int32
break; break;
case AVMEDIA_TYPE_AUDIO: case AVMEDIA_TYPE_AUDIO:
ffmpeg_printf(10, "CODEC_TYPE_AUDIO %d\n", get_codecpar(stream)->codec_type); ffmpeg_printf(10, "CODEC_TYPE_AUDIO %d\n", get_codecpar(stream)->codec_type);
stream->discard = AVDISCARD_ALL;
if (encoding != NULL) if (encoding != NULL)
{ {
AVDictionaryEntry *lang; AVDictionaryEntry *lang;
@@ -2130,11 +2167,45 @@ int32_t container_ffmpeg_update_tracks(Context_t *context, char *filename, int32
case AVMEDIA_TYPE_ATTACHMENT: case AVMEDIA_TYPE_ATTACHMENT:
case AVMEDIA_TYPE_NB: case AVMEDIA_TYPE_NB:
default: default:
stream->discard = AVDISCARD_ALL;
ffmpeg_err("not handled or unknown codec_type %d\n", get_codecpar(stream)->codec_type); ffmpeg_err("not handled or unknown codec_type %d\n", get_codecpar(stream)->codec_type);
break; break;
} }
} /* for */ } /* for */
} }
if (context->manager->audio)
{
Track_t *Tracks = NULL;
int32_t TrackCount = 0;
int32_t selTrackIdx = -1;
context->manager->audio->Command(context, MANAGER_REF_LIST, &Tracks);
context->manager->audio->Command(context, MANAGER_REF_LIST_SIZE, &TrackCount);
if (Tracks && TrackCount)
{
int32_t i;
for (i = 0; i < TrackCount; ++i)
{
if (Tracks[i].pending || Tracks[i].Id < 0)
continue;
if (selTrackIdx == -1)
selTrackIdx = i;
if (currAudioTrack && currAudioTrack->Id == Tracks[i].Id)
{
selTrackIdx = i;
break;
}
}
if (selTrackIdx > -1)
{
((AVStream *)Tracks[selTrackIdx].stream)->discard = AVDISCARD_DEFAULT;
if (!currAudioTrack || currAudioTrack->Id != Tracks[selTrackIdx].Id)
{
context->manager->audio->Command(context, MANAGER_SET, &Tracks[selTrackIdx].Id);
}
}
}
}
releaseMutex(__FILE__, __FUNCTION__, __LINE__);
return cERR_CONTAINER_FFMPEG_NO_ERROR; return cERR_CONTAINER_FFMPEG_NO_ERROR;
} }
@@ -2398,7 +2469,6 @@ static int32_t container_ffmpeg_seek(Context_t *context, int64_t sec, uint8_t ab
{ {
seek_target_flag |= AVSEEK_FLAG_BACKWARD; seek_target_flag |= AVSEEK_FLAG_BACKWARD;
} }
getMutex(__FILE__, __FUNCTION__, __LINE__);
if (!context->playback || !context->playback->isPlaying) if (!context->playback || !context->playback->isPlaying)
{ {
releaseMutex(__FILE__, __FUNCTION__, __LINE__); releaseMutex(__FILE__, __FUNCTION__, __LINE__);
@@ -2414,8 +2484,9 @@ static int32_t container_ffmpeg_seek(Context_t *context, int64_t sec, uint8_t ab
* seeking per HTTP does still not work very good. forward seeks everytime * seeking per HTTP does still not work very good. forward seeks everytime
* about 10 seconds, backward does not work. * about 10 seconds, backward does not work.
*/ */
getMutex(__FILE__, __FUNCTION__, __LINE__);
off_t pos = avio_tell(avContextTab[0]->pb); off_t pos = avio_tell(avContextTab[0]->pb);
ffmpeg_printf(10, "pos %lld %d\n", pos, avContextTab[0]->bit_rate); releaseMutex(__FILE__, __FUNCTION__, __LINE__);
if (avContextTab[0]->bit_rate) if (avContextTab[0]->bit_rate)
{ {
sec *= avContextTab[0]->bit_rate / 8; sec *= avContextTab[0]->bit_rate / 8;
@@ -2440,7 +2511,6 @@ static int32_t container_ffmpeg_seek(Context_t *context, int64_t sec, uint8_t ab
seek_target_seconds = sec * AV_TIME_BASE; seek_target_seconds = sec * AV_TIME_BASE;
do_seek_target_seconds = 1; do_seek_target_seconds = 1;
} }
releaseMutex(__FILE__, __FUNCTION__, __LINE__);
return cERR_CONTAINER_FFMPEG_NO_ERROR; return cERR_CONTAINER_FFMPEG_NO_ERROR;
} }
@@ -2495,8 +2565,25 @@ static int32_t container_ffmpeg_get_length(Context_t *context, int64_t *length)
static int32_t container_ffmpeg_switch_audio(Context_t *context, int32_t *arg __attribute__((unused))) static int32_t container_ffmpeg_switch_audio(Context_t *context, int32_t *arg __attribute__((unused)))
{ {
ffmpeg_printf(10, "track %d\n", *arg); ffmpeg_printf(10, "track %d\n", *arg);
getMutex(__FILE__, __FUNCTION__, __LINE__);
if (context->manager->audio)
{
Track_t *Tracks = NULL;
int32_t TrackCount = 0;
context->manager->audio->Command(context, MANAGER_REF_LIST, &Tracks);
context->manager->audio->Command(context, MANAGER_REF_LIST_SIZE, &TrackCount);
if (Tracks && TrackCount)
{
int32_t i;
for (i = 0; i < TrackCount; ++i)
{
((AVStream *)Tracks[i].stream)->discard = Tracks[i].Id == *arg ? AVDISCARD_DEFAULT : AVDISCARD_ALL;
}
}
}
releaseMutex(__FILE__, __FUNCTION__, __LINE__);
/* Hellmaster1024: nothing to do here! */ /* Hellmaster1024: nothing to do here! */
int64_t sec = -5; int64_t sec = -1;
context->playback->Command(context, PLAYBACK_SEEK, (void *)&sec); context->playback->Command(context, PLAYBACK_SEEK, (void *)&sec);
return cERR_CONTAINER_FFMPEG_NO_ERROR; return cERR_CONTAINER_FFMPEG_NO_ERROR;
} }
@@ -2509,7 +2596,7 @@ static int32_t container_ffmpeg_switch_subtitle(Context_t *context, int32_t *arg
* we seek to force ffmpeg to read once again the same data * we seek to force ffmpeg to read once again the same data
* but now we will not ignore subtitle frame * but now we will not ignore subtitle frame
*/ */
int64_t sec = -5; int64_t sec = -1;
context->playback->Command(context, PLAYBACK_SEEK, (void *)&sec); context->playback->Command(context, PLAYBACK_SEEK, (void *)&sec);
return cERR_CONTAINER_FFMPEG_NO_ERROR; return cERR_CONTAINER_FFMPEG_NO_ERROR;
} }
@@ -2744,4 +2831,4 @@ Container_t FFMPEGContainer =
"FFMPEG", "FFMPEG",
&Command, &Command,
FFMPEG_Capabilities FFMPEG_Capabilities
}; };

View File

@@ -34,7 +34,7 @@ static int flv2mpeg4_context_write_packet_cb(void *usr_data, int keyframe, int p
avOut.width = ctx->track->width; avOut.width = ctx->track->width;
avOut.height = ctx->track->height; avOut.height = ctx->track->height;
avOut.type = "video"; avOut.type = "video";
if (ctx->out_ctx->output->video->Write(ctx->out_ctx, &avOut) < 0) if (Write(ctx->out_ctx->output->video->Write, ctx->out_ctx, &avOut) < 0)
{ {
ffmpeg_err("writing data to video device failed\n"); ffmpeg_err("writing data to video device failed\n");
} }

View File

@@ -107,7 +107,7 @@ static void mpeg4p2_write(Context_t *ctx, Track_t *track, int avContextIdx, int6
avOut.width = track->width; avOut.width = track->width;
avOut.height = track->height; avOut.height = track->height;
avOut.type = "video"; avOut.type = "video";
if (ctx->output->video->Write(ctx, &avOut) < 0) if (Write(ctx->output->video->Write, ctx, &avOut) < 0)
{ {
ffmpeg_err("writing data to video device failed\n"); ffmpeg_err("writing data to video device failed\n");
} }

View File

@@ -24,6 +24,8 @@ typedef enum
MANAGER_INIT_UPDATE, MANAGER_INIT_UPDATE,
MANAGER_UPDATED_TRACK_INFO, MANAGER_UPDATED_TRACK_INFO,
MANAGER_REGISTER_UPDATED_TRACK_INFO, MANAGER_REGISTER_UPDATED_TRACK_INFO,
MANAGER_REF_LIST,
MANAGER_REF_LIST_SIZE,
} ManagerCmd_t; } ManagerCmd_t;
typedef enum typedef enum

View File

@@ -71,7 +71,7 @@ typedef struct Output_s
{ {
char *Name; char *Name;
int32_t (* Command)(Context_t *, OutputCmd_t, void *); int32_t (* Command)(Context_t *, OutputCmd_t, void *);
int32_t (* Write)(Context_t *, void *privateData); int32_t (* Write)(Context_t *, void *);
char **Capabilities; char **Capabilities;
} Output_t; } Output_t;

View File

@@ -635,7 +635,7 @@ int main(int argc, char *argv[])
memset(argvBuff, '\0', sizeof(argvBuff)); memset(argvBuff, '\0', sizeof(argvBuff));
int commandRetVal = -1; int commandRetVal = -1;
/* inform client that we can handle additional commands */ /* inform client that we can handle additional commands */
fprintf(stderr, "{\"EPLAYER3_EXTENDED\":{\"version\":%d}}\n", 38); fprintf(stderr, "{\"EPLAYER3_EXTENDED\":{\"version\":%d}}\n", 39);
if (0 != ParseParams(argc, argv, file, audioFile, &audioTrackIdx, &subtitleTrackIdx)) if (0 != ParseParams(argc, argv, file, audioFile, &audioTrackIdx, &subtitleTrackIdx))
{ {
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("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");

View File

@@ -231,6 +231,16 @@ static int Command(Context_t *context, ManagerCmd_t command, void *argument)
*((char ** *) argument) = (char **) ManagerList(context); *((char ** *) argument) = (char **) ManagerList(context);
break; break;
} }
case MANAGER_REF_LIST:
{
*((Track_t **)argument) = Tracks;
break;
}
case MANAGER_REF_LIST_SIZE:
{
*((int *)argument) = TrackCount;
break;
}
case MANAGER_GET: case MANAGER_GET:
{ {
audio_mgr_printf(20, "%s::%s MANAGER_GET\n", __FILE__, __FUNCTION__); audio_mgr_printf(20, "%s::%s MANAGER_GET\n", __FILE__, __FUNCTION__);