mirror of
https://github.com/tuxbox-fork-migrations/recycled-ni-libstb-hal.git
synced 2025-08-27 07:22:44 +02:00
libeplayer3: use actual pids instead of indexes
Origin commit data
------------------
Branch: master
Commit: fb16fc2ffb
Author: martii <m4rtii@gmx.de>
Date: 2013-07-12 (Fri, 12 Jul 2013)
------------------
No further description and justification available within origin commit message!
------------------
This commit was generated by Migit
This commit is contained in:
@@ -492,7 +492,7 @@ static void FFMPEGThread(Context_t *context) {
|
|||||||
Track_t * dvbsubtitleTrack = NULL;
|
Track_t * dvbsubtitleTrack = NULL;
|
||||||
Track_t * teletextTrack = NULL;
|
Track_t * teletextTrack = NULL;
|
||||||
|
|
||||||
int ix = packet.stream_index;
|
int pid = avContext->streams[packet.stream_index]->id;
|
||||||
|
|
||||||
if (context->manager->video->Command(context, MANAGER_GET_TRACK, &videoTrack) < 0)
|
if (context->manager->video->Command(context, MANAGER_GET_TRACK, &videoTrack) < 0)
|
||||||
ffmpeg_err("error getting video track\n");
|
ffmpeg_err("error getting video track\n");
|
||||||
@@ -509,10 +509,10 @@ static void FFMPEGThread(Context_t *context) {
|
|||||||
if (context->manager->teletext->Command(context, MANAGER_GET_TRACK, &teletextTrack) < 0)
|
if (context->manager->teletext->Command(context, MANAGER_GET_TRACK, &teletextTrack) < 0)
|
||||||
ffmpeg_err("error getting teletext track\n");
|
ffmpeg_err("error getting teletext track\n");
|
||||||
|
|
||||||
ffmpeg_printf(200, "packet.size %d - index %d\n", packet.size, ix);
|
ffmpeg_printf(200, "packet.size %d - index %d\n", packet.size, pid);
|
||||||
|
|
||||||
if (videoTrack != NULL) {
|
if (videoTrack != NULL) {
|
||||||
if (videoTrack->Id == ix) {
|
if (videoTrack->Id == pid) {
|
||||||
currentVideoPts = videoTrack->pts = pts = calcPts(videoTrack->stream, &packet);
|
currentVideoPts = videoTrack->pts = pts = calcPts(videoTrack->stream, &packet);
|
||||||
|
|
||||||
if ((currentVideoPts > latestPts) && (currentVideoPts != INVALID_PTS_VALUE))
|
if ((currentVideoPts > latestPts) && (currentVideoPts != INVALID_PTS_VALUE))
|
||||||
@@ -526,7 +526,7 @@ static void FFMPEGThread(Context_t *context) {
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
ffmpeg_printf(200, "VideoTrack index = %d %lld\n",ix, currentVideoPts);
|
ffmpeg_printf(200, "VideoTrack index = %d %lld\n",pid, currentVideoPts);
|
||||||
|
|
||||||
avOut.data = packet.data;
|
avOut.data = packet.data;
|
||||||
avOut.len = packet.size;
|
avOut.len = packet.size;
|
||||||
@@ -546,7 +546,7 @@ static void FFMPEGThread(Context_t *context) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (audioTrack != NULL) {
|
if (audioTrack != NULL) {
|
||||||
if (audioTrack->Id == ix) {
|
if (audioTrack->Id == pid) {
|
||||||
currentAudioPts = audioTrack->pts = pts = calcPts(audioTrack->stream, &packet);
|
currentAudioPts = audioTrack->pts = pts = calcPts(audioTrack->stream, &packet);
|
||||||
|
|
||||||
if ((currentAudioPts > latestPts) && (!videoTrack))
|
if ((currentAudioPts > latestPts) && (!videoTrack))
|
||||||
@@ -560,7 +560,7 @@ static void FFMPEGThread(Context_t *context) {
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
ffmpeg_printf(200, "AudioTrack index = %d\n",ix);
|
ffmpeg_printf(200, "AudioTrack index = %d\n",pid);
|
||||||
if (audioTrack->inject_raw_pcm == 1){
|
if (audioTrack->inject_raw_pcm == 1){
|
||||||
ffmpeg_printf(200,"write audio raw pcm\n");
|
ffmpeg_printf(200,"write audio raw pcm\n");
|
||||||
|
|
||||||
@@ -780,7 +780,7 @@ static void FFMPEGThread(Context_t *context) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (subtitleTrack != NULL) {
|
if (subtitleTrack != NULL) {
|
||||||
if (subtitleTrack->Id == ix) {
|
if (subtitleTrack->Id == pid) {
|
||||||
float duration=3.0;
|
float duration=3.0;
|
||||||
ffmpeg_printf(100, "subtitleTrack->stream %p \n", subtitleTrack->stream);
|
ffmpeg_printf(100, "subtitleTrack->stream %p \n", subtitleTrack->stream);
|
||||||
|
|
||||||
@@ -888,10 +888,10 @@ static void FFMPEGThread(Context_t *context) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (dvbsubtitleTrack != NULL) {
|
if (dvbsubtitleTrack != NULL) {
|
||||||
if (dvbsubtitleTrack->Id == ix) {
|
if (dvbsubtitleTrack->Id == pid) {
|
||||||
dvbsubtitleTrack->pts = pts = calcPts(dvbsubtitleTrack->stream, &packet);
|
dvbsubtitleTrack->pts = pts = calcPts(dvbsubtitleTrack->stream, &packet);
|
||||||
|
|
||||||
ffmpeg_printf(200, "DvbSubTitle index = %d\n",ix);
|
ffmpeg_printf(200, "DvbSubTitle index = %d\n",pid);
|
||||||
|
|
||||||
avOut.data = packet.data;
|
avOut.data = packet.data;
|
||||||
avOut.len = packet.size;
|
avOut.len = packet.size;
|
||||||
@@ -911,10 +911,10 @@ static void FFMPEGThread(Context_t *context) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (teletextTrack != NULL) {
|
if (teletextTrack != NULL) {
|
||||||
if (teletextTrack->Id == ix) {
|
if (teletextTrack->Id == pid) {
|
||||||
teletextTrack->pts = pts = calcPts(teletextTrack->stream, &packet);
|
teletextTrack->pts = pts = calcPts(teletextTrack->stream, &packet);
|
||||||
|
|
||||||
ffmpeg_printf(200, "TeleText index = %d\n",ix);
|
ffmpeg_printf(200, "TeleText index = %d\n",pid);
|
||||||
|
|
||||||
avOut.data = packet.data;
|
avOut.data = packet.data;
|
||||||
avOut.len = packet.size;
|
avOut.len = packet.size;
|
||||||
@@ -1027,6 +1027,7 @@ int container_ffmpeg_init(Context_t *context, char * filename)
|
|||||||
return cERR_CONTAINER_FFMPEG_OPEN;
|
return cERR_CONTAINER_FFMPEG_OPEN;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
avContext->iformat->flags |= AVFMT_SEEK_TO_PTS;
|
||||||
avContext->flags = AVFMT_FLAG_GENPTS;
|
avContext->flags = AVFMT_FLAG_GENPTS;
|
||||||
if (context->playback->noprobe)
|
if (context->playback->noprobe)
|
||||||
avContext->max_analyze_duration = 1;
|
avContext->max_analyze_duration = 1;
|
||||||
@@ -1060,6 +1061,29 @@ int container_ffmpeg_update_tracks(Context_t *context, char *filename)
|
|||||||
if (terminating)
|
if (terminating)
|
||||||
return cERR_CONTAINER_FFMPEG_NO_ERROR;
|
return cERR_CONTAINER_FFMPEG_NO_ERROR;
|
||||||
|
|
||||||
|
Track_t * audioTrack = NULL;
|
||||||
|
Track_t * subtitleTrack = NULL;
|
||||||
|
Track_t * dvbsubtitleTrack = NULL;
|
||||||
|
Track_t * teletextTrack = NULL;
|
||||||
|
int audioId = -1;
|
||||||
|
int subtitleId = -1;
|
||||||
|
int dvbsubtitleId = -1;
|
||||||
|
int teletextId = -1;
|
||||||
|
|
||||||
|
context->manager->audio->Command(context, MANAGER_GET_TRACK, &audioTrack);
|
||||||
|
context->manager->subtitle->Command(context, MANAGER_GET_TRACK, &subtitleTrack);
|
||||||
|
context->manager->dvbsubtitle->Command(context, MANAGER_GET_TRACK, &dvbsubtitleTrack);
|
||||||
|
context->manager->teletext->Command(context, MANAGER_GET_TRACK, &teletextTrack);
|
||||||
|
|
||||||
|
if (audioTrack)
|
||||||
|
audioId = ((AVStream *) (audioTrack->stream))->id;
|
||||||
|
if (subtitleTrack)
|
||||||
|
subtitleId = ((AVStream *) (subtitleTrack->stream))->id;
|
||||||
|
if (dvbsubtitleTrack)
|
||||||
|
dvbsubtitleId = ((AVStream *) (dvbsubtitleTrack->stream))->id;
|
||||||
|
if (teletextTrack)
|
||||||
|
teletextId = ((AVStream *) (teletextTrack->stream))->id;
|
||||||
|
|
||||||
unsigned int n;
|
unsigned int n;
|
||||||
|
|
||||||
if (context->manager->audio)
|
if (context->manager->audio)
|
||||||
@@ -1136,9 +1160,8 @@ int container_ffmpeg_update_tracks(Context_t *context, char *filename)
|
|||||||
|
|
||||||
track.Name = "und";
|
track.Name = "und";
|
||||||
track.Encoding = encoding;
|
track.Encoding = encoding;
|
||||||
track.Id = n;
|
|
||||||
|
|
||||||
track.stream = stream;
|
track.stream = stream;
|
||||||
|
track.Id = ((AVStream *) (track.stream))->id;
|
||||||
|
|
||||||
if(stream->duration == AV_NOPTS_VALUE) {
|
if(stream->duration == AV_NOPTS_VALUE) {
|
||||||
ffmpeg_printf(10, "Stream has no duration so we take the duration from context\n");
|
ffmpeg_printf(10, "Stream has no duration so we take the duration from context\n");
|
||||||
@@ -1173,11 +1196,9 @@ int container_ffmpeg_update_tracks(Context_t *context, char *filename)
|
|||||||
ffmpeg_printf(10, "Language %s\n", track.Name);
|
ffmpeg_printf(10, "Language %s\n", track.Name);
|
||||||
|
|
||||||
track.Encoding = encoding;
|
track.Encoding = encoding;
|
||||||
track.Id = n;
|
|
||||||
|
|
||||||
track.stream = stream;
|
track.stream = stream;
|
||||||
|
track.Id = ((AVStream *) (track.stream))->id;
|
||||||
track.duration = (double)stream->duration * av_q2d(stream->time_base) * 1000.0;
|
track.duration = (double)stream->duration * av_q2d(stream->time_base) * 1000.0;
|
||||||
|
|
||||||
track.aacbuf = 0;
|
track.aacbuf = 0;
|
||||||
track.have_aacheader = -1;
|
track.have_aacheader = -1;
|
||||||
|
|
||||||
@@ -1373,9 +1394,8 @@ int container_ffmpeg_update_tracks(Context_t *context, char *filename)
|
|||||||
ffmpeg_printf(10, "Language %s\n", track.Name);
|
ffmpeg_printf(10, "Language %s\n", track.Name);
|
||||||
|
|
||||||
track.Encoding = encoding;
|
track.Encoding = encoding;
|
||||||
track.Id = n;
|
|
||||||
|
|
||||||
track.stream = stream;
|
track.stream = stream;
|
||||||
|
track.Id = ((AVStream *) (track.stream))->id;
|
||||||
track.duration = (double)stream->duration * av_q2d(stream->time_base) * 1000.0;
|
track.duration = (double)stream->duration * av_q2d(stream->time_base) * 1000.0;
|
||||||
|
|
||||||
track.aacbuf = 0;
|
track.aacbuf = 0;
|
||||||
@@ -1442,6 +1462,15 @@ int container_ffmpeg_update_tracks(Context_t *context, char *filename)
|
|||||||
|
|
||||||
} /* for */
|
} /* for */
|
||||||
|
|
||||||
|
if (audioId > -1 && context->playback)
|
||||||
|
context->playback->Command(context, PLAYBACK_SWITCH_AUDIO, &audioId);
|
||||||
|
if (subtitleId > -1 && context->playback)
|
||||||
|
context->playback->Command(context, PLAYBACK_SWITCH_SUBTITLE, &subtitleId);
|
||||||
|
if (dvbsubtitleId > -1 && context->playback)
|
||||||
|
context->playback->Command(context, PLAYBACK_SWITCH_DVBSUBTITLE, &dvbsubtitleId);
|
||||||
|
if (teletextId > -1 && context->playback)
|
||||||
|
context->playback->Command(context, PLAYBACK_SWITCH_TELETEXT, &teletextId);
|
||||||
|
|
||||||
releaseMutex(FILENAME, __FUNCTION__,__LINE__);
|
releaseMutex(FILENAME, __FUNCTION__,__LINE__);
|
||||||
|
|
||||||
return cERR_CONTAINER_FFMPEG_NO_ERROR;
|
return cERR_CONTAINER_FFMPEG_NO_ERROR;
|
||||||
|
@@ -124,7 +124,10 @@ static char ** ManagerList(Context_t *context __attribute__((unused))) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
for (i = 0, j = 0; i < TrackCount; i++, j+=2) {
|
for (i = 0, j = 0; i < TrackCount; i++, j+=2) {
|
||||||
tracklist[j] = strdup(Tracks[i].Name);
|
size_t len = strlen(Tracks[i].Name) + 20;
|
||||||
|
char tmp[len];
|
||||||
|
snprintf(tmp, len, "%d %s\n", Tracks[i].Id, Tracks[i].Name);
|
||||||
|
tracklist[j] = strdup(tmp);
|
||||||
tracklist[j+1] = strdup(Tracks[i].Encoding);
|
tracklist[j+1] = strdup(Tracks[i].Encoding);
|
||||||
}
|
}
|
||||||
tracklist[j] = NULL;
|
tracklist[j] = NULL;
|
||||||
@@ -214,23 +217,17 @@ static int Command(void *_context, ManagerCmd_t command, void * argument) {
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case MANAGER_SET: {
|
case MANAGER_SET: {
|
||||||
int id = *((int*)argument);
|
int i;
|
||||||
|
audio_mgr_printf(20, "%s::%s MANAGER_SET id=%d\n", FILENAME, __FUNCTION__, *((int*)argument));
|
||||||
|
|
||||||
// What's the argument supposed to be? apid or local index? --martii
|
for (i = 0; i < TrackCount; i++)
|
||||||
if (id >= TrackCount) {
|
if (Tracks[i].Id == *((int*)argument)) {
|
||||||
int apid = id;
|
CurrentTrack = i;
|
||||||
for (id = 0; id < TrackCount; id++) {
|
|
||||||
if (((AVStream *) (Tracks[id].stream))->id == apid)
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
audio_mgr_printf(20, "%s::%s MANAGER_SET id=%d\n", FILENAME, __FUNCTION__, id);
|
|
||||||
|
|
||||||
if (id < TrackCount)
|
if (i == TrackCount) {
|
||||||
CurrentTrack = id;
|
audio_mgr_err("%s::%s track id %d unknown\n", FILENAME, __FUNCTION__, *((int*)argument));
|
||||||
else
|
|
||||||
{
|
|
||||||
audio_mgr_err("%s::%s track id out of range (%d - %d)\n", FILENAME, __FUNCTION__, id, TrackCount);
|
|
||||||
ret = cERR_AUDIO_MGR_ERROR;
|
ret = cERR_AUDIO_MGR_ERROR;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
@@ -124,7 +124,10 @@ static char ** ManagerList(Context_t *context __attribute__((unused))) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
for (i = 0, j = 0; i < TrackCount; i++, j+=2) {
|
for (i = 0, j = 0; i < TrackCount; i++, j+=2) {
|
||||||
tracklist[j] = strdup(Tracks[i].Name);
|
size_t len = strlen(Tracks[i].Name) + 20;
|
||||||
|
char tmp[len];
|
||||||
|
snprintf(tmp, len, "%d %s\n", Tracks[i].Id, Tracks[i].Name);
|
||||||
|
tracklist[j] = strdup(tmp);
|
||||||
tracklist[j+1] = strdup(Tracks[i].Encoding);
|
tracklist[j+1] = strdup(Tracks[i].Encoding);
|
||||||
}
|
}
|
||||||
tracklist[j] = NULL;
|
tracklist[j] = NULL;
|
||||||
@@ -214,23 +217,17 @@ static int Command(void *_context, ManagerCmd_t command, void * argument) {
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case MANAGER_SET: {
|
case MANAGER_SET: {
|
||||||
int id = *((int*)argument);
|
int i;
|
||||||
|
dvbsubtitle_mgr_printf(20, "%s::%s MANAGER_SET id=%d\n", FILENAME, __FUNCTION__, *((int*)argument));
|
||||||
|
|
||||||
dvbsubtitle_mgr_printf(20, "%s::%s MANAGER_SET id=%d\n", FILENAME, __FUNCTION__, id);
|
for (i = 0; i < TrackCount; i++)
|
||||||
|
if (Tracks[i].Id == *((int*)argument)) {
|
||||||
if (id >= TrackCount) {
|
CurrentTrack = i;
|
||||||
int mypid = id;
|
|
||||||
for (id = 0; id < TrackCount; id++) {
|
|
||||||
if (((AVStream *) (Tracks[id].stream))->id == mypid)
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
if (id < TrackCount)
|
if (i == TrackCount) {
|
||||||
CurrentTrack = id;
|
dvbsubtitle_mgr_err("%s::%s track id %d unknown\n", FILENAME, __FUNCTION__, *((int*)argument));
|
||||||
else
|
|
||||||
{
|
|
||||||
dvbsubtitle_mgr_err("%s::%s track id out of range (%d - %d)\n", FILENAME, __FUNCTION__, id, TrackCount);
|
|
||||||
ret = cERR_DVBSUBTITLE_MGR_ERROR;
|
ret = cERR_DVBSUBTITLE_MGR_ERROR;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
@@ -123,7 +123,10 @@ static char ** ManagerList(Context_t *context __attribute__((unused))) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
for (i = 0, j = 0; i < TrackCount; i++, j+=2) {
|
for (i = 0, j = 0; i < TrackCount; i++, j+=2) {
|
||||||
tracklist[j] = strdup(Tracks[i].Name);
|
size_t len = strlen(Tracks[i].Name) + 20;
|
||||||
|
char tmp[len];
|
||||||
|
snprintf(tmp, len, "%d %s\n", Tracks[i].Id, Tracks[i].Name);
|
||||||
|
tracklist[j] = strdup(tmp);
|
||||||
tracklist[j+1] = strdup(Tracks[i].Encoding);
|
tracklist[j+1] = strdup(Tracks[i].Encoding);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -225,7 +228,7 @@ static int Command(void *_context, ManagerCmd_t command, void * argument) {
|
|||||||
CurrentTrack = id;
|
CurrentTrack = id;
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
subtitle_mgr_err("%s::%s track id out of range (%d - %d)\n", FILENAME, __FUNCTION__, id, TrackCount);
|
subtitle_mgr_err("%s::%s track id %d unknown\n", FILENAME, __FUNCTION__, id);
|
||||||
ret = cERR_SUBTITLE_MGR_ERROR;
|
ret = cERR_SUBTITLE_MGR_ERROR;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
@@ -114,6 +114,7 @@ static char ** ManagerList(Context_t *context __attribute__((unused))) {
|
|||||||
teletext_mgr_printf(10, "%s::%s\n", FILENAME, __FUNCTION__);
|
teletext_mgr_printf(10, "%s::%s\n", FILENAME, __FUNCTION__);
|
||||||
|
|
||||||
if (Tracks != NULL) {
|
if (Tracks != NULL) {
|
||||||
|
|
||||||
tracklist = malloc(sizeof(char *) * ((TrackCount*2) + 1));
|
tracklist = malloc(sizeof(char *) * ((TrackCount*2) + 1));
|
||||||
|
|
||||||
if (tracklist == NULL)
|
if (tracklist == NULL)
|
||||||
@@ -123,7 +124,10 @@ static char ** ManagerList(Context_t *context __attribute__((unused))) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
for (i = 0, j = 0; i < TrackCount; i++, j+=2) {
|
for (i = 0, j = 0; i < TrackCount; i++, j+=2) {
|
||||||
tracklist[j] = strdup(Tracks[i].Name);
|
size_t len = strlen(Tracks[i].Name) + 20;
|
||||||
|
char tmp[len];
|
||||||
|
snprintf(tmp, len, "%d %s\n", Tracks[i].Id, Tracks[i].Name);
|
||||||
|
tracklist[j] = strdup(tmp);
|
||||||
tracklist[j+1] = strdup(Tracks[i].Encoding);
|
tracklist[j+1] = strdup(Tracks[i].Encoding);
|
||||||
}
|
}
|
||||||
tracklist[j] = NULL;
|
tracklist[j] = NULL;
|
||||||
@@ -213,23 +217,17 @@ static int Command(void *_context, ManagerCmd_t command, void * argument) {
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case MANAGER_SET: {
|
case MANAGER_SET: {
|
||||||
int id = *((int*)argument);
|
int i;
|
||||||
|
teletext_mgr_printf(20, "%s::%s MANAGER_SET id=%d\n", FILENAME, __FUNCTION__, *((int*)argument));
|
||||||
|
|
||||||
teletext_mgr_printf(20, "%s::%s MANAGER_SET id=%d\n", FILENAME, __FUNCTION__, id);
|
for (i = 0; i < TrackCount; i++)
|
||||||
|
if (Tracks[i].Id == *((int*)argument)) {
|
||||||
if (id >= TrackCount) {
|
CurrentTrack = i;
|
||||||
int mypid = id;
|
|
||||||
for (id = 0; id < TrackCount; id++) {
|
|
||||||
if (((AVStream *) (Tracks[id].stream))->id == mypid)
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
if (id < TrackCount)
|
if (i == TrackCount) {
|
||||||
CurrentTrack = id;
|
teletext_mgr_err("%s::%s track id %d unknown\n", FILENAME, __FUNCTION__, *((int*)argument));
|
||||||
else
|
|
||||||
{
|
|
||||||
teletext_mgr_err("%s::%s track id out of range (%d - %d)\n", FILENAME, __FUNCTION__, id, TrackCount);
|
|
||||||
ret = cERR_TELETEXT_MGR_ERROR;
|
ret = cERR_TELETEXT_MGR_ERROR;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
@@ -123,7 +123,10 @@ static char ** ManagerList(Context_t *context __attribute__((unused))) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
for (i = 0, j = 0; i < TrackCount; i++, j+=2) {
|
for (i = 0, j = 0; i < TrackCount; i++, j+=2) {
|
||||||
tracklist[j] = strdup(Tracks[i].Name);
|
size_t len = strlen(Tracks[i].Name) + 20;
|
||||||
|
char tmp[len];
|
||||||
|
snprintf(tmp, len, "%d %s\n", Tracks[i].Id, Tracks[i].Name);
|
||||||
|
tracklist[j] = strdup(tmp);
|
||||||
tracklist[j+1] = strdup(Tracks[i].Encoding);
|
tracklist[j+1] = strdup(Tracks[i].Encoding);
|
||||||
}
|
}
|
||||||
tracklist[j] = NULL;
|
tracklist[j] = NULL;
|
||||||
@@ -208,13 +211,17 @@ static int Command(void *_context, ManagerCmd_t command, void * argument) {
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case MANAGER_SET: {
|
case MANAGER_SET: {
|
||||||
int id = (int) argument;
|
int i;
|
||||||
|
|
||||||
if (id < TrackCount)
|
for (i = 0; i < TrackCount; i++)
|
||||||
CurrentTrack = id;
|
if (Tracks[i].Id == *((int*)argument)) {
|
||||||
else
|
CurrentTrack = i;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (i == TrackCount)
|
||||||
{
|
{
|
||||||
video_mgr_err("%s::%s track id out of range (%d - %d)\n", FILENAME, __FUNCTION__, id, TrackCount);
|
video_mgr_err("%s::%s track id %d unknown\n", FILENAME, __FUNCTION__, *((int*)argument));
|
||||||
ret = cERR_VIDEO_MGR_ERROR;
|
ret = cERR_VIDEO_MGR_ERROR;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
@@ -110,17 +110,17 @@ int LinuxDvbOpen(Context_t *context __attribute__((unused)), char * type) {
|
|||||||
|
|
||||||
linuxdvb_printf(10, "v%d a%d\n", video, audio);
|
linuxdvb_printf(10, "v%d a%d\n", video, audio);
|
||||||
|
|
||||||
if (video && videofd == -1) {
|
if (video && videofd < 0) {
|
||||||
videofd = open(VIDEODEV, O_RDWR);
|
videofd = open(VIDEODEV, O_RDWR);
|
||||||
|
|
||||||
if (videofd <= 0)
|
if (videofd < 0)
|
||||||
{
|
{
|
||||||
linuxdvb_err("failed to open %s - errno %d\n", VIDEODEV, errno);
|
linuxdvb_err("failed to open %s - errno %d\n", VIDEODEV, errno);
|
||||||
linuxdvb_err("%s\n", strerror(errno));
|
linuxdvb_err("%s\n", strerror(errno));
|
||||||
return cERR_LINUXDVB_ERROR;
|
return cERR_LINUXDVB_ERROR;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (ioctl( videofd, VIDEO_CLEAR_BUFFER, NULL) == -1)
|
if (ioctl( videofd, VIDEO_CLEAR_BUFFER) == -1)
|
||||||
{
|
{
|
||||||
linuxdvb_err("ioctl failed with errno %d\n", errno);
|
linuxdvb_err("ioctl failed with errno %d\n", errno);
|
||||||
linuxdvb_err("VIDEO_CLEAR_BUFFER: %s\n", strerror(errno));
|
linuxdvb_err("VIDEO_CLEAR_BUFFER: %s\n", strerror(errno));
|
||||||
@@ -145,20 +145,20 @@ int LinuxDvbOpen(Context_t *context __attribute__((unused)), char * type) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
if (audio && audiofd == -1) {
|
if (audio && audiofd < 0) {
|
||||||
audiofd = open(AUDIODEV, O_RDWR);
|
audiofd = open(AUDIODEV, O_RDWR);
|
||||||
|
|
||||||
if (audiofd <= 0)
|
if (audiofd < 0)
|
||||||
{
|
{
|
||||||
linuxdvb_err("failed to open %s - errno %d\n", AUDIODEV, errno);
|
linuxdvb_err("failed to open %s - errno %d\n", AUDIODEV, errno);
|
||||||
linuxdvb_err("%s\n", strerror(errno));
|
linuxdvb_err("%s\n", strerror(errno));
|
||||||
|
|
||||||
if (videofd != -1)
|
if (videofd < 0)
|
||||||
close(videofd);
|
close(videofd);
|
||||||
return cERR_LINUXDVB_ERROR;
|
return cERR_LINUXDVB_ERROR;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (ioctl( audiofd, AUDIO_CLEAR_BUFFER, NULL) == -1)
|
if (ioctl( audiofd, AUDIO_CLEAR_BUFFER) == -1)
|
||||||
{
|
{
|
||||||
linuxdvb_err("ioctl failed with errno %d\n", errno);
|
linuxdvb_err("ioctl failed with errno %d\n", errno);
|
||||||
linuxdvb_err("AUDIO_CLEAR_BUFFER: %s\n", strerror(errno));
|
linuxdvb_err("AUDIO_CLEAR_BUFFER: %s\n", strerror(errno));
|
||||||
@@ -302,7 +302,7 @@ int LinuxDvbStop(Context_t *context __attribute__((unused)), char * type) {
|
|||||||
getLinuxDVBMutex(FILENAME, __FUNCTION__,__LINE__);
|
getLinuxDVBMutex(FILENAME, __FUNCTION__,__LINE__);
|
||||||
|
|
||||||
if (video && videofd != -1) {
|
if (video && videofd != -1) {
|
||||||
if (ioctl(videofd, VIDEO_CLEAR_BUFFER, NULL) == -1)
|
if (ioctl(videofd, VIDEO_CLEAR_BUFFER) == -1)
|
||||||
{
|
{
|
||||||
linuxdvb_err("ioctl failed with errno %d\n", errno);
|
linuxdvb_err("ioctl failed with errno %d\n", errno);
|
||||||
linuxdvb_err("VIDEO_CLEAR_BUFFER: %s\n", strerror(errno));
|
linuxdvb_err("VIDEO_CLEAR_BUFFER: %s\n", strerror(errno));
|
||||||
@@ -314,7 +314,6 @@ int LinuxDvbStop(Context_t *context __attribute__((unused)), char * type) {
|
|||||||
linuxdvb_err("ioctl failed with errno %d\n", errno);
|
linuxdvb_err("ioctl failed with errno %d\n", errno);
|
||||||
linuxdvb_err("VIDEO_SET_SPEED: %s\n", strerror(errno));
|
linuxdvb_err("VIDEO_SET_SPEED: %s\n", strerror(errno));
|
||||||
}
|
}
|
||||||
|
|
||||||
if (ioctl(videofd, VIDEO_STOP, NULL) == -1)
|
if (ioctl(videofd, VIDEO_STOP, NULL) == -1)
|
||||||
{
|
{
|
||||||
linuxdvb_err("ioctl failed with errno %d\n", errno);
|
linuxdvb_err("ioctl failed with errno %d\n", errno);
|
||||||
@@ -323,7 +322,7 @@ int LinuxDvbStop(Context_t *context __attribute__((unused)), char * type) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (audio && audiofd != -1) {
|
if (audio && audiofd != -1) {
|
||||||
if (ioctl(audiofd, AUDIO_CLEAR_BUFFER, NULL) == -1)
|
if (ioctl(audiofd, AUDIO_CLEAR_BUFFER) == -1)
|
||||||
{
|
{
|
||||||
linuxdvb_err("ioctl failed with errno %d\n", errno);
|
linuxdvb_err("ioctl failed with errno %d\n", errno);
|
||||||
linuxdvb_err("AUDIO_CLEAR_BUFFER: %s\n", strerror(errno));
|
linuxdvb_err("AUDIO_CLEAR_BUFFER: %s\n", strerror(errno));
|
||||||
@@ -335,7 +334,6 @@ int LinuxDvbStop(Context_t *context __attribute__((unused)), char * type) {
|
|||||||
linuxdvb_err("ioctl failed with errno %d\n", errno);
|
linuxdvb_err("ioctl failed with errno %d\n", errno);
|
||||||
linuxdvb_err("AUDIO_SET_SPEED: %s\n", strerror(errno));
|
linuxdvb_err("AUDIO_SET_SPEED: %s\n", strerror(errno));
|
||||||
}
|
}
|
||||||
|
|
||||||
if (ioctl(audiofd, AUDIO_STOP, NULL) == -1)
|
if (ioctl(audiofd, AUDIO_STOP, NULL) == -1)
|
||||||
{
|
{
|
||||||
linuxdvb_err("ioctl failed with errno %d\n", errno);
|
linuxdvb_err("ioctl failed with errno %d\n", errno);
|
||||||
@@ -475,12 +473,16 @@ int LinuxDvbFlush(Context_t *context __attribute__((unused)), char * type) {
|
|||||||
getLinuxDVBMutex(FILENAME, __FUNCTION__,__LINE__);
|
getLinuxDVBMutex(FILENAME, __FUNCTION__,__LINE__);
|
||||||
|
|
||||||
if (video && videofd != -1) {
|
if (video && videofd != -1) {
|
||||||
|
if (ioctl(videofd, VIDEO_CLEAR_BUFFER) == -1)
|
||||||
|
{
|
||||||
|
linuxdvb_err("ioctl failed with errno %d\n", errno);
|
||||||
|
linuxdvb_err("VIDEO_CLEAR_BUFFER: %s\n", strerror(errno));
|
||||||
|
}
|
||||||
if (ioctl(videofd, VIDEO_FLUSH ,NULL) == -1)
|
if (ioctl(videofd, VIDEO_FLUSH ,NULL) == -1)
|
||||||
{
|
{
|
||||||
linuxdvb_err("ioctl failed with errno %d\n", errno);
|
linuxdvb_err("ioctl failed with errno %d\n", errno);
|
||||||
linuxdvb_err("VIDEO_FLUSH: %s\n", strerror(errno));
|
linuxdvb_err("VIDEO_FLUSH: %s\n", strerror(errno));
|
||||||
}
|
}
|
||||||
|
|
||||||
if (ioctl(videofd, VIDEO_STOP, NULL) == -1)
|
if (ioctl(videofd, VIDEO_STOP, NULL) == -1)
|
||||||
{
|
{
|
||||||
linuxdvb_err("ioctl failed with errno %d\n", errno);
|
linuxdvb_err("ioctl failed with errno %d\n", errno);
|
||||||
@@ -489,6 +491,11 @@ int LinuxDvbFlush(Context_t *context __attribute__((unused)), char * type) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (audio && audiofd != -1) {
|
if (audio && audiofd != -1) {
|
||||||
|
if (ioctl(audiofd, AUDIO_CLEAR_BUFFER) == -1)
|
||||||
|
{
|
||||||
|
linuxdvb_err("ioctl failed with errno %d\n", errno);
|
||||||
|
linuxdvb_err("AUDIO_CLEAR_BUFFER: %s\n", strerror(errno));
|
||||||
|
}
|
||||||
if (ioctl(audiofd, AUDIO_FLUSH ,NULL) == -1)
|
if (ioctl(audiofd, AUDIO_FLUSH ,NULL) == -1)
|
||||||
{
|
{
|
||||||
linuxdvb_err("ioctl failed with errno %d\n", errno);
|
linuxdvb_err("ioctl failed with errno %d\n", errno);
|
||||||
@@ -721,7 +728,7 @@ int LinuxDvbClear(Context_t *context __attribute__((unused)), char * type) {
|
|||||||
getLinuxDVBMutex(FILENAME, __FUNCTION__,__LINE__);
|
getLinuxDVBMutex(FILENAME, __FUNCTION__,__LINE__);
|
||||||
|
|
||||||
if (video && videofd != -1) {
|
if (video && videofd != -1) {
|
||||||
if (ioctl(videofd, VIDEO_CLEAR_BUFFER, NULL) == -1)
|
if (ioctl(videofd, VIDEO_CLEAR_BUFFER) == -1)
|
||||||
{
|
{
|
||||||
linuxdvb_err("ioctl failed with errno %d\n", errno);
|
linuxdvb_err("ioctl failed with errno %d\n", errno);
|
||||||
linuxdvb_err("VIDEO_CLEAR_BUFFER: %s\n", strerror(errno));
|
linuxdvb_err("VIDEO_CLEAR_BUFFER: %s\n", strerror(errno));
|
||||||
@@ -729,7 +736,7 @@ int LinuxDvbClear(Context_t *context __attribute__((unused)), char * type) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (audio && audiofd != -1) {
|
if (audio && audiofd != -1) {
|
||||||
if (ioctl(audiofd, AUDIO_CLEAR_BUFFER, NULL) == -1)
|
if (ioctl(audiofd, AUDIO_CLEAR_BUFFER) == -1)
|
||||||
{
|
{
|
||||||
linuxdvb_err("ioctl failed with errno %d\n", errno);
|
linuxdvb_err("ioctl failed with errno %d\n", errno);
|
||||||
linuxdvb_err("AUDIO_CLEAR_BUFFER: %s\n", strerror(errno));
|
linuxdvb_err("AUDIO_CLEAR_BUFFER: %s\n", strerror(errno));
|
||||||
@@ -746,35 +753,25 @@ int LinuxDvbClear(Context_t *context __attribute__((unused)), char * type) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
int LinuxDvbPts(Context_t *context __attribute__((unused)), unsigned long long int* pts) {
|
int LinuxDvbPts(Context_t *context __attribute__((unused)), unsigned long long int* pts) {
|
||||||
int ret = cERR_LINUXDVB_NO_ERROR;
|
int ret = cERR_LINUXDVB_ERROR;
|
||||||
|
|
||||||
linuxdvb_printf(50, "\n");
|
linuxdvb_printf(50, "\n");
|
||||||
|
|
||||||
// pts is a non writting requests and can be done in parallel to other requests
|
// pts is a non writting requests and can be done in parallel to other requests
|
||||||
//getLinuxDVBMutex(FILENAME, __FUNCTION__,__LINE__);
|
//getLinuxDVBMutex(FILENAME, __FUNCTION__,__LINE__);
|
||||||
|
|
||||||
if (videofd != -1)
|
if (videofd > -1 && !ioctl(videofd, VIDEO_GET_PTS, (void*)&sCURRENT_PTS))
|
||||||
{
|
ret = cERR_LINUXDVB_NO_ERROR;
|
||||||
if (ioctl(videofd, VIDEO_GET_PTS, (void*)&sCURRENT_PTS) == -1)
|
else
|
||||||
{
|
linuxdvb_err("VIDEO_GET_PTS: %d (%s)\n", errno, strerror(errno));
|
||||||
linuxdvb_err("ioctl failed with errno %d\n", errno);
|
|
||||||
linuxdvb_err("VIDEO_GET_PTS: %s\n", strerror(errno));
|
if (audiofd > -1 && ret != cERR_LINUXDVB_NO_ERROR && !ioctl(audiofd, AUDIO_GET_PTS, (void*)&sCURRENT_PTS))
|
||||||
ret = cERR_LINUXDVB_ERROR;
|
ret = cERR_LINUXDVB_NO_ERROR;
|
||||||
}
|
else
|
||||||
}
|
linuxdvb_err("AUDIO_GET_PTS: %d (%s)\n", errno, strerror(errno));
|
||||||
else if (audiofd != -1)
|
|
||||||
{
|
if (ret != cERR_LINUXDVB_NO_ERROR)
|
||||||
if (ioctl(audiofd, AUDIO_GET_PTS, (void*)&sCURRENT_PTS) == -1)
|
|
||||||
{
|
|
||||||
linuxdvb_err("ioctl failed with errno %d\n", errno);
|
|
||||||
linuxdvb_err("AUDIO_GET_PTS: %s\n", strerror(errno));
|
|
||||||
ret = cERR_LINUXDVB_ERROR;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
sCURRENT_PTS = 0;
|
sCURRENT_PTS = 0;
|
||||||
ret = cERR_LINUXDVB_ERROR;
|
|
||||||
}
|
|
||||||
|
|
||||||
*((unsigned long long int *)pts)=(unsigned long long int)sCURRENT_PTS;
|
*((unsigned long long int *)pts)=(unsigned long long int)sCURRENT_PTS;
|
||||||
|
|
||||||
@@ -849,7 +846,7 @@ int LinuxDvbSwitch(Context_t *context, char * type) {
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (ioctl(audiofd, AUDIO_CLEAR_BUFFER ,NULL) == -1)
|
if (ioctl(audiofd, AUDIO_CLEAR_BUFFER) == -1)
|
||||||
{
|
{
|
||||||
linuxdvb_err("ioctl failed with errno %d\n", errno);
|
linuxdvb_err("ioctl failed with errno %d\n", errno);
|
||||||
linuxdvb_err("AUDIO_CLEAR_BUFFER: %s\n", strerror(errno));
|
linuxdvb_err("AUDIO_CLEAR_BUFFER: %s\n", strerror(errno));
|
||||||
@@ -896,7 +893,7 @@ int LinuxDvbSwitch(Context_t *context, char * type) {
|
|||||||
linuxdvb_err("VIDEO_STOP: %s\n", strerror(errno));
|
linuxdvb_err("VIDEO_STOP: %s\n", strerror(errno));
|
||||||
}
|
}
|
||||||
|
|
||||||
if (ioctl(videofd, VIDEO_CLEAR_BUFFER ,NULL) == -1)
|
if (ioctl(videofd, VIDEO_CLEAR_BUFFER) == -1)
|
||||||
{
|
{
|
||||||
linuxdvb_err("ioctl failed with errno %d\n", errno);
|
linuxdvb_err("ioctl failed with errno %d\n", errno);
|
||||||
linuxdvb_err("VIDEO_CLEAR_BUFFER: %s\n", strerror(errno));
|
linuxdvb_err("VIDEO_CLEAR_BUFFER: %s\n", strerror(errno));
|
||||||
|
@@ -214,6 +214,7 @@ bool cPlayback::Start(char *filename, unsigned short vpid, int vtype, unsigned s
|
|||||||
if (pm != PLAYMODE_TS && player && player->output && player->playback) {
|
if (pm != PLAYMODE_TS && player && player->output && player->playback) {
|
||||||
player->output->Command(player, OUTPUT_OPEN, NULL);
|
player->output->Command(player, OUTPUT_OPEN, NULL);
|
||||||
|
|
||||||
|
SetAPid(apid, 0);
|
||||||
if ( player->playback->Command(player, PLAYBACK_PLAY, NULL) == 0 ) // playback.c uses "int = 0" for "true"
|
if ( player->playback->Command(player, PLAYBACK_PLAY, NULL) == 0 ) // playback.c uses "int = 0" for "true"
|
||||||
ret = true;
|
ret = true;
|
||||||
}
|
}
|
||||||
@@ -526,7 +527,10 @@ void cPlayback::FindAllPids(uint16_t *apids, unsigned short *ac3flags, uint16_t
|
|||||||
for (i = 0,j=0; TrackList[i] != NULL; i+=2,j++) {
|
for (i = 0,j=0; TrackList[i] != NULL; i+=2,j++) {
|
||||||
printf("\t%s - %s\n", TrackList[i], TrackList[i+1]);
|
printf("\t%s - %s\n", TrackList[i], TrackList[i+1]);
|
||||||
if (j < max_numpida) {
|
if (j < max_numpida) {
|
||||||
apids[j]=j;
|
int _pid;
|
||||||
|
char _lang[strlen(TrackList[i])];
|
||||||
|
if (2 == sscanf(TrackList[i], "%d %s\n", &_pid, _lang)) {
|
||||||
|
apids[j]=(uint16_t)_pid;
|
||||||
// atUnknown, atMPEG, atMP3, atAC3, atDTS, atAAC, atPCM, atOGG, atFLAC
|
// atUnknown, atMPEG, atMP3, atAC3, atDTS, atAAC, atPCM, atOGG, atFLAC
|
||||||
if( !strncmp("A_MPEG/L3", TrackList[i+1], 9))
|
if( !strncmp("A_MPEG/L3", TrackList[i+1], 9))
|
||||||
ac3flags[j] = 4;
|
ac3flags[j] = 4;
|
||||||
@@ -544,7 +548,8 @@ void cPlayback::FindAllPids(uint16_t *apids, unsigned short *ac3flags, uint16_t
|
|||||||
ac3flags[j] = 0; //todo
|
ac3flags[j] = 0; //todo
|
||||||
else
|
else
|
||||||
ac3flags[j] = 0; //todo
|
ac3flags[j] = 0; //todo
|
||||||
language[j]=std::string(TrackList[i]);
|
language[j]=std::string(_lang);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
free(TrackList[i]);
|
free(TrackList[i]);
|
||||||
free(TrackList[i+1]);
|
free(TrackList[i+1]);
|
||||||
@@ -569,8 +574,12 @@ void cPlayback::FindAllSubtitlePids(uint16_t *pids, uint16_t *numpids, std::stri
|
|||||||
for (i = 0,j=0; TrackList[i] != NULL; i+=2,j++) {
|
for (i = 0,j=0; TrackList[i] != NULL; i+=2,j++) {
|
||||||
printf("\t%s - %s\n", TrackList[i], TrackList[i+1]);
|
printf("\t%s - %s\n", TrackList[i], TrackList[i+1]);
|
||||||
if (j < max_numpids) {
|
if (j < max_numpids) {
|
||||||
pids[j]=j;
|
int _pid;
|
||||||
language[j]=std::string(TrackList[i]);
|
char _lang[strlen(TrackList[i])];
|
||||||
|
if (2 == sscanf(TrackList[i], "%d %s\n", &_pid, _lang)) {
|
||||||
|
pids[j]=(uint16_t)_pid;
|
||||||
|
language[j]=std::string(_lang);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
free(TrackList[i]);
|
free(TrackList[i]);
|
||||||
free(TrackList[i+1]);
|
free(TrackList[i+1]);
|
||||||
@@ -595,8 +604,12 @@ void cPlayback::FindAllDvbsubtitlePids(uint16_t *pids, uint16_t *numpids, std::s
|
|||||||
for (i = 0,j=0; TrackList[i] != NULL; i+=2,j++) {
|
for (i = 0,j=0; TrackList[i] != NULL; i+=2,j++) {
|
||||||
printf("\t%s - %s\n", TrackList[i], TrackList[i+1]);
|
printf("\t%s - %s\n", TrackList[i], TrackList[i+1]);
|
||||||
if (j < max_numpids) {
|
if (j < max_numpids) {
|
||||||
pids[j]=j;
|
int _pid;
|
||||||
language[j]=std::string(TrackList[i]);
|
char _lang[strlen(TrackList[i])];
|
||||||
|
if (2 == sscanf(TrackList[i], "%d %s\n", &_pid, _lang)) {
|
||||||
|
pids[j]=(uint16_t)_pid;
|
||||||
|
language[j]=std::string(_lang);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
free(TrackList[i]);
|
free(TrackList[i]);
|
||||||
free(TrackList[i+1]);
|
free(TrackList[i+1]);
|
||||||
@@ -622,11 +635,12 @@ void cPlayback::FindAllTeletextsubtitlePids(uint16_t *pids, uint16_t *numpids, s
|
|||||||
int type = 0;
|
int type = 0;
|
||||||
printf("\t%s - %s\n", TrackList[i], TrackList[i+1]);
|
printf("\t%s - %s\n", TrackList[i], TrackList[i+1]);
|
||||||
if (j < max_numpids) {
|
if (j < max_numpids) {
|
||||||
if (1 != sscanf(TrackList[i], "%*d %*s %d %*d %*d", &type))
|
int _pid;
|
||||||
|
if (2 != sscanf(TrackList[i], "%d %*s %d %*d %*d", &_pid, &type))
|
||||||
continue;
|
continue;
|
||||||
if (type != 2 && type != 5) // return subtitles only
|
if (type != 2 && type != 5) // return subtitles only
|
||||||
continue;
|
continue;
|
||||||
pids[j]=j;
|
pids[j]=(uint16_t)_pid;
|
||||||
language[j]=std::string(TrackList[i]);
|
language[j]=std::string(TrackList[i]);
|
||||||
j++;
|
j++;
|
||||||
}
|
}
|
||||||
|
Reference in New Issue
Block a user