From 0824b330fb8b260dca2eeb80a44fca2230420ba4 Mon Sep 17 00:00:00 2001 From: samsamsam Date: Fri, 30 Mar 2018 14:29:35 +0200 Subject: [PATCH 01/19] Do not wait in the FFMPEG thread. Signed-off-by: max_10 Origin commit data ------------------ Branch: master Commit: https://github.com/neutrino-images/ni-libstb-hal/commit/da5077caa25be75114b9ff1bc57893efcbe050a5 Author: samsamsam Date: 2018-03-30 (Fri, 30 Mar 2018) ------------------ This commit was generated by Migit --- libeplayer3-arm/container/container_ffmpeg.c | 27 +++++++++++++++----- libeplayer3-arm/container/flv2mpeg4_ffmpeg.c | 2 +- libeplayer3-arm/container/mpeg4p2_ffmpeg.c | 2 +- libeplayer3-arm/main/exteplayer.c | 18 +++++++++++-- 4 files changed, 38 insertions(+), 11 deletions(-) diff --git a/libeplayer3-arm/container/container_ffmpeg.c b/libeplayer3-arm/container/container_ffmpeg.c index 5fec340..874e78f 100644 --- a/libeplayer3-arm/container/container_ffmpeg.c +++ b/libeplayer3-arm/container/container_ffmpeg.c @@ -182,7 +182,7 @@ static void releaseMutex(const char *filename __attribute__((unused)), const con typedef int32_t (* Write_FN)(Context_t *context, void *); -static int32_t Write(Write_FN WriteFun, Context_t *context, void *privateData) +static int32_t Write(Write_FN WriteFun, Context_t *context, void *privateData, int64_t pts __attribute__((unused))) { /* Because Write is blocking we will release mutex which protect * avformat structures, during write time @@ -485,6 +485,10 @@ static int64_t calcPts(uint32_t avContextIdx, AVStream *stream, int64_t pts) { pts = INVALID_PTS_VALUE; } + else + { + pts &= 0x01FFFFFFFF; // PES header can handle only 33 bit PTS + } return pts; } @@ -571,6 +575,14 @@ static void FFMPEGThread(Context_t *context) int8_t isWaitingForFinish = 0; while (context && context->playback && context->playback->isPlaying) { + /* When user press PAUSE we call pause on AUDIO and VIDEO decoders, + * we will not wait here because we can still fill + * DVB drivers buffers at PAUSE time + * + * In the future we can add buffering queue before injection in to + * AUDIO, VIDEO decoders, so we can not wait here + */ +#ifdef __sh__ //IF MOVIE IS PAUSED, WAIT if (context->playback->isPaused) { @@ -579,6 +591,7 @@ static void FFMPEGThread(Context_t *context) usleep(10000); continue; } +#endif if (context->playback->isSeeking) { ffmpeg_printf(10, "seeking\n"); @@ -835,7 +848,7 @@ static void FFMPEGThread(Context_t *context) { avOut.infoFlags = 1; // TS container } - if (Write(context->output->video->Write, context, &avOut) < 0) + if (Write(context->output->video->Write, context, &avOut, pts) < 0) { ffmpeg_err("writing data to video device failed\n"); } @@ -903,7 +916,7 @@ static void FFMPEGThread(Context_t *context) avOut.width = 0; avOut.height = 0; avOut.type = "audio"; - if (Write(context->output->audio->Write, context, &avOut) < 0) + if (Write(context->output->audio->Write, context, &avOut, pts) < 0) { ffmpeg_err("(raw pcm) writing data to audio device failed\n"); } @@ -1079,7 +1092,7 @@ static void FFMPEGThread(Context_t *context) avOut.width = 0; avOut.height = 0; avOut.type = "audio"; - if (!context->playback->BackWard && Write(context->output->audio->Write, context, &avOut) < 0) + if (!context->playback->BackWard && Write(context->output->audio->Write, context, &avOut, pts) < 0) { ffmpeg_err("writing data to audio device failed\n"); } @@ -1100,7 +1113,7 @@ static void FFMPEGThread(Context_t *context) avOut.width = 0; avOut.height = 0; avOut.type = "audio"; - if (!context->playback->BackWard && Write(context->output->audio->Write, context, &avOut) < 0) + if (!context->playback->BackWard && Write(context->output->audio->Write, context, &avOut, pts) < 0) { ffmpeg_err("(aac) writing data to audio device failed\n"); } @@ -1117,7 +1130,7 @@ static void FFMPEGThread(Context_t *context) avOut.width = 0; avOut.height = 0; avOut.type = "audio"; - if (!context->playback->BackWard && Write(context->output->audio->Write, context, &avOut) < 0) + if (!context->playback->BackWard && Write(context->output->audio->Write, context, &avOut, pts) < 0) { ffmpeg_err("writing data to audio device failed\n"); } @@ -1146,7 +1159,7 @@ static void FFMPEGThread(Context_t *context) subOut.data = (uint8_t *)packet.data; subOut.pts = pts; subOut.durationMS = duration; - if (Write(context->output->subtitle->Write, context, &subOut) < 0) + if (Write(context->output->subtitle->Write, context, &subOut, pts) < 0) { ffmpeg_err("writing data to teletext fifo failed\n"); } diff --git a/libeplayer3-arm/container/flv2mpeg4_ffmpeg.c b/libeplayer3-arm/container/flv2mpeg4_ffmpeg.c index a96e055..8f72216 100644 --- a/libeplayer3-arm/container/flv2mpeg4_ffmpeg.c +++ b/libeplayer3-arm/container/flv2mpeg4_ffmpeg.c @@ -34,7 +34,7 @@ static int flv2mpeg4_context_write_packet_cb(void *usr_data, int keyframe, int p avOut.width = ctx->track->width; avOut.height = ctx->track->height; avOut.type = "video"; - if (Write(ctx->out_ctx->output->video->Write, ctx->out_ctx, &avOut) < 0) + if (Write(ctx->out_ctx->output->video->Write, ctx->out_ctx, &avOut, avOut.pts) < 0) { ffmpeg_err("writing data to video device failed\n"); } diff --git a/libeplayer3-arm/container/mpeg4p2_ffmpeg.c b/libeplayer3-arm/container/mpeg4p2_ffmpeg.c index f77ef73..74a5559 100644 --- a/libeplayer3-arm/container/mpeg4p2_ffmpeg.c +++ b/libeplayer3-arm/container/mpeg4p2_ffmpeg.c @@ -107,7 +107,7 @@ static void mpeg4p2_write(Context_t *ctx, Track_t *track, int avContextIdx, int6 avOut.width = track->width; avOut.height = track->height; avOut.type = "video"; - if (Write(ctx->output->video->Write, ctx, &avOut) < 0) + if (Write(ctx->output->video->Write, ctx, &avOut, avOut.pts) < 0) { ffmpeg_err("writing data to video device failed\n"); } diff --git a/libeplayer3-arm/main/exteplayer.c b/libeplayer3-arm/main/exteplayer.c index d7c2c19..0589587 100644 --- a/libeplayer3-arm/main/exteplayer.c +++ b/libeplayer3-arm/main/exteplayer.c @@ -635,7 +635,7 @@ int main(int argc, char *argv[]) memset(argvBuff, '\0', sizeof(argvBuff)); int commandRetVal = -1; /* inform client that we can handle additional commands */ - fprintf(stderr, "{\"EPLAYER3_EXTENDED\":{\"version\":%d}}\n", 39); + fprintf(stderr, "{\"EPLAYER3_EXTENDED\":{\"version\":%d}}\n", 40); 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"); @@ -922,7 +922,21 @@ int main(int argc, char *argv[]) commandRetVal = g_player->playback->Command(g_player, PLAYBACK_PTS, &pts); if (0 == commandRetVal) { - fprintf(stderr, "{\"J\":{\"ms\":%lld}}\n", pts / 90); + int64_t lastPts = 0; + commandRetVal = 1; + if (g_player->container && g_player->container->selectedContainer) + { + commandRetVal = g_player->container->selectedContainer->Command((Context_t*)g_player->container, CONTAINER_LAST_PTS, &lastPts); + } + + if (0 == commandRetVal && lastPts != INVALID_PTS_VALUE) + { + fprintf(stderr, "{\"J\":{\"ms\":%lld,\"lms\":%lld}}\n", pts / 90, lastPts / 90); + } + else + { + fprintf(stderr, "{\"J\":{\"ms\":%lld}}\n", pts / 90); + } } break; } From bd5187dc8c8db9493dbd963e394b609b3f0e214f Mon Sep 17 00:00:00 2001 From: samsamsam Date: Sat, 31 Mar 2018 11:39:41 +0200 Subject: [PATCH 02/19] Add buffering for Linux DVB outputs Signed-off-by: max_10 Origin commit data ------------------ Branch: master Commit: https://github.com/neutrino-images/ni-libstb-hal/commit/98103766665393f4b762ac00623ae8529191f55a Author: samsamsam Date: 2018-03-31 (Sat, 31 Mar 2018) ------------------ This commit was generated by Migit --- libeplayer3-arm/Makefile.am | 1 + libeplayer3-arm/include/output.h | 1 + libeplayer3-arm/include/writer.h | 1 + libeplayer3-arm/main/exteplayer.c | 16 +- libeplayer3-arm/output/linuxdvb_buffering.c | 389 +++++++++++++++++++ libeplayer3-arm/output/linuxdvb_mipsel.c | 380 +++++------------- libeplayer3-arm/output/output.c | 41 +- libeplayer3-arm/output/writer/mipsel/aac.c | 6 +- libeplayer3-arm/output/writer/mipsel/ac3.c | 2 +- libeplayer3-arm/output/writer/mipsel/amr.c | 2 +- libeplayer3-arm/output/writer/mipsel/divx3.c | 2 +- libeplayer3-arm/output/writer/mipsel/dts.c | 2 +- libeplayer3-arm/output/writer/mipsel/h263.c | 2 +- libeplayer3-arm/output/writer/mipsel/h264.c | 5 +- libeplayer3-arm/output/writer/mipsel/h265.c | 5 +- libeplayer3-arm/output/writer/mipsel/lpcm.c | 2 +- libeplayer3-arm/output/writer/mipsel/mp3.c | 2 +- libeplayer3-arm/output/writer/mipsel/mpeg2.c | 2 +- libeplayer3-arm/output/writer/mipsel/mpeg4.c | 2 +- libeplayer3-arm/output/writer/mipsel/pcm.c | 4 +- libeplayer3-arm/output/writer/mipsel/vc1.c | 2 +- libeplayer3-arm/output/writer/mipsel/vp.c | 2 +- libeplayer3-arm/output/writer/mipsel/wma.c | 2 +- libeplayer3-arm/output/writer/mipsel/wmv.c | 2 +- libeplayer3-arm/playback/playback.c | 8 - 25 files changed, 563 insertions(+), 320 deletions(-) create mode 100644 libeplayer3-arm/output/linuxdvb_buffering.c diff --git a/libeplayer3-arm/Makefile.am b/libeplayer3-arm/Makefile.am index b1bdd32..1f7f51e 100644 --- a/libeplayer3-arm/Makefile.am +++ b/libeplayer3-arm/Makefile.am @@ -21,6 +21,7 @@ libeplayer3_arm_la_SOURCES = \ output/linuxdvb_mipsel.c \ output/output_subtitle.c \ output/output.c \ + output/linuxdvb_buffering.c \ output/writer/common/pes.c \ output/writer/common/misc.c \ output/writer/mipsel/writer.c \ diff --git a/libeplayer3-arm/include/output.h b/libeplayer3-arm/include/output.h index 5b0fedb..16a61f1 100644 --- a/libeplayer3-arm/include/output.h +++ b/libeplayer3-arm/include/output.h @@ -28,6 +28,7 @@ typedef enum OUTPUT_DISCONTINUITY_REVERSE, OUTPUT_GET_FRAME_COUNT, OUTPUT_GET_PROGRESSIVE, + OUTPUT_SET_BUFFER_SIZE, } OutputCmd_t; typedef struct diff --git a/libeplayer3-arm/include/writer.h b/libeplayer3-arm/include/writer.h index c027899..28c74d3 100644 --- a/libeplayer3-arm/include/writer.h +++ b/libeplayer3-arm/include/writer.h @@ -22,6 +22,7 @@ typedef struct unsigned int Height; unsigned char Version; unsigned int InfoFlags; + ssize_t (* WriteV) (int, const struct iovec *, size_t); } WriterAVCallData_t; typedef struct WriterCaps_s diff --git a/libeplayer3-arm/main/exteplayer.c b/libeplayer3-arm/main/exteplayer.c index 0589587..a71e33b 100644 --- a/libeplayer3-arm/main/exteplayer.c +++ b/libeplayer3-arm/main/exteplayer.c @@ -480,14 +480,14 @@ static void UpdateVideoTrack() HandleTracks(g_player->manager->video, (PlaybackCmd_t) - 1, "vc"); } -static int ParseParams(int argc, char *argv[], char *file, char *audioFile, int *pAudioTrackIdx, int *subtitleTrackIdx) +static int ParseParams(int argc, char *argv[], char *file, char *audioFile, int *pAudioTrackIdx, int *subtitleTrackIdx, uint32_t *linuxDvbBufferSizeMB) { int ret = 0; int c; //int digit_optind = 0; //int aopt = 0, bopt = 0; //char *copt = 0, *dopt = 0; - while ((c = getopt(argc, argv, "we3dlsrimva:n:x:u:c:h:o:p:P:t:9:0:1:4:f:")) != -1) + while ((c = getopt(argc, argv, "we3dlsrimva:n:x:u:c:h:o:p:P:t:9:0:1:4:f:b:")) != -1) { switch (c) { @@ -597,6 +597,9 @@ static int ParseParams(int argc, char *argv[], char *file, char *audioFile, int free(ffopt); break; } + case 'b': + *linuxDvbBufferSizeMB = 1024 * 1024 * atoi(optarg); + break; default: printf("?? getopt returned character code 0%o ??\n", c); ret = -1; @@ -631,14 +634,16 @@ int main(int argc, char *argv[]) memset(audioFile, '\0', sizeof(audioFile)); 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", 40); - if (0 != ParseParams(argc, argv, file, audioFile, &audioTrackIdx, &subtitleTrackIdx)) + fprintf(stderr, "{\"EPLAYER3_EXTENDED\":{\"version\":%d}}\n", 41); + if (0 != ParseParams(argc, argv, file, audioFile, &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"); @@ -707,6 +712,9 @@ int main(int argc, char *argv[]) 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(file, "rtmp", 4) && strncmp(file, "ffrtmp", 4)) { diff --git a/libeplayer3-arm/output/linuxdvb_buffering.c b/libeplayer3-arm/output/linuxdvb_buffering.c new file mode 100644 index 0000000..c8f106e --- /dev/null +++ b/libeplayer3-arm/output/linuxdvb_buffering.c @@ -0,0 +1,389 @@ +/* + * RAM write buffering utilities + * samsamsam 2018 + * + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + */ + +/* ***************************** */ +/* Includes */ +/* ***************************** */ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "common.h" +#include "misc.h" +#include "writer.h" + +/* ***************************** */ +/* Types */ +/* ***************************** */ +typedef enum OutputType_e{ + OUTPUT_UNK, + OUTPUT_AUDIO, + OUTPUT_VIDEO, +} OutputType_t; + +typedef struct BufferingNode_s { + uint32_t dataSize; + OutputType_t dataType; + struct BufferingNode_s *next; +} BufferingNode_t; + +/* ***************************** */ +/* Makros/Constants */ +/* ***************************** */ +#define cERR_LINUX_DVB_BUFFERING_NO_ERROR 0 +#define cERR_LINUX_DVB_BUFFERING_ERROR -1 + +//#define SAM_WITH_DEBUG +#ifdef SAM_WITH_DEBUG +#define LINUX_DVB_BUFFERING_DEBUG +#else +#define LINUX_DVB_BUFFERING_SILENT +#endif + +#ifdef LINUX_DVB_BUFFERING_DEBUG + +static const uint16_t debug_level = 40; + +#define buff_printf(level, fmt, x...) do { \ +if (debug_level >= level) printf("[%s:%d:%s] " fmt, __FILE__, __LINE__, __FUNCTION__, ## x); } while (0) +#else +#define buff_printf(level, fmt, x...) +#endif + +#ifndef LINUX_DVB_BUFFERING_SILENT +#define buff_err(fmt, x...) do { printf("[%s:%d:%s] " fmt, __FILE__, __LINE__, __FUNCTION__, ## x); } while (0) +#else +#define buff_err(fmt, x...) +#endif + +/* ***************************** */ +/* Varaibles */ +/* ***************************** */ +static pthread_t bufferingThread; +static pthread_mutex_t bufferingMtx; +static pthread_cond_t bufferingExitCond; +static pthread_cond_t bufferingDataConsumedCond; +static pthread_cond_t bufferingdDataAddedCond; +static bool hasBufferingThreadStarted = false; +static BufferingNode_t *bufferingQueueHead = NULL; +static BufferingNode_t *bufferingQueueTail = NULL; + +static uint32_t maxBufferingDataSize = 0; +static uint32_t bufferingDataSize = 0; + +static int videofd = -1; +static int audiofd = -1; + +/* ***************************** */ +/* Prototypes */ +/* ***************************** */ + +/* ***************************** */ +/* MISC Functions */ +/* ***************************** */ + +/* **************************** */ +/* Worker Thread */ +/* **************************** */ +static void LinuxDvbBuffThread(Context_t *context) +{ + static BufferingNode_t *nodePtr = NULL; + buff_printf(20, "ENTER\n"); + while (0 == PlaybackDieNow(0)) + { + pthread_mutex_lock(&bufferingMtx); + if (nodePtr) + { + free(nodePtr); + nodePtr = NULL; + /* signal that we free some space in queue */ + pthread_cond_signal(&bufferingDataConsumedCond); + } + + if (!bufferingQueueHead) + { + assert(bufferingQueueTail == NULL); + + /* Queue is empty we need to wait for data to be added */ + pthread_cond_wait(&bufferingdDataAddedCond, &bufferingMtx); + pthread_mutex_unlock(&bufferingMtx); + continue; /* To check PlaybackDieNow(0) */ + } + else + { + nodePtr = bufferingQueueHead; + bufferingQueueHead = bufferingQueueHead->next; + if (bufferingQueueHead == NULL) + { + bufferingQueueTail = NULL; + } + + if (bufferingDataSize >= (nodePtr->dataSize + sizeof(BufferingNode_t))) + { + bufferingDataSize -= (nodePtr->dataSize + sizeof(BufferingNode_t)); + } + else + { + assert(bufferingDataSize == 0); + bufferingDataSize = 0; + } + } + pthread_mutex_unlock(&bufferingMtx); + + /* We will write data without mutex + * this have some disadvantage because we can + * write some portion of data after LinuxDvbBuffFlush, + * for example after seek, this will be fixed later + */ + if (nodePtr && !context->playback->isSeeking) + { + /* Write data to valid output */ + uint8_t *dataPtr = (uint8_t *)nodePtr + sizeof(BufferingNode_t); + int fd = nodePtr->dataType == OUTPUT_VIDEO ? videofd : audiofd; + if (0 != write_with_retry(fd, dataPtr, nodePtr->dataSize)) + { + printf("Something is WRONG\n"); + } + } + } + + pthread_mutex_lock(&bufferingMtx); + pthread_cond_signal(&bufferingExitCond); + pthread_mutex_unlock(&bufferingMtx); + + buff_printf(20, "EXIT\n"); + hasBufferingThreadStarted = false; +} + +int32_t WriteSetBufferingSize(const uint32_t bufferSize) +{ + maxBufferingDataSize = bufferSize; + return cERR_LINUX_DVB_BUFFERING_NO_ERROR; +} + +int32_t LinuxDvbBuffOpen(Context_t *context, char *type, int outfd) +{ + int32_t error = 0; + int32_t ret = cERR_LINUX_DVB_BUFFERING_NO_ERROR; + + buff_printf(10, "\n"); + + if (!hasBufferingThreadStarted) + { + pthread_attr_t attr; + pthread_attr_init(&attr); + pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED); + + if((error = pthread_create(&bufferingThread, &attr, (void *)&LinuxDvbBuffThread, context)) != 0) + { + buff_printf(10, "Creating thread, error:%d:%s\n", error, strerror(error)); + + hasBufferingThreadStarted = false; + ret = cERR_LINUX_DVB_BUFFERING_ERROR; + } + else + { + buff_printf(10, "Created thread\n"); + hasBufferingThreadStarted = true; + + /* init synchronization prymitives */ + pthread_mutex_init(&bufferingMtx, NULL); + + pthread_cond_init(&bufferingExitCond, NULL); + pthread_cond_init(&bufferingDataConsumedCond, NULL); + pthread_cond_init(&bufferingdDataAddedCond, NULL); + } + } + + if (!ret) + { + if (!strcmp("video", type) && -1 == videofd) + { + videofd = outfd; + } + else if (!strcmp("audio", type) && -1 == audiofd) + { + audiofd = outfd; + } + else + { + ret = cERR_LINUX_DVB_BUFFERING_ERROR; + } + } + + buff_printf(10, "exiting with value %d\n", ret); + return ret; +} + +int32_t LinuxDvbBuffClose(Context_t *context) +{ + int32_t ret = 0; + + buff_printf(10, "\n"); + videofd = -1; + audiofd = -1; + + if (hasBufferingThreadStarted) + { + struct timespec max_wait = {0, 0}; + pthread_mutex_lock(&bufferingMtx); + /* wait for thread end */ + clock_gettime(CLOCK_REALTIME, &max_wait); + max_wait.tv_sec += 1; + pthread_cond_timedwait(&bufferingExitCond, &bufferingMtx, &max_wait); + pthread_mutex_unlock(&bufferingMtx); + + if (!hasBufferingThreadStarted) + { + /* destroy synchronization prymitives? + * for a moment, we'll exit linux process, + * so the system will do this for us + */ + /* + pthread_mutex_destroy(&bufferingMtx); + pthread_cond_destroy(&bufferingDataConsumedCond); + pthread_cond_destroy(&bufferingdDataAddedCond); + */ + } + } + + ret = hasBufferingThreadStarted ? cERR_LINUX_DVB_BUFFERING_ERROR : cERR_LINUX_DVB_BUFFERING_NO_ERROR; + + buff_printf(10, "exiting with value %d\n", ret); + return ret; +} + +int32_t LinuxDvbBuffFlush(Context_t *context) +{ + static BufferingNode_t *nodePtr = NULL; + buff_printf(40, "ENTER bufferingQueueHead[%p]\n", bufferingQueueHead); + pthread_mutex_lock(&bufferingMtx); + while (bufferingQueueHead) + { + nodePtr = bufferingQueueHead; + bufferingQueueHead = nodePtr->next; + bufferingDataSize -= (nodePtr->dataSize + sizeof(BufferingNode_t)); + free(nodePtr); + } + bufferingQueueHead = NULL; + bufferingQueueTail = NULL; + buff_printf(40, "bufferingDataSize [%u]\n", bufferingDataSize); + assert(bufferingDataSize == 0); + bufferingDataSize = 0; + + /* signal that queue is empty */ + pthread_cond_signal(&bufferingDataConsumedCond); + pthread_mutex_unlock(&bufferingMtx); + buff_printf(40, "EXIT\n"); + return 0; +} + +ssize_t BufferingWriteV(int fd, const struct iovec *iov, size_t ic) +{ + OutputType_t dataType = OUTPUT_UNK; + BufferingNode_t *nodePtr = NULL; + uint8_t *dataPtr = NULL; + uint32_t chunkSize = 0; + uint32_t i = 0; + + buff_printf(60, "ENTER\n"); + if (fd == videofd) + { + buff_printf(60, "VIDEO\n"); + dataType = OUTPUT_VIDEO; + } + else if (fd == audiofd) + { + buff_printf(60, "AUDIO\n"); + dataType = OUTPUT_AUDIO; + } + else + { + buff_err("Unknown output type\n"); + return cERR_LINUX_DVB_BUFFERING_ERROR; + } + + for (i=0; i= maxBufferingDataSize) + { + /* Buffering queue is full we need wait for space*/ + pthread_cond_wait(&bufferingDataConsumedCond, &bufferingMtx); + } + else + { + /* Add chunk to buffering queue */ + if (bufferingQueueHead == NULL) + { + bufferingQueueHead = nodePtr; + bufferingQueueTail = nodePtr; + } + else + { + bufferingQueueTail->next = nodePtr; + bufferingQueueTail = nodePtr; + } + + bufferingDataSize += chunkSize; + chunkSize -= sizeof(BufferingNode_t); + nodePtr->dataSize = chunkSize; + nodePtr->dataType = dataType; + nodePtr->next = NULL; + + /* signal that we added some data to queue */ + pthread_cond_signal(&bufferingdDataAddedCond); + break; + } + } + pthread_mutex_unlock(&bufferingMtx); + buff_printf(60, "EXIT\n"); + return chunkSize; +} diff --git a/libeplayer3-arm/output/linuxdvb_mipsel.c b/libeplayer3-arm/output/linuxdvb_mipsel.c index 1699f7d..4ef70df 100644 --- a/libeplayer3-arm/output/linuxdvb_mipsel.c +++ b/libeplayer3-arm/output/linuxdvb_mipsel.c @@ -25,6 +25,7 @@ #include #include #include +#include #include #include #include @@ -93,13 +94,18 @@ struct DVBApiVideoInfo_s static struct DVBApiVideoInfo_s videoInfo = {-1, -1, -1, -1, -1}; unsigned long long int sCURRENT_PTS = 0; +bool isBufferedOutput = false; pthread_mutex_t LinuxDVBmutex; /* ***************************** */ /* Prototypes */ /* ***************************** */ - +int32_t LinuxDvbBuffOpen(Context_t *context, char *type, int outfd); +int32_t LinuxDvbBuffClose(Context_t *context); +int32_t LinuxDvbBuffFlush(Context_t *context); +ssize_t BufferingWriteV(int fd, const struct iovec *iov, size_t ic); +int32_t WriteSetBufferingSize(const uint32_t bufferSize); int LinuxDvbStop(Context_t *context, char *type); /* ***************************** */ @@ -108,15 +114,12 @@ int LinuxDvbStop(Context_t *context, char *type); void getLinuxDVBMutex(const char *filename __attribute__((unused)), const char *function __attribute__((unused)), int line __attribute__((unused))) { - linuxdvb_printf(250, "requesting mutex\n"); pthread_mutex_lock(&LinuxDVBmutex); - linuxdvb_printf(250, "received mutex\n"); } void releaseLinuxDVBMutex(const char *filename __attribute__((unused)), const char *function __attribute__((unused)), int line __attribute__((unused))) { pthread_mutex_unlock(&LinuxDVBmutex); - linuxdvb_printf(250, "released mutex\n"); } static int LinuxDvbMapBypassMode(int bypass) @@ -130,66 +133,62 @@ static int LinuxDvbMapBypassMode(int bypass) int LinuxDvbOpen(Context_t *context __attribute__((unused)), char *type) { - unsigned char video = !strcmp("video", type); - unsigned char audio = !strcmp("audio", type); + uint8_t video = !strcmp("video", type); + uint8_t audio = !strcmp("audio", type); linuxdvb_printf(10, "v%d a%d\n", video, audio); if (video && videofd < 0) { videofd = open(VIDEODEV, O_RDWR | O_CLOEXEC); if (videofd < 0) { - linuxdvb_err("failed to open %s - errno %d\n", VIDEODEV, errno); - linuxdvb_err("%s\n", strerror(errno)); + linuxdvb_err("failed to open %s - errno %d, %s\n", VIDEODEV, errno, strerror(errno)); return cERR_LINUXDVB_ERROR; } 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)); + linuxdvb_err("VIDEO_CLEAR_BUFFER: ERROR %d, %s\n", errno, strerror(errno)); } if (ioctl(videofd, VIDEO_SELECT_SOURCE, (void *)VIDEO_SOURCE_MEMORY) == -1) { - linuxdvb_err("ioctl failed with errno %d\n", errno); - linuxdvb_err("VIDEO_SELECT_SOURCE: %s\n", strerror(errno)); + linuxdvb_err("VIDEO_SELECT_SOURCE: ERROR %d, %s\n", errno, strerror(errno)); } if (ioctl(videofd, VIDEO_FREEZE) == -1) { - linuxdvb_err("ioctl failed with errno %d\n", errno); - linuxdvb_err("VIDEO_FREEZE: %s\n", strerror(errno)); + linuxdvb_err("VIDEO_FREEZE: ERROR %d, %s\n", errno, strerror(errno)); } + if (isBufferedOutput) + LinuxDvbBuffOpen(context, type, videofd); } if (audio && audiofd < 0) { audiofd = open(AUDIODEV, O_RDWR | O_CLOEXEC); if (audiofd < 0) { - linuxdvb_err("failed to open %s - errno %d\n", AUDIODEV, errno); - linuxdvb_err("%s\n", strerror(errno)); + linuxdvb_err("failed to open %s - errno %d, %s\n", AUDIODEV, errno, strerror(errno)); return cERR_LINUXDVB_ERROR; } 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)); + linuxdvb_err("AUDIO_CLEAR_BUFFER: ERROR %d, %s\n", errno, strerror(errno)); } if (ioctl(audiofd, AUDIO_SELECT_SOURCE, AUDIO_SOURCE_MEMORY) == -1) { - linuxdvb_err("ioctl failed with errno %d\n", errno); - linuxdvb_err("AUDIO_SELECT_SOURCE: %s\n", strerror(errno)); + linuxdvb_err("AUDIO_SELECT_SOURCE: ERROR %d, %s\n", errno, strerror(errno)); } if (ioctl(audiofd, AUDIO_PAUSE) == -1) { - linuxdvb_err("ioctl failed with errno %d\n", errno); - linuxdvb_err("AUDIO_PAUSE: %s\n", strerror(errno)); + linuxdvb_err("AUDIO_PAUSE: ERROR %d, %s\n", errno, strerror(errno)); } + if (isBufferedOutput) + LinuxDvbBuffOpen(context, type, audiofd); } return cERR_LINUXDVB_NO_ERROR; } int LinuxDvbClose(Context_t *context, char *type) { - unsigned char video = !strcmp("video", type); - unsigned char audio = !strcmp("audio", type); + uint8_t video = !strcmp("video", type); + uint8_t audio = !strcmp("audio", type); linuxdvb_printf(10, "v%d a%d\n", video, audio); /* closing stand alone is not allowed, so prevent * user from closing and don't call stop. stop will @@ -207,6 +206,8 @@ int LinuxDvbClose(Context_t *context, char *type) close(audiofd); audiofd = -1; } + if (isBufferedOutput) + LinuxDvbBuffClose(context); releaseLinuxDVBMutex(FILENAME, __FUNCTION__, __LINE__); return cERR_LINUXDVB_NO_ERROR; } @@ -215,8 +216,8 @@ int LinuxDvbPlay(Context_t *context, char *type) { int ret = cERR_LINUXDVB_NO_ERROR; Writer_t *writer; - unsigned char video = !strcmp("video", type); - unsigned char audio = !strcmp("audio", type); + uint8_t video = !strcmp("video", type); + uint8_t audio = !strcmp("audio", type); linuxdvb_printf(10, "v%d a%d\n", video, audio); if (video && videofd != -1) { @@ -224,15 +225,6 @@ int LinuxDvbPlay(Context_t *context, char *type) context->manager->video->Command(context, MANAGER_GETENCODING, &Encoding); linuxdvb_printf(10, "V %s\n", Encoding); writer = getWriter(Encoding); - // SULGE VU 4K dont like this - /* - if (0 != ioctl(videofd, VIDEO_STOP)) - { - linuxdvb_err("ioctl failed with errno %d\n", errno); - linuxdvb_err("VIDEO_STOP: %s\n", strerror(errno)); - ret = cERR_LINUXDVB_ERROR; - } - */ if (writer == NULL) { linuxdvb_err("cannot found writer for encoding %s using default\n", Encoding); @@ -243,27 +235,23 @@ int LinuxDvbPlay(Context_t *context, char *type) linuxdvb_printf(20, "found writer %s for encoding %s\n", writer->caps->name, Encoding); if (ioctl(videofd, VIDEO_SET_STREAMTYPE, (void *) writer->caps->dvbStreamType) == -1) { - linuxdvb_err("ioctl failed with errno %d\n", errno); - linuxdvb_err("VIDEO_SET_STREAMTYPE: %s\n", strerror(errno)); + linuxdvb_err("VIDEO_SET_STREAMTYPE: ERROR %d, %s\n", errno, strerror(errno)); ret = cERR_LINUXDVB_ERROR; } } free(Encoding); if (0 != ioctl(videofd, VIDEO_PLAY)) { - linuxdvb_err("ioctl failed with errno %d\n", errno); - linuxdvb_err("VIDEO_PLAY: %s\n", strerror(errno)); + linuxdvb_err("VIDEO_PLAY: ERROR %d, %s\n", errno, strerror(errno)); ret = cERR_LINUXDVB_ERROR; } if (ioctl(videofd, VIDEO_CONTINUE) == -1) { - linuxdvb_err("ioctl failed with errno %d\n", errno); - linuxdvb_err("VIDEO_CONTINUE: %s\n", strerror(errno)); + linuxdvb_err("VIDEO_CONTINUE: ERROR %d, %s\n", errno, strerror(errno)); } 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)); + linuxdvb_err("VIDEO_CLEAR_BUFFER: ERROR %d, %s\n", errno, strerror(errno)); } } if (audio && audiofd != -1) @@ -272,15 +260,6 @@ int LinuxDvbPlay(Context_t *context, char *type) context->manager->audio->Command(context, MANAGER_GETENCODING, &Encoding); linuxdvb_printf(20, "0 A %s\n", Encoding); writer = getWriter(Encoding); - // SULGE VU 4K dont like this - /* - if (0 != ioctl(audiofd, AUDIO_STOP)) - { - linuxdvb_err("ioctl failed with errno %d\n", errno); - linuxdvb_err("AUDIO_STOP: %s\n", strerror(errno)); - ret = cERR_LINUXDVB_ERROR; - } - */ if (writer == NULL) { linuxdvb_err("cannot found writer for encoding %s using default\n", Encoding); @@ -291,21 +270,18 @@ int LinuxDvbPlay(Context_t *context, char *type) linuxdvb_printf(20, "found writer %s for encoding %s\n", writer->caps->name, Encoding); if (ioctl(audiofd, AUDIO_SET_BYPASS_MODE, (void *) LinuxDvbMapBypassMode(writer->caps->dvbStreamType)) < 0) { - linuxdvb_err("ioctl failed with errno %d\n", errno); - linuxdvb_err("AUDIO_SET_BYPASS_MODE: %s\n", strerror(errno)); + linuxdvb_err("AUDIO_SET_BYPASS_MODE: ERROR %d, %s\n", errno, strerror(errno)); ret = cERR_LINUXDVB_ERROR; } } if (ioctl(audiofd, AUDIO_PLAY) < 0) { - linuxdvb_err("ioctl failed with errno %d\n", errno); - linuxdvb_err("AUDIO_PLAY: %s\n", strerror(errno)); + linuxdvb_err("AUDIO_PLAY: ERROR %d, %s\n", errno, strerror(errno)); ret = cERR_LINUXDVB_ERROR; } if (ioctl(audiofd, AUDIO_CONTINUE) < 0) { - linuxdvb_err("ioctl failed with errno %d\n", errno); - linuxdvb_err("AUDIO_CONTINUE: %s\n", strerror(errno)); + linuxdvb_err("AUDIO_CONTINUE: ERROR %d, %s\n", errno, strerror(errno)); ret = cERR_LINUXDVB_ERROR; } free(Encoding); @@ -326,13 +302,11 @@ int LinuxDvbStop(Context_t *context __attribute__((unused)), char *type) { 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)); + linuxdvb_err("VIDEO_CLEAR_BUFFER: ERROR %d, %s\n", errno, strerror(errno)); } if (ioctl(videofd, VIDEO_STOP) == -1) { - linuxdvb_err("ioctl failed with errno %d\n", errno); - linuxdvb_err("VIDEO_STOP: %s\n", strerror(errno)); + linuxdvb_err("VIDEO_STOP: ERROR %d, %s\n", errno, strerror(errno)); ret = cERR_LINUXDVB_ERROR; } ioctl(videofd, VIDEO_SLOWMOTION, 0); @@ -343,21 +317,11 @@ int LinuxDvbStop(Context_t *context __attribute__((unused)), char *type) { 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)); + linuxdvb_err("AUDIO_CLEAR_BUFFER: ERROR %d, %s\n", errno, strerror(errno)); } - /* set back to normal speed (end trickmodes) */ - /* - if (ioctl(audiofd, AUDIO_SET_SPEED, DVB_SPEED_NORMAL_PLAY) == -1) - { - linuxdvb_err("ioctl failed with errno %d\n", errno); - linuxdvb_err("AUDIO_SET_SPEED: %s\n", strerror(errno)); - } - */ if (ioctl(audiofd, AUDIO_STOP) == -1) { - linuxdvb_err("ioctl failed with errno %d\n", errno); - linuxdvb_err("AUDIO_STOP: %s\n", strerror(errno)); + linuxdvb_err("AUDIO_STOP: ERROR %d, %s\n", errno, strerror(errno)); ret = cERR_LINUXDVB_ERROR; } ioctl(audiofd, AUDIO_SELECT_SOURCE, AUDIO_SOURCE_DEMUX); @@ -368,17 +332,16 @@ int LinuxDvbStop(Context_t *context __attribute__((unused)), char *type) int LinuxDvbPause(Context_t *context __attribute__((unused)), char *type) { - int ret = cERR_LINUXDVB_NO_ERROR; - unsigned char video = !strcmp("video", type); - unsigned char audio = !strcmp("audio", type); + int32_t ret = cERR_LINUXDVB_NO_ERROR; + uint8_t video = !strcmp("video", type); + uint8_t audio = !strcmp("audio", type); linuxdvb_printf(10, "v%d a%d\n", video, audio); getLinuxDVBMutex(FILENAME, __FUNCTION__, __LINE__); if (video && videofd != -1) { if (ioctl(videofd, VIDEO_FREEZE, NULL) == -1) { - linuxdvb_err("ioctl failed with errno %d\n", errno); - linuxdvb_err("VIDEO_FREEZE: %s\n", strerror(errno)); + linuxdvb_err("VIDEO_FREEZE: ERROR %d, %s\n", errno, strerror(errno)); ret = cERR_LINUXDVB_ERROR; } } @@ -386,8 +349,7 @@ int LinuxDvbPause(Context_t *context __attribute__((unused)), char *type) { if (ioctl(audiofd, AUDIO_PAUSE, NULL) == -1) { - linuxdvb_err("ioctl failed with errno %d\n", errno); - linuxdvb_err("AUDIO_PAUSE: %s\n", strerror(errno)); + linuxdvb_err("AUDIO_PAUSE: ERROR %d, %s\n", errno, strerror(errno)); ret = cERR_LINUXDVB_ERROR; } } @@ -397,9 +359,9 @@ int LinuxDvbPause(Context_t *context __attribute__((unused)), char *type) int LinuxDvbContinue(Context_t *context __attribute__((unused)), char *type) { - int ret = cERR_LINUXDVB_NO_ERROR; - unsigned char video = !strcmp("video", type); - unsigned char audio = !strcmp("audio", type); + int32_t ret = cERR_LINUXDVB_NO_ERROR; + uint8_t video = !strcmp("video", type); + uint8_t audio = !strcmp("audio", type); linuxdvb_printf(10, "v%d a%d\n", video, audio); if (video && videofd != -1) { @@ -409,8 +371,7 @@ int LinuxDvbContinue(Context_t *context __attribute__((unused)), char *type) } if (ioctl(videofd, VIDEO_CONTINUE, NULL) == -1) { - linuxdvb_err("ioctl failed with errno %d\n", errno); - linuxdvb_err("VIDEO_CONTINUE: %s\n", strerror(errno)); + linuxdvb_err("VIDEO_CONTINUE: ERROR %d, %s\n", errno, strerror(errno)); ret = cERR_LINUXDVB_ERROR; } } @@ -418,8 +379,7 @@ int LinuxDvbContinue(Context_t *context __attribute__((unused)), char *type) { if (ioctl(audiofd, AUDIO_CONTINUE, NULL) == -1) { - linuxdvb_err("ioctl failed with errno %d\n", errno); - linuxdvb_err("AUDIO_CONTINUE: %s\n", strerror(errno)); + linuxdvb_err("AUDIO_CONTINUE: ERROR %d, %s\n", errno, strerror(errno)); ret = cERR_LINUXDVB_ERROR; } } @@ -427,22 +387,6 @@ int LinuxDvbContinue(Context_t *context __attribute__((unused)), char *type) return ret; } -int LinuxDvbReverseDiscontinuity(Context_t *context __attribute__((unused)), int *surplus __attribute__((unused))) -{ - int ret = cERR_LINUXDVB_NO_ERROR; - /* - int dis_type = VIDEO_DISCONTINUITY_CONTINUOUS_REVERSE | *surplus; - linuxdvb_printf(50, "\n"); - if (ioctl(videofd, VIDEO_DISCONTINUITY, (void *) dis_type) == -1) - { - linuxdvb_err("ioctl failed with errno %d\n", errno); - linuxdvb_err("VIDEO_DISCONTINUITY: %s\n", strerror(errno)); - } - linuxdvb_printf(50, "exiting\n"); - */ - return ret; -} - int LinuxDvbAudioMute(Context_t *context __attribute__((unused)), char *flag) { int ret = cERR_LINUXDVB_NO_ERROR; @@ -451,25 +395,17 @@ int LinuxDvbAudioMute(Context_t *context __attribute__((unused)), char *flag) { if (*flag == '1') { - //AUDIO_SET_MUTE has no effect with new player - //if (ioctl(audiofd, AUDIO_SET_MUTE, 1) == -1) if (ioctl(audiofd, AUDIO_STOP, NULL) == -1) { - linuxdvb_err("ioctl failed with errno %d\n", errno); - //linuxdvb_err("AUDIO_SET_MUTE: %s\n", strerror(errno)); - linuxdvb_err("AUDIO_STOP: %s\n", strerror(errno)); + linuxdvb_err("AUDIO_STOP: ERROR %d, %s\n", errno, strerror(errno)); ret = cERR_LINUXDVB_ERROR; } } else { - //AUDIO_SET_MUTE has no effect with new player - //if (ioctl(audiofd, AUDIO_SET_MUTE, 0) == -1) if (ioctl(audiofd, AUDIO_PLAY) == -1) { - linuxdvb_err("ioctl failed with errno %d\n", errno); - //linuxdvb_err("AUDIO_SET_MUTE: %s\n", strerror(errno)); - linuxdvb_err("AUDIO_PLAY: %s\n", strerror(errno)); + linuxdvb_err("AUDIO_PLAY: ERROR %d, %s\n", errno, strerror(errno)); ret = cERR_LINUXDVB_ERROR; } } @@ -480,52 +416,23 @@ int LinuxDvbAudioMute(Context_t *context __attribute__((unused)), char *flag) int LinuxDvbFlush(Context_t *context __attribute__((unused)), char *type __attribute__((unused))) { - /* - unsigned char video = !strcmp("video", type); - unsigned char audio = !strcmp("audio", type); - linuxdvb_printf(10, "v%d a%d\n", video, audio); - if ((video && videofd != -1) || (audio && audiofd != -1)) - { - getLinuxDVBMutex(FILENAME, __FUNCTION__, __LINE__); - if (video && videofd != -1) - { - if (ioctl(videofd, VIDEO_FLUSH, NULL) == -1) - { - linuxdvb_err("ioctl failed with errno %d\n", errno); - linuxdvb_err("VIDEO_FLUSH: %s\n", strerror(errno)); - } - } - if (audio && audiofd != -1) - { - if (ioctl(audiofd, AUDIO_FLUSH, NULL) == -1) - { - linuxdvb_err("ioctl failed with errno %d\n", errno); - linuxdvb_err("AUDIO_FLUSH: %s\n", strerror(errno)); - } - } - releaseLinuxDVBMutex(FILENAME, __FUNCTION__, __LINE__); - } - linuxdvb_printf(10, "exiting\n"); - */ return cERR_LINUXDVB_NO_ERROR; } -#ifndef use_set_speed_instead_ff int LinuxDvbFastForward(Context_t *context, char *type) { - int ret = cERR_LINUXDVB_NO_ERROR; - unsigned char video = !strcmp("video", type); - unsigned char audio = !strcmp("audio", type); + int32_t ret = cERR_LINUXDVB_NO_ERROR; + uint8_t video = !strcmp("video", type); + uint8_t audio = !strcmp("audio", type); if (audio) {} linuxdvb_printf(10, "v%d a%d speed %d\n", video, audio, context->playback->Speed); if (video && videofd != -1) { getLinuxDVBMutex(FILENAME, __FUNCTION__, __LINE__); - /* konfetti comment: speed is a value given in skipped frames */ + // konfetti comment: speed is a value given in skipped frames if (ioctl(videofd, VIDEO_FAST_FORWARD, context->playback->Speed) == -1) { - linuxdvb_err("ioctl failed with errno %d\n", errno); - linuxdvb_err("VIDEO_FAST_FORWARD: %s\n", strerror(errno)); + linuxdvb_err("VIDEO_FAST_FORWARD: ERROR %d, %s\n", errno, strerror(errno)); ret = cERR_LINUXDVB_ERROR; } releaseLinuxDVBMutex(FILENAME, __FUNCTION__, __LINE__); @@ -533,69 +440,12 @@ int LinuxDvbFastForward(Context_t *context, char *type) linuxdvb_printf(10, "exiting with value %d\n", ret); return ret; } -#else - -static unsigned int SpeedList[] = -{ - 1000, 1100, 1200, 1300, 1500, - 2000, 3000, 4000, 5000, 8000, - 12000, 16000, - 125, 250, 500, 700, 800, 900 -}; - -int LinuxDvbFastForward(Context_t *context, char *type) -{ - int ret = cERR_LINUXDVB_NO_ERROR; - int speedIndex; - unsigned char video = !strcmp("video", type); - unsigned char audio = !strcmp("audio", type); - linuxdvb_printf(10, "v%d a%d\n", video, audio); - if (video && videofd != -1) - { - getLinuxDVBMutex(FILENAME, __FUNCTION__, __LINE__); - speedIndex = context->playback->Speed % (sizeof(SpeedList) / sizeof(int)); - linuxdvb_printf(1, "speedIndex %d\n", speedIndex); - /* - if (ioctl(videofd, VIDEO_SET_SPEED, SpeedList[speedIndex]) == -1) - { - linuxdvb_err("ioctl failed with errno %d\n", errno); - linuxdvb_err("VIDEO_SET_SPEED: %s\n", strerror(errno)); - ret = cERR_LINUXDVB_ERROR; - } - */ - releaseLinuxDVBMutex(FILENAME, __FUNCTION__, __LINE__); - } - if (audio && audiofd != -1) - { - getLinuxDVBMutex(FILENAME, __FUNCTION__, __LINE__); - speedIndex = context->playback->Speed % (sizeof(SpeedList) / sizeof(int)); - linuxdvb_printf(1, "speedIndex %d\n", speedIndex); - /* - if (ioctl(audiofd, AUDIO_SET_SPEED, SpeedList[speedIndex]) == -1) - { - linuxdvb_err("ioctl failed with errno %d\n", errno); - linuxdvb_err("AUDIO_SET_SPEED: %s\n", strerror(errno)); - ret = cERR_LINUXDVB_ERROR; - } - */ - releaseLinuxDVBMutex(FILENAME, __FUNCTION__, __LINE__); - } - linuxdvb_printf(10, "exiting with value %d\n", ret); - return ret; -} -#endif - -int LinuxDvbReverse(Context_t *context __attribute__((unused)), char *type __attribute__((unused))) -{ - int ret = cERR_LINUXDVB_NO_ERROR; - return ret; -} int LinuxDvbSlowMotion(Context_t *context, char *type) { - int ret = cERR_LINUXDVB_NO_ERROR; - unsigned char video = !strcmp("video", type); - unsigned char audio = !strcmp("audio", type); + int32_t ret = cERR_LINUXDVB_NO_ERROR; + uint8_t video = !strcmp("video", type); + uint8_t audio = !strcmp("audio", type); linuxdvb_printf(10, "v%d a%d\n", video, audio); if ((video && videofd != -1) || (audio && audiofd != -1)) { @@ -604,8 +454,7 @@ int LinuxDvbSlowMotion(Context_t *context, char *type) { if (ioctl(videofd, VIDEO_SLOWMOTION, context->playback->SlowMotion) == -1) { - linuxdvb_err("ioctl failed with errno %d\n", errno); - linuxdvb_err("VIDEO_SLOWMOTION: %s\n", strerror(errno)); + linuxdvb_err("VIDEO_SLOWMOTION: ERROR %d, %s\n", errno, strerror(errno)); ret = cERR_LINUXDVB_ERROR; } } @@ -617,7 +466,7 @@ int LinuxDvbSlowMotion(Context_t *context, char *type) int LinuxDvbAVSync(Context_t *context __attribute__((unused)), char *type __attribute__((unused))) { - int ret = cERR_LINUXDVB_NO_ERROR; + int32_t ret = cERR_LINUXDVB_NO_ERROR; /* konfetti: this one is dedicated to audiofd so we * are ignoring what is given by type! I think we should * remove this param. Therefor we should add a variable @@ -629,8 +478,7 @@ int LinuxDvbAVSync(Context_t *context __attribute__((unused)), char *type __attr getLinuxDVBMutex(FILENAME, __FUNCTION__, __LINE__); if (ioctl(audiofd, AUDIO_SET_AV_SYNC, 0) == -1) //context->playback->AVSync) == -1) { - linuxdvb_err("ioctl failed with errno %d\n", errno); - linuxdvb_err("AUDIO_SET_AV_SYNC: %s\n", strerror(errno)); + linuxdvb_err("AUDIO_SET_AV_SYNC: ERROR %d, %s\n", errno, strerror(errno)); ret = cERR_LINUXDVB_ERROR; } releaseLinuxDVBMutex(FILENAME, __FUNCTION__, __LINE__); @@ -643,7 +491,7 @@ int LinuxDvbClear(Context_t *context __attribute__((unused)), char *type) int32_t ret = cERR_LINUXDVB_NO_ERROR; uint8_t video = !strcmp("video", type); uint8_t audio = !strcmp("audio", type); - linuxdvb_printf(10, ">>>>>>>>>>LinuxDvbClear v%d a%d\n", video, audio); + linuxdvb_printf(10, "LinuxDvbClear v%d a%d\n", video, audio); if ((video && videofd != -1) || (audio && audiofd != -1)) { getLinuxDVBMutex(FILENAME, __FUNCTION__, __LINE__); @@ -651,8 +499,7 @@ int LinuxDvbClear(Context_t *context __attribute__((unused)), char *type) { 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)); + linuxdvb_err("VIDEO_CLEAR_BUFFER: ERROR %d, %s\n", errno, strerror(errno)); ret = cERR_LINUXDVB_ERROR; } } @@ -660,8 +507,7 @@ int LinuxDvbClear(Context_t *context __attribute__((unused)), char *type) { 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)); + linuxdvb_err("AUDIO_CLEAR_BUFFER: ERROR %d, %s\n", errno, strerror(errno)); ret = cERR_LINUXDVB_ERROR; } } @@ -673,17 +519,16 @@ int LinuxDvbClear(Context_t *context __attribute__((unused)), char *type) int LinuxDvbPts(Context_t *context __attribute__((unused)), unsigned long long int *pts) { - int ret = cERR_LINUXDVB_ERROR; + int32_t ret = cERR_LINUXDVB_ERROR; linuxdvb_printf(50, "\n"); - // pts is a non writting requests and can be done in parallel to other requests - //getLinuxDVBMutex(FILENAME, __FUNCTION__,__LINE__); + // GET_PTS is immutable call, so it can be done in parallel to other requests if (videofd > -1 && !ioctl(videofd, VIDEO_GET_PTS, (void *)&sCURRENT_PTS)) { ret = cERR_LINUXDVB_NO_ERROR; } else { - linuxdvb_err("VIDEO_GET_PTS: %d (%s)\n", errno, strerror(errno)); + linuxdvb_err("VIDEO_GET_PTS: ERROR %d, %s\n", errno, strerror(errno)); } if (ret != cERR_LINUXDVB_NO_ERROR) { @@ -693,7 +538,7 @@ int LinuxDvbPts(Context_t *context __attribute__((unused)), unsigned long long i } else { - linuxdvb_err("AUDIO_GET_PTS: %d (%s)\n", errno, strerror(errno)); + linuxdvb_err("AUDIO_GET_PTS: ERROR %d, %s\n", errno, strerror(errno)); } } if (ret != cERR_LINUXDVB_NO_ERROR) @@ -701,20 +546,18 @@ int LinuxDvbPts(Context_t *context __attribute__((unused)), unsigned long long i sCURRENT_PTS = 0; } *((unsigned long long int *)pts) = (unsigned long long int)sCURRENT_PTS; - //releaseLinuxDVBMutex(FILENAME, __FUNCTION__,__LINE__); return ret; } int LinuxDvbGetFrameCount(Context_t *context __attribute__((unused)), unsigned long long int *frameCount __attribute__((unused))) { - int ret = cERR_LINUXDVB_NO_ERROR; - return ret; + return cERR_LINUXDVB_NO_ERROR; } int LinuxDvbSwitch(Context_t *context, char *type) { - unsigned char audio = !strcmp("audio", type); - unsigned char video = !strcmp("video", type); + uint8_t audio = !strcmp("audio", type); + uint8_t video = !strcmp("video", type); Writer_t *writer; linuxdvb_printf(10, "v%d a%d\n", video, audio); if ((video && videofd != -1) || (audio && audiofd != -1)) @@ -730,38 +573,27 @@ int LinuxDvbSwitch(Context_t *context, char *type) writer = getWriter(Encoding); if (ioctl(audiofd, AUDIO_STOP, NULL) == -1) { - linuxdvb_err("ioctl failed with errno %d\n", errno); - linuxdvb_err("AUDIO_STOP: %s\n", strerror(errno)); + linuxdvb_err("AUDIO_STOP: ERROR %d, %s\n", errno, strerror(errno)); } 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)); + linuxdvb_err("AUDIO_CLEAR_BUFFER: ERROR %d, %s\n", errno, strerror(errno)); } if (writer == NULL) { linuxdvb_err("cannot found writer for encoding %s using default\n", Encoding); - /* - if (ioctl(audiofd, AUDIO_SET_BYPASS_MODE, (void *) AUDIO_ENCODING_MP3) == -1) - { - linuxdvb_err("ioctl failed with errno %d\n", errno); - linuxdvb_err("AUDIO_SET_BYPASS_MODE: %s\n", strerror(errno)); - } - */ } else { linuxdvb_printf(10, "found writer %s for encoding %s\n", writer->caps->name, Encoding); if (ioctl(audiofd, AUDIO_SET_BYPASS_MODE, (void *) LinuxDvbMapBypassMode(writer->caps->dvbStreamType)) == -1) { - linuxdvb_err("ioctl failed with errno %d\n", errno); - linuxdvb_err("AUDIO_SET_BYPASS_MODE: %s\n", strerror(errno)); + linuxdvb_err("AUDIO_SET_BYPASS_MODE: ERROR %d, %s\n", errno, strerror(errno)); } } if (ioctl(audiofd, AUDIO_PLAY) == -1) { - linuxdvb_err("ioctl failed with errno %d\n", errno); - linuxdvb_err("AUDIO_PLAY: %s\n", strerror(errno)); + linuxdvb_err("AUDIO_PLAY: ERROR %d, %s\n", errno, strerror(errno)); } free(Encoding); } @@ -778,34 +610,24 @@ int LinuxDvbSwitch(Context_t *context, char *type) context->manager->video->Command(context, MANAGER_GETENCODING, &Encoding); if (ioctl(videofd, VIDEO_STOP, NULL) == -1) { - linuxdvb_err("ioctl failed with errno %d\n", errno); - linuxdvb_err("VIDEO_STOP: %s\n", strerror(errno)); + linuxdvb_err("VIDEO_STOP: ERROR %d, %s\n", errno, strerror(errno)); } 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)); + linuxdvb_err("VIDEO_CLEAR_BUFFER: ERROR %d, %s\n", errno, strerror(errno)); } linuxdvb_printf(10, "V %s\n", Encoding); writer = getWriter(Encoding); if (writer == NULL) { linuxdvb_err("cannot found writer for encoding %s using default\n", Encoding); - /* - if (ioctl(videofd, VIDEO_SET_STREAMTYPE, (void *) VIDEO_ENCODING_AUTO) == -1) - { - linuxdvb_err("ioctl failed with errno %d\n", errno); - linuxdvb_err("VIDEO_SET_STREAMTYPE: %s\n", strerror(errno)); - } - */ } else { linuxdvb_printf(10, "found writer %s for encoding %s\n", writer->caps->name, Encoding); if (ioctl(videofd, VIDEO_SET_STREAMTYPE, (void *) writer->caps->dvbStreamType) == -1) { - linuxdvb_err("ioctl failed with errno %d\n", errno); - linuxdvb_err("VIDEO_SET_STREAMTYPE: %s\n", strerror(errno)); + linuxdvb_err("VIDEO_SET_STREAMTYPE: ERROR %d, %s\n", errno, strerror(errno)); } } if (ioctl(videofd, VIDEO_PLAY) == -1) @@ -813,8 +635,7 @@ int LinuxDvbSwitch(Context_t *context, char *type) /* konfetti: fixme: think on this, I think we should * return an error here and stop the playback mode */ - linuxdvb_err("ioctl failed with errno %d\n", errno); - linuxdvb_err("VIDEO_PLAY: %s\n", strerror(errno)); + linuxdvb_err("VIDEO_PLAY:ERROR %d, %s\n", errno, strerror(errno)); } free(Encoding); } @@ -832,11 +653,11 @@ int LinuxDvbSwitch(Context_t *context, char *type) static int Write(Context_t *context, void *_out) { AudioVideoOut_t *out = (AudioVideoOut_t *) _out; - int ret = cERR_LINUXDVB_NO_ERROR; - int res = 0; - unsigned char video = 0; - unsigned char audio = 0; - Writer_t *writer; + int32_t ret = cERR_LINUXDVB_NO_ERROR; + int32_t res = 0; + uint8_t video = 0; + uint8_t audio = 0; + Writer_t *writer = NULL; WriterAVCallData_t call; if (out == NULL) { @@ -921,7 +742,8 @@ static int Write(Context_t *context, void *_out) call.Width = out->width; call.Height = out->height; call.InfoFlags = out->infoFlags; - call.Version = 0; // is unsingned char + call.Version = 0; + call.WriteV = isBufferedOutput ? BufferingWriteV : writev_with_retry; if (writer->writeData) { res = writer->writeData(&call); @@ -963,7 +785,8 @@ static int Write(Context_t *context, void *_out) call.FrameRate = out->frameRate; call.FrameScale = out->timeScale; call.InfoFlags = out->infoFlags; - call.Version = 0; /* -1; unsigned char cannot be negative */ + call.Version = 0; + call.WriteV = isBufferedOutput ? BufferingWriteV : writev_with_retry; if (writer->writeData) { res = writer->writeData(&call); @@ -1009,6 +832,8 @@ static int reset(Context_t *context) writer->reset(); } free(Encoding); + if (isBufferedOutput) + LinuxDvbBuffFlush(context); return ret; } @@ -1065,11 +890,6 @@ static int Command(Context_t *context, OutputCmd_t command, void *argument) return LinuxDvbFastForward(context, (char *)argument); break; } - case OUTPUT_REVERSE: - { - return LinuxDvbReverse(context, (char *)argument); - break; - } case OUTPUT_AVSYNC: { ret = LinuxDvbAVSync(context, (char *)argument); @@ -1104,11 +924,6 @@ static int Command(Context_t *context, OutputCmd_t command, void *argument) return LinuxDvbAudioMute(context, (char *)argument); break; } - case OUTPUT_DISCONTINUITY_REVERSE: - { - return LinuxDvbReverseDiscontinuity(context, (int *)argument); - break; - } case OUTPUT_GET_FRAME_COUNT: { unsigned long long int frameCount = 0; @@ -1122,6 +937,21 @@ static int Command(Context_t *context, OutputCmd_t command, void *argument) *((int *)argument) = videoInfo.progressive; break; } + case OUTPUT_SET_BUFFER_SIZE: + { + ret = cERR_LINUXDVB_ERROR; + if (!isBufferedOutput) + { + uint32_t bufferSize = *((uint32_t*)argument); + ret = cERR_LINUXDVB_NO_ERROR; + if (bufferSize > 0) + { + WriteSetBufferingSize(bufferSize); + isBufferedOutput = true; + } + } + break; + } default: linuxdvb_err("ContainerCmd %d not supported!\n", command); ret = cERR_LINUXDVB_ERROR; diff --git a/libeplayer3-arm/output/output.c b/libeplayer3-arm/output/output.c index 168c203..8c1580f 100644 --- a/libeplayer3-arm/output/output.c +++ b/libeplayer3-arm/output/output.c @@ -522,21 +522,40 @@ static int Command(Context_t *context, OutputCmd_t command, void *argument) ret = cERR_OUTPUT_INTERNAL_ERROR; } break; - case OUTPUT_GET_PROGRESSIVE: + } + case OUTPUT_GET_PROGRESSIVE: + { + if (context && context->playback) { - if (context && context->playback) + if (context->playback->isVideo) { - if (context->playback->isVideo) - { - return context->output->video->Command(context, OUTPUT_GET_PROGRESSIVE, (void *) argument); - } + return context->output->video->Command(context, OUTPUT_GET_PROGRESSIVE, (void *) argument); } - else - { - ret = cERR_OUTPUT_INTERNAL_ERROR; - } - break; } + else + { + ret = cERR_OUTPUT_INTERNAL_ERROR; + } + break; + } + case OUTPUT_SET_BUFFER_SIZE: + { + if (context && context->playback) + { + if (context->output->video) + { + return context->output->video->Command(context, OUTPUT_SET_BUFFER_SIZE, argument); + } + else if (context->output->audio) + { + return context->output->audio->Command(context, OUTPUT_SET_BUFFER_SIZE, argument); + } + } + else + { + ret = cERR_OUTPUT_INTERNAL_ERROR; + } + break; } default: output_err("%s::%s OutputCmd %d not supported!\n", __FILE__, __FUNCTION__, command); diff --git a/libeplayer3-arm/output/writer/mipsel/aac.c b/libeplayer3-arm/output/writer/mipsel/aac.c index 8e6d163..c1cec2d 100644 --- a/libeplayer3-arm/output/writer/mipsel/aac.c +++ b/libeplayer3-arm/output/writer/mipsel/aac.c @@ -195,7 +195,7 @@ static int _writeData(WriterAVCallData_t *call, int type) iov[0].iov_len = HeaderLength; iov[1].iov_base = call->data; iov[1].iov_len = call->len; - return writev_with_retry(call->fd, iov, 2); + return call->WriteV(call->fd, iov, 2); } static int writeDataADTS(WriterAVCallData_t *call) @@ -253,7 +253,7 @@ static int writeDataADTS(WriterAVCallData_t *call) iov[0].iov_len = headerSize + AAC_HEADER_LENGTH; iov[1].iov_base = call->data; iov[1].iov_len = call->len; - return writev_with_retry(call->fd, iov, 2); + return call->WriteV(call->fd, iov, 2); } static int writeDataLATM(WriterAVCallData_t *call) @@ -309,7 +309,7 @@ static int writeDataLATM(WriterAVCallData_t *call) iov[1].iov_len = 3; iov[2].iov_base = pLATMCtx->buffer; iov[2].iov_len = pLATMCtx->len; - return writev_with_retry(call->fd, iov, 3); + return call->WriteV(call->fd, iov, 3); } /* ***************************** */ diff --git a/libeplayer3-arm/output/writer/mipsel/ac3.c b/libeplayer3-arm/output/writer/mipsel/ac3.c index b71b089..37ee989 100644 --- a/libeplayer3-arm/output/writer/mipsel/ac3.c +++ b/libeplayer3-arm/output/writer/mipsel/ac3.c @@ -126,7 +126,7 @@ static int writeData(WriterAVCallData_t *call) iov[1].iov_base = call->data; iov[1].iov_len = call->len; ac3_printf(40, "PES HEADER LEN %d\n", iov[0].iov_len); - return writev_with_retry(call->fd, iov, 2); + return call->WriteV(call->fd, iov, 2); } /* ***************************** */ diff --git a/libeplayer3-arm/output/writer/mipsel/amr.c b/libeplayer3-arm/output/writer/mipsel/amr.c index cb843b5..d509ea5 100644 --- a/libeplayer3-arm/output/writer/mipsel/amr.c +++ b/libeplayer3-arm/output/writer/mipsel/amr.c @@ -145,7 +145,7 @@ static int writeData(WriterAVCallData_t *call) iov[0].iov_len = headerSize; iov[1].iov_base = call->data; iov[1].iov_len = call->len; - int len = writev_with_retry(call->fd, iov, 2); + int len = call->WriteV(call->fd, iov, 2); amr_printf(10, "amr_Write-< len=%d\n", len); return len; } diff --git a/libeplayer3-arm/output/writer/mipsel/divx3.c b/libeplayer3-arm/output/writer/mipsel/divx3.c index 98f1f4a..de7ebab 100644 --- a/libeplayer3-arm/output/writer/mipsel/divx3.c +++ b/libeplayer3-arm/output/writer/mipsel/divx3.c @@ -169,7 +169,7 @@ static int writeData(WriterAVCallData_t *call) iov[ic++].iov_len = headerSize; iov[ic].iov_base = call->data; iov[ic++].iov_len = call->len; - int len = writev_with_retry(call->fd, iov, ic); + int len = call->WriteV(call->fd, iov, ic); divx_printf(10, "xvid_Write < len=%d\n", len); return len; } diff --git a/libeplayer3-arm/output/writer/mipsel/dts.c b/libeplayer3-arm/output/writer/mipsel/dts.c index b56969b..beb8e28 100644 --- a/libeplayer3-arm/output/writer/mipsel/dts.c +++ b/libeplayer3-arm/output/writer/mipsel/dts.c @@ -150,7 +150,7 @@ static int writeData(WriterAVCallData_t *call) iov[0].iov_len = InsertPesHeader(PesHeader, Size, MPEG_AUDIO_PES_START_CODE, call->Pts, 0); iov[1].iov_base = Data; iov[1].iov_len = Size; - int32_t len = writev_with_retry(call->fd, iov, 2); + int32_t len = call->WriteV(call->fd, iov, 2); dts_printf(10, "< len %d\n", len); return len; } diff --git a/libeplayer3-arm/output/writer/mipsel/h263.c b/libeplayer3-arm/output/writer/mipsel/h263.c index 152b026..39c4ed2 100644 --- a/libeplayer3-arm/output/writer/mipsel/h263.c +++ b/libeplayer3-arm/output/writer/mipsel/h263.c @@ -125,7 +125,7 @@ static int writeData(WriterAVCallData_t *call) iov[0].iov_len = HeaderLength; iov[1].iov_base = call->data; iov[1].iov_len = call->len; - len = writev_with_retry(call->fd, iov, 2); + len = call->WriteV(call->fd, iov, 2); h263_printf(10, "< len %d\n", len); return len; } diff --git a/libeplayer3-arm/output/writer/mipsel/h264.c b/libeplayer3-arm/output/writer/mipsel/h264.c index 9855288..4dbf2b6 100644 --- a/libeplayer3-arm/output/writer/mipsel/h264.c +++ b/libeplayer3-arm/output/writer/mipsel/h264.c @@ -55,6 +55,7 @@ /* ***************************** */ /* Makros/Constants */ /* ***************************** */ +#define H264_SILENT //#define H264_DEBUG #ifdef H264_DEBUG @@ -348,7 +349,7 @@ static int writeData(WriterAVCallData_t *call) iov[ic++].iov_len = call->len; PacketLength += call->len; iov[0].iov_len = InsertPesHeader(PesHeader, -1, MPEG_VIDEO_PES_START_CODE, VideoPts, FakeStartCode); - return writev_with_retry(call->fd, iov, ic); + return call->WriteV(call->fd, iov, ic); } else if (!call->private_data || call->private_size < 7 || 1 != call->private_data[0]) { @@ -418,7 +419,7 @@ static int writeData(WriterAVCallData_t *call) while ((pos + NalLengthBytes) < call->len); h264_printf(10, "<<<< PacketLength [%d]\n", PacketLength); iov[0].iov_len = InsertPesHeader(PesHeader, -1, MPEG_VIDEO_PES_START_CODE, VideoPts, 0); - len = writev_with_retry(call->fd, iov, ic); + len = call->WriteV(call->fd, iov, ic); PacketLength += iov[0].iov_len; if (PacketLength != len) { diff --git a/libeplayer3-arm/output/writer/mipsel/h265.c b/libeplayer3-arm/output/writer/mipsel/h265.c index cb21d99..ad59853 100644 --- a/libeplayer3-arm/output/writer/mipsel/h265.c +++ b/libeplayer3-arm/output/writer/mipsel/h265.c @@ -55,6 +55,7 @@ /* ***************************** */ /* Makros/Constants */ /* ***************************** */ +#define H264_SILENT //#define H265_DEBUG #ifdef H265_DEBUG @@ -220,7 +221,7 @@ static int writeData(WriterAVCallData_t *call) iov[ic++].iov_len = call->len; PacketLength += call->len; iov[0].iov_len = InsertPesHeader(PesHeader, -1, MPEG_VIDEO_PES_START_CODE, VideoPts, FakeStartCode); - return writev_with_retry(call->fd, iov, ic); + return call->WriteV(call->fd, iov, ic); } uint32_t PacketLength = 0; ic = 0; @@ -275,7 +276,7 @@ static int writeData(WriterAVCallData_t *call) while ((pos + NalLengthBytes) < call->len); h264_printf(10, "<<<< PacketLength [%d]\n", PacketLength); iov[0].iov_len = InsertPesHeader(PesHeader, -1, MPEG_VIDEO_PES_START_CODE, VideoPts, 0); - len = writev_with_retry(call->fd, iov, ic); + len = call->WriteV(call->fd, iov, ic); PacketLength += iov[0].iov_len; if (PacketLength != len) { diff --git a/libeplayer3-arm/output/writer/mipsel/lpcm.c b/libeplayer3-arm/output/writer/mipsel/lpcm.c index aca119e..f03fc5d 100644 --- a/libeplayer3-arm/output/writer/mipsel/lpcm.c +++ b/libeplayer3-arm/output/writer/mipsel/lpcm.c @@ -238,7 +238,7 @@ static int writeData(WriterAVCallData_t *call) iov[0].iov_len = pes_header_size; iov[1].iov_base = frame; iov[1].iov_len = i_frame_size; - i_ret_size += writev_with_retry(call->fd, iov, 2); + i_ret_size += call->WriteV(call->fd, iov, 2); } memcpy(p_buffer, call->data + i_bytes_consumed, i_leftover_samples * i_channels * 2); i_buffer_used = i_leftover_samples; diff --git a/libeplayer3-arm/output/writer/mipsel/mp3.c b/libeplayer3-arm/output/writer/mipsel/mp3.c index 88c5a82..3271f98 100644 --- a/libeplayer3-arm/output/writer/mipsel/mp3.c +++ b/libeplayer3-arm/output/writer/mipsel/mp3.c @@ -123,7 +123,7 @@ static int writeData(WriterAVCallData_t *call) iov[0].iov_len = headerSize; iov[1].iov_base = call->data; iov[1].iov_len = call->len; - int len = writev_with_retry(call->fd, iov, 2); + int len = call->WriteV(call->fd, iov, 2); mp3_printf(10, "mp3_Write-< len=%d\n", len); return len; } diff --git a/libeplayer3-arm/output/writer/mipsel/mpeg2.c b/libeplayer3-arm/output/writer/mipsel/mpeg2.c index daa9daf..2e53f70 100644 --- a/libeplayer3-arm/output/writer/mipsel/mpeg2.c +++ b/libeplayer3-arm/output/writer/mipsel/mpeg2.c @@ -125,7 +125,7 @@ static int writeData(WriterAVCallData_t *call) iov[0].iov_len = InsertPesHeader(PesHeader, PacketLength, 0xe0, call->Pts, 0); iov[1].iov_base = call->data + Position; iov[1].iov_len = PacketLength; - ssize_t l = writev_with_retry(call->fd, iov, 2); + ssize_t l = call->WriteV(call->fd, iov, 2); if (l < 0) { len = l; diff --git a/libeplayer3-arm/output/writer/mipsel/mpeg4.c b/libeplayer3-arm/output/writer/mipsel/mpeg4.c index 7abce59..23cb154 100644 --- a/libeplayer3-arm/output/writer/mipsel/mpeg4.c +++ b/libeplayer3-arm/output/writer/mipsel/mpeg4.c @@ -137,7 +137,7 @@ static int writeData(WriterAVCallData_t *call) } iov[ic].iov_base = call->data; iov[ic++].iov_len = call->len; - int len = writev_with_retry(call->fd, iov, ic); + int len = call->WriteV(call->fd, iov, ic); mpeg4_printf(10, "xvid_Write < len=%d\n", len); return len; } diff --git a/libeplayer3-arm/output/writer/mipsel/pcm.c b/libeplayer3-arm/output/writer/mipsel/pcm.c index bc63b09..8246100 100644 --- a/libeplayer3-arm/output/writer/mipsel/pcm.c +++ b/libeplayer3-arm/output/writer/mipsel/pcm.c @@ -265,10 +265,10 @@ static int writeData(WriterAVCallData_t *call) iov[0].iov_len = headerSize; iov[1].iov_base = fixed_buffer; iov[1].iov_len = fixed_buffersize; - writev_with_retry(call->fd, iov, 2); + call->WriteV(call->fd, iov, 2); fixed_buffertimestamp += fixed_bufferduration; int g_fd_dump = open("/hdd/lpcm/ffmpeg.pes", O_CREAT | O_RDWR | O_APPEND, S_IRUSR | S_IWUSR); - writev_with_retry(g_fd_dump, iov, 2); + call->WriteV(g_fd_dump, iov, 2); close(g_fd_dump); } return size; diff --git a/libeplayer3-arm/output/writer/mipsel/vc1.c b/libeplayer3-arm/output/writer/mipsel/vc1.c index f6997ab..d291e2a 100644 --- a/libeplayer3-arm/output/writer/mipsel/vc1.c +++ b/libeplayer3-arm/output/writer/mipsel/vc1.c @@ -175,7 +175,7 @@ static int writeData(WriterAVCallData_t *call) free(videocodecdata.data); videocodecdata.data = NULL; } - return writev_with_retry(call->fd, iov, ic); + return call->WriteV(call->fd, iov, ic); } /* ***************************** */ diff --git a/libeplayer3-arm/output/writer/mipsel/vp.c b/libeplayer3-arm/output/writer/mipsel/vp.c index 2e31151..0c61c8c 100644 --- a/libeplayer3-arm/output/writer/mipsel/vp.c +++ b/libeplayer3-arm/output/writer/mipsel/vp.c @@ -138,7 +138,7 @@ static int writeData(WriterAVCallData_t *call, int is_vp6) iov[0].iov_len = pes_header_len; iov[1].iov_base = call->data; iov[1].iov_len = call->len; - return writev_with_retry(call->fd, iov, 2); + return call->WriteV(call->fd, iov, 2); } static int writeDataVP6(WriterAVCallData_t *call) diff --git a/libeplayer3-arm/output/writer/mipsel/wma.c b/libeplayer3-arm/output/writer/mipsel/wma.c index 6500c7e..cea0459 100644 --- a/libeplayer3-arm/output/writer/mipsel/wma.c +++ b/libeplayer3-arm/output/writer/mipsel/wma.c @@ -158,7 +158,7 @@ static int writeData(WriterAVCallData_t *call) iov[0].iov_len = headerSize; iov[1].iov_base = call->data; iov[1].iov_len = call->len; - return writev_with_retry(call->fd, iov, 2); + return call->WriteV(call->fd, iov, 2); } /* ***************************** */ diff --git a/libeplayer3-arm/output/writer/mipsel/wmv.c b/libeplayer3-arm/output/writer/mipsel/wmv.c index 96db958..225697b 100644 --- a/libeplayer3-arm/output/writer/mipsel/wmv.c +++ b/libeplayer3-arm/output/writer/mipsel/wmv.c @@ -181,7 +181,7 @@ static int writeData(WriterAVCallData_t *call) free(videocodecdata.data); videocodecdata.data = NULL; } - return writev_with_retry(call->fd, iov, ic); + return call->WriteV(call->fd, iov, ic); } /* ***************************** */ diff --git a/libeplayer3-arm/playback/playback.c b/libeplayer3-arm/playback/playback.c index f9364e9..1cf422f 100644 --- a/libeplayer3-arm/playback/playback.c +++ b/libeplayer3-arm/playback/playback.c @@ -468,14 +468,6 @@ static int PlaybackFastBackward(Context_t *context, int *speed) playback_printf(1, "S %d B %d\n", context->playback->Speed, context->playback->BackWard); } context->output->Command(context, OUTPUT_CLEAR, NULL); - if (context->output->Command(context, OUTPUT_REVERSE, NULL) < 0) - { - playback_err("OUTPUT_REVERSE failed\n"); - context->playback->BackWard = 0; - context->playback->Speed = 1; - context->playback->isSeeking = 0; - ret = cERR_PLAYBACK_ERROR; - } } else { From 934ef0bb07fecc325063e78c5df2c282cbbb23d4 Mon Sep 17 00:00:00 2001 From: samsamsam Date: Mon, 2 Apr 2018 23:59:24 +0200 Subject: [PATCH 03/19] Linux DVB output for STBs based on Broadcom - replace active pooling by select (ready to write) Signed-off-by: max_10 Origin commit data ------------------ Branch: master Commit: https://github.com/neutrino-images/ni-libstb-hal/commit/f6f84cdd66f7bbb4046cd15556db197674af5451 Author: samsamsam Date: 2018-04-02 (Mon, 02 Apr 2018) ------------------ This commit was generated by Migit --- libeplayer3-arm/include/playback.h | 4 ++ libeplayer3-arm/include/writer.h | 2 + libeplayer3-arm/main/exteplayer.c | 31 +++++---- libeplayer3-arm/output/linuxdvb_buffering.c | 54 ++++++++++++++-- libeplayer3-arm/output/writer/mipsel/writer.c | 64 +++++++++++++++++++ libeplayer3-arm/playback/playback.c | 45 ++++++++++++- 6 files changed, 178 insertions(+), 22 deletions(-) diff --git a/libeplayer3-arm/include/playback.h b/libeplayer3-arm/include/playback.h index e817e38..68a7fc8 100644 --- a/libeplayer3-arm/include/playback.h +++ b/libeplayer3-arm/include/playback.h @@ -2,6 +2,10 @@ #define PLAYBACK_H_ #include #include +#include + +typedef void( * PlaybackDieNowCallback )(); +bool PlaybackDieNowRegisterCallback(PlaybackDieNowCallback callback); typedef enum { PLAYBACK_OPEN, diff --git a/libeplayer3-arm/include/writer.h b/libeplayer3-arm/include/writer.h index 28c74d3..5f09166 100644 --- a/libeplayer3-arm/include/writer.h +++ b/libeplayer3-arm/include/writer.h @@ -4,6 +4,7 @@ #include #include #include +#include "common.h" typedef enum { eNone, eAudio, eVideo} eWriterType_t; @@ -87,5 +88,6 @@ Writer_t *getDefaultVideoWriter(); Writer_t *getDefaultAudioWriter(); ssize_t write_with_retry(int fd, const void *buf, size_t size); ssize_t writev_with_retry(int fd, const struct iovec *iov, size_t ic); +ssize_t WriteWithRetry(Context_t *context, int pipefd, int fd, const void *buf, size_t size); #endif diff --git a/libeplayer3-arm/main/exteplayer.c b/libeplayer3-arm/main/exteplayer.c index a71e33b..6ad047b 100644 --- a/libeplayer3-arm/main/exteplayer.c +++ b/libeplayer3-arm/main/exteplayer.c @@ -84,10 +84,15 @@ static void TerminateAllSockets(void) } } -static int g_pfd[2] = {-1, -1}; /* Used to wake terminate thread */ +static int g_pfd[2] = {-1, -1}; /* Used to wake terminate thread and kbhit */ static int isPlaybackStarted = 0; static pthread_mutex_t playbackStartMtx; +static void TerminateWakeUp() +{ + write(g_pfd[1], "x", 1); +} + static void *TermThreadFun(void *arg __attribute__((unused))) { const char *socket_path = "/tmp/iptvplayer_extplayer_term_fd"; @@ -126,13 +131,6 @@ static void *TermThreadFun(void *arg __attribute__((unused))) } if (FD_ISSET(fd, &readfds)) { - /* - if ((cl = accept(fd, NULL, NULL)) == -1) - { - perror("TermThreadFun accept error"); - goto finish; - } - */ pthread_mutex_lock(&playbackStartMtx); PlaybackDieNow(1); if (isPlaybackStarted) @@ -171,16 +169,17 @@ static void map_inter_file_path(char *filename) static int kbhit(void) { struct timeval tv; - fd_set read_fd; + fd_set readfds; tv.tv_sec = 1; tv.tv_usec = 0; - FD_ZERO(&read_fd); - FD_SET(0, &read_fd); - if (-1 == select(1, &read_fd, NULL, NULL, &tv)) + FD_ZERO(&readfds); + FD_SET(0,&readfds); + FD_SET(g_pfd[0], &readfds); + if(-1 == select(g_pfd[0] + 1, &readfds, NULL, NULL, &tv)) { return 0; } - if (FD_ISSET(0, &read_fd)) + if (FD_ISSET(0, &readfds)) { return 1; } @@ -639,7 +638,7 @@ int main(int argc, char *argv[]) memset(argvBuff, '\0', sizeof(argvBuff)); int commandRetVal = -1; /* inform client that we can handle additional commands */ - fprintf(stderr, "{\"EPLAYER3_EXTENDED\":{\"version\":%d}}\n", 41); + fprintf(stderr, "{\"EPLAYER3_EXTENDED\":{\"version\":%d}}\n", 42); if (0 != ParseParams(argc, argv, file, audioFile, &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"); @@ -745,6 +744,7 @@ int main(int argc, char *argv[]) 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) @@ -763,7 +763,7 @@ int main(int argc, char *argv[]) } HandleTracks(g_player->manager->subtitle, (PlaybackCmd_t) - 1, "sc"); } - while (g_player->playback->isPlaying) + while (g_player->playback->isPlaying && 0 == PlaybackDieNow(0)) { /* we made fgets non blocking */ if (NULL == fgets(argvBuff, sizeof(argvBuff) - 1, stdin)) @@ -994,6 +994,5 @@ int main(int argc, char *argv[]) pthread_mutex_destroy(&playbackStartMtx); close(g_pfd[0]); close(g_pfd[1]); - //printOutputCapabilities(); exit(0); } diff --git a/libeplayer3-arm/output/linuxdvb_buffering.c b/libeplayer3-arm/output/linuxdvb_buffering.c index c8f106e..fb7adff 100644 --- a/libeplayer3-arm/output/linuxdvb_buffering.c +++ b/libeplayer3-arm/output/linuxdvb_buffering.c @@ -25,6 +25,7 @@ #include #include #include +#include #include #include #include @@ -98,6 +99,7 @@ static uint32_t bufferingDataSize = 0; static int videofd = -1; static int audiofd = -1; +static int g_pfd[2] = {-1, -1}; /* ***************************** */ /* Prototypes */ @@ -106,14 +108,46 @@ static int audiofd = -1; /* ***************************** */ /* MISC Functions */ /* ***************************** */ +static void WriteWakeUp() +{ + write(g_pfd[1], "x", 1); +} /* **************************** */ /* Worker Thread */ /* **************************** */ static void LinuxDvbBuffThread(Context_t *context) { + int flags = 0; static BufferingNode_t *nodePtr = NULL; buff_printf(20, "ENTER\n"); + + if (pipe(g_pfd) == -1) + { + buff_err("critical error\n"); + } + /* Make read and write ends of pipe nonblocking */ + if ((flags = fcntl(g_pfd[0], F_GETFL)) == -1) + { + buff_err("critical error\n"); + } + /* Make read end nonblocking */ + flags |= O_NONBLOCK; + if (fcntl(g_pfd[0], F_SETFL, flags) == -1) + { + buff_err("critical error\n"); + } + if ((flags = fcntl(g_pfd[1], F_GETFL)) == -1) + { + buff_err("critical error\n"); + } + /* Make write end nonblocking */ + flags |= O_NONBLOCK; + if (fcntl(g_pfd[1], F_SETFL, flags) == -1) + { + buff_err("critical error\n"); + } + PlaybackDieNowRegisterCallback(WriteWakeUp); while (0 == PlaybackDieNow(0)) { pthread_mutex_lock(&bufferingMtx); @@ -165,9 +199,9 @@ static void LinuxDvbBuffThread(Context_t *context) /* Write data to valid output */ uint8_t *dataPtr = (uint8_t *)nodePtr + sizeof(BufferingNode_t); int fd = nodePtr->dataType == OUTPUT_VIDEO ? videofd : audiofd; - if (0 != write_with_retry(fd, dataPtr, nodePtr->dataSize)) + if (0 != WriteWithRetry(context, g_pfd[0], fd, dataPtr, nodePtr->dataSize)) { - printf("Something is WRONG\n"); + buff_err("Something is WRONG\n"); } } } @@ -178,6 +212,10 @@ static void LinuxDvbBuffThread(Context_t *context) buff_printf(20, "EXIT\n"); hasBufferingThreadStarted = false; + close(g_pfd[0]); + close(g_pfd[1]); + g_pfd[0] = -1; + g_pfd[1] = -1; } int32_t WriteSetBufferingSize(const uint32_t bufferSize) @@ -240,7 +278,7 @@ int32_t LinuxDvbBuffOpen(Context_t *context, char *type, int outfd) return ret; } -int32_t LinuxDvbBuffClose(Context_t *context) +int32_t LinuxDvbBuffClose(Context_t *context __attribute__((unused))) { int32_t ret = 0; @@ -251,6 +289,10 @@ int32_t LinuxDvbBuffClose(Context_t *context) if (hasBufferingThreadStarted) { struct timespec max_wait = {0, 0}; + + /* WakeUp if we are waiting in the write */ + WriteWakeUp(); + pthread_mutex_lock(&bufferingMtx); /* wait for thread end */ clock_gettime(CLOCK_REALTIME, &max_wait); @@ -278,10 +320,14 @@ int32_t LinuxDvbBuffClose(Context_t *context) return ret; } -int32_t LinuxDvbBuffFlush(Context_t *context) +int32_t LinuxDvbBuffFlush(Context_t *context __attribute__((unused))) { static BufferingNode_t *nodePtr = NULL; buff_printf(40, "ENTER bufferingQueueHead[%p]\n", bufferingQueueHead); + + /* signal if we are waiting for write to DVB decoders */ + WriteWakeUp(); + pthread_mutex_lock(&bufferingMtx); while (bufferingQueueHead) { diff --git a/libeplayer3-arm/output/writer/mipsel/writer.c b/libeplayer3-arm/output/writer/mipsel/writer.c index 2d7f70a..594ee47 100644 --- a/libeplayer3-arm/output/writer/mipsel/writer.c +++ b/libeplayer3-arm/output/writer/mipsel/writer.c @@ -29,6 +29,7 @@ #include "misc.h" #include "writer.h" +#include "common.h" /* ***************************** */ /* Makros/Constants */ @@ -100,6 +101,69 @@ static Writer_t *AvailableWriter[] = /* Functions */ /* ***************************** */ +ssize_t WriteWithRetry(Context_t *context, int pipefd, int fd, const void *buf, size_t size) +{ + fd_set rfds; + fd_set wfds; + + ssize_t ret; + int retval = -1; + int maxFd = pipefd > fd ? pipefd : fd; + + while(size > 0 && 0 == PlaybackDieNow(0) && !context->playback->isSeeking) + { + FD_ZERO(&rfds); + FD_ZERO(&wfds); + + FD_SET(pipefd, &rfds); + FD_SET(fd, &wfds); + + retval = select(maxFd + 1, &rfds, &wfds, NULL, NULL); + if (retval < 0) + { + break; + } + + if(FD_ISSET(pipefd, &rfds)) + { + char tmp; + /* flush pipefd pipe */ + while(1 == read(pipefd, &tmp, 1)); + break; + } + + if(FD_ISSET(fd, &wfds)) + { + ret = write(fd, buf, size); + if (ret < 0) + { + switch(errno) + { + case EINTR: + case EAGAIN: + continue; + default: + retval = -3; + break; + } + if (retval < 0) + { + break; + } + } + + if (ret < 0) + { + return ret; + } + + size -= ret; + buf += ret; + } + } + return 0; +} + ssize_t write_with_retry(int fd, const void *buf, size_t size) { ssize_t ret; diff --git a/libeplayer3-arm/playback/playback.c b/libeplayer3-arm/playback/playback.c index 1cf422f..bac6adb 100644 --- a/libeplayer3-arm/playback/playback.c +++ b/libeplayer3-arm/playback/playback.c @@ -57,6 +57,8 @@ if (debug_level >= level) printf("[%s:%s] " fmt, __FILE__, __FUNCTION__, ## x); #define cMaxSpeed_ff 128 /* fixme: revise */ #define cMaxSpeed_fr -320 /* fixme: revise */ +#define MAX_PLAYBACK_DIE_NOW_CALLBACKS 10 + /* ***************************** */ /* Varaibles */ /* ***************************** */ @@ -67,17 +69,30 @@ static int hasThreadStarted = 0; /* ***************************** */ /* Prototypes */ /* ***************************** */ + static int32_t PlaybackTerminate(Context_t *context); +static int8_t dieNow = 0; +static PlaybackDieNowCallback playbackDieNowCallbacks[MAX_PLAYBACK_DIE_NOW_CALLBACKS] = {NULL}; /* ***************************** */ /* MISC Functions */ /* ***************************** */ + int8_t PlaybackDieNow(int8_t val) { - static int8_t dieNow = 0; - if (val == 1) + if (val == 1 && dieNow == 0) { + uint32_t i = 0; dieNow = 1; + while (i < MAX_PLAYBACK_DIE_NOW_CALLBACKS) + { + if (playbackDieNowCallbacks[i] == NULL) + { + break; + } + playbackDieNowCallbacks[i](); + i += 1; + } } else if (val == 2) { @@ -86,6 +101,32 @@ int8_t PlaybackDieNow(int8_t val) return dieNow; } +bool PlaybackDieNowRegisterCallback(PlaybackDieNowCallback callback) +{ + bool ret = false; + if (callback) + { + uint32_t i = 0; + while (i < MAX_PLAYBACK_DIE_NOW_CALLBACKS) + { + if (playbackDieNowCallbacks[i] == callback) + { + ret = true; + break; + } + + if (playbackDieNowCallbacks[i] == NULL) + { + playbackDieNowCallbacks[i] = callback; + ret = true; + break; + } + i += 1; + } + } + return ret; +} + /* **************************** */ /* Supervisor Thread */ /* **************************** */ From ee22d8296de55fd9c813175b1164f98876bef95b Mon Sep 17 00:00:00 2001 From: samsamsam Date: Tue, 3 Apr 2018 00:00:54 +0200 Subject: [PATCH 04/19] Replace the AAC Main object type to the AAC LC in the ADTS header - workaround for no audio on some TS'streams Signed-off-by: max_10 Origin commit data ------------------ Branch: master Commit: https://github.com/neutrino-images/ni-libstb-hal/commit/2d6d6d7827695993d98a0a796b532453867935a3 Author: samsamsam Date: 2018-04-03 (Tue, 03 Apr 2018) ------------------ This commit was generated by Migit --- libeplayer3-arm/main/exteplayer.c | 2 +- libeplayer3-arm/output/writer/mipsel/aac.c | 13 ++++++++++++- libeplayer3-arm/output/writer/sh4/aac.c | 8 ++++++++ 3 files changed, 21 insertions(+), 2 deletions(-) diff --git a/libeplayer3-arm/main/exteplayer.c b/libeplayer3-arm/main/exteplayer.c index 6ad047b..ed82df1 100644 --- a/libeplayer3-arm/main/exteplayer.c +++ b/libeplayer3-arm/main/exteplayer.c @@ -638,7 +638,7 @@ int main(int argc, char *argv[]) memset(argvBuff, '\0', sizeof(argvBuff)); int commandRetVal = -1; /* inform client that we can handle additional commands */ - fprintf(stderr, "{\"EPLAYER3_EXTENDED\":{\"version\":%d}}\n", 42); + fprintf(stderr, "{\"EPLAYER3_EXTENDED\":{\"version\":%d}}\n", 43); if (0 != ParseParams(argc, argv, file, audioFile, &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"); diff --git a/libeplayer3-arm/output/writer/mipsel/aac.c b/libeplayer3-arm/output/writer/mipsel/aac.c index c1cec2d..c382f16 100644 --- a/libeplayer3-arm/output/writer/mipsel/aac.c +++ b/libeplayer3-arm/output/writer/mipsel/aac.c @@ -177,6 +177,14 @@ static int _writeData(WriterAVCallData_t *call, int type) aac_err("parsing Data with missing syncword. ignoring...\n"); return 0; } + + // STB can handle only AAC LC profile + if (0 == (call->data[2] & 0xC0)) + { + // change profile AAC Main -> AAC LC (Low Complexity) + aac_printf(1, "change profile AAC Main -> AAC LC (Low Complexity) in the ADTS header"); + call->data[2] = (call->data[2] & 0x1F) | 0x40; + } } else // check LOAS header { @@ -217,8 +225,11 @@ static int writeDataADTS(WriterAVCallData_t *call) return 0; } if ((call->private_data && 0 == strncmp("ADTS", (const char *)call->private_data, call->private_size)) || - HasADTSHeader(call->data, call->len)) + HasADTSHeader(call->data, call->len)) { + //(aacbuf[2] & 0x1F) | 0x40 + + //printf("%hhx %hhx %hhx %hhx %hhx %hhx %hhx %hhx\n", call->data[0], call->data[1], call->data[2], call->data[3], call->data[4], call->data[5], call->data[6], call->data[7]); return _writeData(call, 0); } uint32_t PacketLength = call->len + AAC_HEADER_LENGTH; diff --git a/libeplayer3-arm/output/writer/sh4/aac.c b/libeplayer3-arm/output/writer/sh4/aac.c index 6eeab11..e70336c 100644 --- a/libeplayer3-arm/output/writer/sh4/aac.c +++ b/libeplayer3-arm/output/writer/sh4/aac.c @@ -176,6 +176,14 @@ static int _writeData(void *_call, int type) aac_err("parsing Data with missing syncword. ignoring...\n"); return 0; } + + // STB can handle only AAC LC profile + if (0 == (call->data[2] & 0xC0)) + { + // change profile AAC Main -> AAC LC (Low Complexity) + aac_printf(1, "change profile AAC Main -> AAC LC (Low Complexity) in the ADTS header"); + call->data[2] = (call->data[2] & 0x1F) | 0x40; + } } else // check LOAS header { From db9ed727b09f0a895670fbd122b2451a800b7cbb Mon Sep 17 00:00:00 2001 From: samsamsam Date: Tue, 3 Apr 2018 09:37:33 +0200 Subject: [PATCH 05/19] Linux DVB output - workaround for BUG? in the DVB drivers Signed-off-by: max_10 Origin commit data ------------------ Branch: master Commit: https://github.com/neutrino-images/ni-libstb-hal/commit/ebf3abadda2ede823d1757a85e7b4529014db15b Author: samsamsam Date: 2018-04-03 (Tue, 03 Apr 2018) ------------------ This commit was generated by Migit --- libeplayer3-arm/main/exteplayer.c | 2 +- libeplayer3-arm/output/linuxdvb_buffering.c | 7 +++ libeplayer3-arm/output/linuxdvb_mipsel.c | 4 ++ libeplayer3-arm/output/writer/mipsel/aac.c | 2 - libeplayer3-arm/output/writer/mipsel/writer.c | 46 +++++++++++++++---- 5 files changed, 50 insertions(+), 11 deletions(-) diff --git a/libeplayer3-arm/main/exteplayer.c b/libeplayer3-arm/main/exteplayer.c index ed82df1..b333d9b 100644 --- a/libeplayer3-arm/main/exteplayer.c +++ b/libeplayer3-arm/main/exteplayer.c @@ -638,7 +638,7 @@ int main(int argc, char *argv[]) memset(argvBuff, '\0', sizeof(argvBuff)); int commandRetVal = -1; /* inform client that we can handle additional commands */ - fprintf(stderr, "{\"EPLAYER3_EXTENDED\":{\"version\":%d}}\n", 43); + fprintf(stderr, "{\"EPLAYER3_EXTENDED\":{\"version\":%d}}\n", 44); if (0 != ParseParams(argc, argv, file, audioFile, &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"); diff --git a/libeplayer3-arm/output/linuxdvb_buffering.c b/libeplayer3-arm/output/linuxdvb_buffering.c index fb7adff..f4c5db3 100644 --- a/libeplayer3-arm/output/linuxdvb_buffering.c +++ b/libeplayer3-arm/output/linuxdvb_buffering.c @@ -349,6 +349,13 @@ int32_t LinuxDvbBuffFlush(Context_t *context __attribute__((unused))) return 0; } +int32_t LinuxDvbBuffResume(Context_t *context __attribute__((unused))) +{ + /* signal if we are waiting for write to DVB decoders */ + WriteWakeUp(); + return 0; +} + ssize_t BufferingWriteV(int fd, const struct iovec *iov, size_t ic) { OutputType_t dataType = OUTPUT_UNK; diff --git a/libeplayer3-arm/output/linuxdvb_mipsel.c b/libeplayer3-arm/output/linuxdvb_mipsel.c index 4ef70df..d9f084d 100644 --- a/libeplayer3-arm/output/linuxdvb_mipsel.c +++ b/libeplayer3-arm/output/linuxdvb_mipsel.c @@ -104,6 +104,8 @@ pthread_mutex_t LinuxDVBmutex; int32_t LinuxDvbBuffOpen(Context_t *context, char *type, int outfd); int32_t LinuxDvbBuffClose(Context_t *context); int32_t LinuxDvbBuffFlush(Context_t *context); +int32_t LinuxDvbBuffResume(Context_t *context); + ssize_t BufferingWriteV(int fd, const struct iovec *iov, size_t ic); int32_t WriteSetBufferingSize(const uint32_t bufferSize); int LinuxDvbStop(Context_t *context, char *type); @@ -383,6 +385,8 @@ int LinuxDvbContinue(Context_t *context __attribute__((unused)), char *type) ret = cERR_LINUXDVB_ERROR; } } + if (isBufferedOutput) + LinuxDvbBuffResume(context); linuxdvb_printf(10, "exiting\n"); return ret; } diff --git a/libeplayer3-arm/output/writer/mipsel/aac.c b/libeplayer3-arm/output/writer/mipsel/aac.c index c382f16..90b48c7 100644 --- a/libeplayer3-arm/output/writer/mipsel/aac.c +++ b/libeplayer3-arm/output/writer/mipsel/aac.c @@ -227,8 +227,6 @@ static int writeDataADTS(WriterAVCallData_t *call) if ((call->private_data && 0 == strncmp("ADTS", (const char *)call->private_data, call->private_size)) || HasADTSHeader(call->data, call->len)) { - //(aacbuf[2] & 0x1F) | 0x40 - //printf("%hhx %hhx %hhx %hhx %hhx %hhx %hhx %hhx\n", call->data[0], call->data[1], call->data[2], call->data[3], call->data[4], call->data[5], call->data[6], call->data[7]); return _writeData(call, 0); } diff --git a/libeplayer3-arm/output/writer/mipsel/writer.c b/libeplayer3-arm/output/writer/mipsel/writer.c index 594ee47..829e4db 100644 --- a/libeplayer3-arm/output/writer/mipsel/writer.c +++ b/libeplayer3-arm/output/writer/mipsel/writer.c @@ -101,6 +101,12 @@ static Writer_t *AvailableWriter[] = /* Functions */ /* ***************************** */ +static void FlusPipe(int pipefd) +{ + char tmp; + while(1 == read(pipefd, &tmp, 1)); +} + ssize_t WriteWithRetry(Context_t *context, int pipefd, int fd, const void *buf, size_t size) { fd_set rfds; @@ -109,6 +115,7 @@ ssize_t WriteWithRetry(Context_t *context, int pipefd, int fd, const void *buf, ssize_t ret; int retval = -1; int maxFd = pipefd > fd ? pipefd : fd; + struct timeval tv; while(size > 0 && 0 == PlaybackDieNow(0) && !context->playback->isSeeking) { @@ -118,18 +125,34 @@ ssize_t WriteWithRetry(Context_t *context, int pipefd, int fd, const void *buf, FD_SET(pipefd, &rfds); FD_SET(fd, &wfds); - retval = select(maxFd + 1, &rfds, &wfds, NULL, NULL); + /* When we PAUSE LINUX DVB outputs buffers then audio/video buffers + * will be filled to full unfortunately, in such case after resume + * select never return with fd set - bug in DVB drivers? + * So, there will be to workarounds: + * 1. write to pipe pipe at resume to exit select immediately + * 2. even if fd is not set exit from select after 0,1s + * (it seems that second workaround is not needed) + */ + //tv.tv_sec = 0; + //tv.tv_usec = 100000; // 100ms + + retval = select(maxFd + 1, &rfds, &wfds, NULL, NULL); //&tv); if (retval < 0) { break; } + //if (retval == 0) + //{ + // //printf("RETURN FROM SELECT DUE TO TIMEOUT TIMEOUT\n"); + // continue; + //} + if(FD_ISSET(pipefd, &rfds)) { - char tmp; - /* flush pipefd pipe */ - while(1 == read(pipefd, &tmp, 1)); - break; + FlusPipe(pipefd); + //printf("RETURN FROM SELECT DUE TO pipefd SET\n"); + continue; } if(FD_ISSET(fd, &wfds)) @@ -150,12 +173,19 @@ ssize_t WriteWithRetry(Context_t *context, int pipefd, int fd, const void *buf, { break; } - } - if (ret < 0) - { return ret; } + else if (ret == 0) + { + //printf("This should not happen. Select return fd ready to write, but write return 0, errno [%d]\n", errno); + tv.tv_sec = 0; + tv.tv_usec = 10000; // 10ms + retval = select(pipefd + 1, &rfds, NULL, NULL, &tv); + if (retval) + FlusPipe(pipefd); + continue; + } size -= ret; buf += ret; From 88c2f414e63ae3d50523609fc74a666a36a75da7 Mon Sep 17 00:00:00 2001 From: samsamsam Date: Thu, 5 Apr 2018 21:50:52 +0200 Subject: [PATCH 06/19] Improve STOP command in the buffering mode Signed-off-by: max_10 Origin commit data ------------------ Branch: master Commit: https://github.com/neutrino-images/ni-libstb-hal/commit/b29e15ea230d8bdb1d084d246f77867925386073 Author: samsamsam Date: 2018-04-05 (Thu, 05 Apr 2018) ------------------ This commit was generated by Migit --- libeplayer3-arm/main/exteplayer.c | 2 +- libeplayer3-arm/output/linuxdvb_buffering.c | 2 ++ libeplayer3-arm/output/linuxdvb_mipsel.c | 4 ++-- 3 files changed, 5 insertions(+), 3 deletions(-) diff --git a/libeplayer3-arm/main/exteplayer.c b/libeplayer3-arm/main/exteplayer.c index b333d9b..54526c8 100644 --- a/libeplayer3-arm/main/exteplayer.c +++ b/libeplayer3-arm/main/exteplayer.c @@ -638,7 +638,7 @@ int main(int argc, char *argv[]) memset(argvBuff, '\0', sizeof(argvBuff)); int commandRetVal = -1; /* inform client that we can handle additional commands */ - fprintf(stderr, "{\"EPLAYER3_EXTENDED\":{\"version\":%d}}\n", 44); + fprintf(stderr, "{\"EPLAYER3_EXTENDED\":{\"version\":%d}}\n", 45); if (0 != ParseParams(argc, argv, file, audioFile, &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"); diff --git a/libeplayer3-arm/output/linuxdvb_buffering.c b/libeplayer3-arm/output/linuxdvb_buffering.c index f4c5db3..343296d 100644 --- a/libeplayer3-arm/output/linuxdvb_buffering.c +++ b/libeplayer3-arm/output/linuxdvb_buffering.c @@ -294,6 +294,8 @@ int32_t LinuxDvbBuffClose(Context_t *context __attribute__((unused))) WriteWakeUp(); pthread_mutex_lock(&bufferingMtx); + /* wake up if thread is waiting for data */ + pthread_cond_signal(&bufferingdDataAddedCond); /* wait for thread end */ clock_gettime(CLOCK_REALTIME, &max_wait); max_wait.tv_sec += 1; diff --git a/libeplayer3-arm/output/linuxdvb_mipsel.c b/libeplayer3-arm/output/linuxdvb_mipsel.c index d9f084d..4335399 100644 --- a/libeplayer3-arm/output/linuxdvb_mipsel.c +++ b/libeplayer3-arm/output/linuxdvb_mipsel.c @@ -198,6 +198,8 @@ int LinuxDvbClose(Context_t *context, char *type) */ LinuxDvbStop(context, type); getLinuxDVBMutex(FILENAME, __FUNCTION__, __LINE__); + if (isBufferedOutput) + LinuxDvbBuffClose(context); if (video && videofd != -1) { close(videofd); @@ -208,8 +210,6 @@ int LinuxDvbClose(Context_t *context, char *type) close(audiofd); audiofd = -1; } - if (isBufferedOutput) - LinuxDvbBuffClose(context); releaseLinuxDVBMutex(FILENAME, __FUNCTION__, __LINE__); return cERR_LINUXDVB_NO_ERROR; } From df202fb86b2edc4b4c8f79fdc508342810b0cb2b Mon Sep 17 00:00:00 2001 From: max_10 Date: Tue, 10 Apr 2018 11:31:57 +0200 Subject: [PATCH 07/19] libeplayer3-arm: insert original blank lines from exteplayer3.git, for better merge Origin commit data ------------------ Branch: master Commit: https://github.com/neutrino-images/ni-libstb-hal/commit/b8d7e5ead479b24b10b8561ccdc137bb4ef8af61 Author: max_10 Date: 2018-04-10 (Tue, 10 Apr 2018) ------------------ No further description and justification available within origin commit message! ------------------ This commit was generated by Migit --- libeplayer3-arm/Makefile.am | 2 +- libeplayer3-arm/container/buff_ffmpeg.c | 75 ++++- libeplayer3-arm/container/container.c | 12 + libeplayer3-arm/container/container_ffmpeg.c | 311 +++++++++++++++++- libeplayer3-arm/container/flv2mpeg4_ffmpeg.c | 13 + libeplayer3-arm/container/mpeg4p2_ffmpeg.c | 5 + libeplayer3-arm/container/wrapped_ffmpeg.c | 5 + libeplayer3-arm/external/ffmpeg/get_bits.h | 13 + libeplayer3-arm/external/ffmpeg/latmenc.h | 1 + libeplayer3-arm/external/ffmpeg/put_bits.h | 7 + .../external/ffmpeg/src/bitstream.c | 6 + libeplayer3-arm/external/ffmpeg/src/latmenc.c | 25 ++ .../external/ffmpeg/src/mpeg4audio.c | 16 + .../external/flv2mpeg4/src/bitreader.h | 9 + .../external/flv2mpeg4/src/bitwriter.h | 7 + .../external/flv2mpeg4/src/dcprediction.c | 12 + .../external/flv2mpeg4/src/dcprediction.h | 1 + libeplayer3-arm/external/flv2mpeg4/src/flv.h | 2 + .../external/flv2mpeg4/src/flv2mpeg4.c | 40 +++ .../external/flv2mpeg4/src/flvdecoder.c | 48 +++ libeplayer3-arm/external/flv2mpeg4/src/m4v.h | 2 + .../external/flv2mpeg4/src/m4vencode.c | 76 +++++ libeplayer3-arm/include/aac.h | 1 + libeplayer3-arm/include/bcm_ioctls.h | 7 + libeplayer3-arm/include/debug.h | 2 + libeplayer3-arm/include/manager.h | 2 + libeplayer3-arm/include/misc.h | 6 + libeplayer3-arm/include/output.h | 1 + libeplayer3-arm/include/pes.h | 2 + libeplayer3-arm/include/stm_ioctls.h | 4 + libeplayer3-arm/include/writer.h | 4 +- libeplayer3-arm/main/exteplayer.c | 84 ++++- libeplayer3-arm/manager/audio.c | 37 ++- libeplayer3-arm/manager/chapter.c | 3 +- libeplayer3-arm/manager/manager.c | 5 + libeplayer3-arm/manager/subtitle.c | 4 +- libeplayer3-arm/manager/video.c | 23 +- libeplayer3-arm/output/linuxdvb_buffering.c | 122 ++++--- libeplayer3-arm/output/linuxdvb_mipsel.c | 165 +++++++++- libeplayer3-arm/output/linuxdvb_sh4.c | 182 +++++++++- libeplayer3-arm/output/output.c | 11 +- libeplayer3-arm/output/output_subtitle.c | 31 +- libeplayer3-arm/output/writer/common/misc.c | 5 + libeplayer3-arm/output/writer/common/pes.c | 15 + libeplayer3-arm/output/writer/mipsel/aac.c | 31 +- libeplayer3-arm/output/writer/mipsel/ac3.c | 11 + libeplayer3-arm/output/writer/mipsel/amr.c | 11 + libeplayer3-arm/output/writer/mipsel/divx3.c | 16 +- libeplayer3-arm/output/writer/mipsel/dts.c | 10 + libeplayer3-arm/output/writer/mipsel/h263.c | 9 + libeplayer3-arm/output/writer/mipsel/h264.c | 51 +++ libeplayer3-arm/output/writer/mipsel/h265.c | 32 ++ libeplayer3-arm/output/writer/mipsel/lpcm.c | 21 +- libeplayer3-arm/output/writer/mipsel/mp3.c | 9 + libeplayer3-arm/output/writer/mipsel/mpeg2.c | 13 + libeplayer3-arm/output/writer/mipsel/mpeg4.c | 11 + libeplayer3-arm/output/writer/mipsel/pcm.c | 28 +- libeplayer3-arm/output/writer/mipsel/vc1.c | 15 + libeplayer3-arm/output/writer/mipsel/vp.c | 9 +- libeplayer3-arm/output/writer/mipsel/wma.c | 15 +- libeplayer3-arm/output/writer/mipsel/wmv.c | 15 + libeplayer3-arm/output/writer/mipsel/writer.c | 32 +- libeplayer3-arm/output/writer/sh4/aac.c | 32 ++ libeplayer3-arm/output/writer/sh4/ac3.c | 9 + libeplayer3-arm/output/writer/sh4/divx.c | 15 + libeplayer3-arm/output/writer/sh4/divx2.c | 19 ++ libeplayer3-arm/output/writer/sh4/dts.c | 11 + libeplayer3-arm/output/writer/sh4/h263.c | 13 + libeplayer3-arm/output/writer/sh4/h264.c | 69 ++++ libeplayer3-arm/output/writer/sh4/mp3.c | 9 + libeplayer3-arm/output/writer/sh4/mpeg2.c | 14 + libeplayer3-arm/output/writer/sh4/pcm.c | 26 ++ libeplayer3-arm/output/writer/sh4/pes.c | 14 + libeplayer3-arm/output/writer/sh4/vc1.c | 30 ++ libeplayer3-arm/output/writer/sh4/vorbis.c | 14 +- libeplayer3-arm/output/writer/sh4/wma.c | 15 +- libeplayer3-arm/output/writer/sh4/wmv.c | 31 ++ libeplayer3-arm/output/writer/sh4/writer.c | 9 + libeplayer3-arm/playback/playback.c | 114 ++++++- 79 files changed, 2070 insertions(+), 117 deletions(-) diff --git a/libeplayer3-arm/Makefile.am b/libeplayer3-arm/Makefile.am index 1f7f51e..b77dbf9 100644 --- a/libeplayer3-arm/Makefile.am +++ b/libeplayer3-arm/Makefile.am @@ -19,9 +19,9 @@ libeplayer3_arm_la_SOURCES = \ manager/subtitle.c \ manager/chapter.c \ output/linuxdvb_mipsel.c \ + output/linuxdvb_buffering.c \ output/output_subtitle.c \ output/output.c \ - output/linuxdvb_buffering.c \ output/writer/common/pes.c \ output/writer/common/misc.c \ output/writer/mipsel/writer.c \ diff --git a/libeplayer3-arm/container/buff_ffmpeg.c b/libeplayer3-arm/container/buff_ffmpeg.c index 61ac32d..3386b7f 100644 --- a/libeplayer3-arm/container/buff_ffmpeg.c +++ b/libeplayer3-arm/container/buff_ffmpeg.c @@ -95,15 +95,19 @@ static void update_finish_timeout() int64_t currPts = -1; int32_t ret = g_context->playback->Command(g_context, PLAYBACK_PTS, &currPts); finishTimeout += 1; + if (maxInjectedPts < 0 || maxInjectedPts == INVALID_PTS_VALUE) { maxInjectedPts = 0; } + //printf("ret[%d] playPts[%lld] currPts[%lld] maxInjectedPts[%lld]\n", ret, playPts, currPts, maxInjectedPts); + /* On some STBs PTS readed from decoder is invalid after seek or at start * this is the reason for additional validation when we what to close immediately */ - if (!progressive_playback && 0 == ret && currPts >= maxInjectedPts && ((currPts - maxInjectedPts) / 90000) < 2) + if (!progressive_playback && 0 == ret && currPts >= maxInjectedPts && + ((currPts - maxInjectedPts) / 90000) < 2) { /* close immediately */ @@ -129,6 +133,7 @@ static int32_t ffmpeg_read_wrapper_base(void *opaque, uint8_t *buf, int32_t buf_ { break; } + int32_t partLen = ffmpeg_real_read_org(opaque, buf + len, buf_size - len); if (partLen > 0) { @@ -141,7 +146,9 @@ static int32_t ffmpeg_read_wrapper_base(void *opaque, uint8_t *buf, int32_t buf_ len = 0; break; } + update_finish_timeout(); + usleep(100000); continue; } @@ -163,25 +170,31 @@ static int32_t ffmpeg_read_wrapper(void *opaque, uint8_t *buf, int32_t buf_size) return ffmpeg_real_read_org(opaque, buf, buf_size); } } + #if 0 static int32_t ffmpeg_read_wrapper2(void *opaque, uint8_t *buf, int32_t buf_size) { return ffmpeg_read_wrapper_base(opaque, buf, buf_size, 1); } #endif + //for buffered io void getfillerMutex(const char *filename __attribute__((unused)), const char *function __attribute__((unused)), int line __attribute__((unused))) { 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 __attribute__((unused)), const const char *function __attribute__((unused)), int line __attribute__((unused))) { pthread_mutex_unlock(&fillermutex); + ffmpeg_printf(100, "::%d released mutex\n", line); } + //for buffered io (end)encoding #if 0 static int32_t container_set_ffmpeg_buf_seek_time(int32_t *time) @@ -190,6 +203,7 @@ static int32_t container_set_ffmpeg_buf_seek_time(int32_t *time) return cERR_CONTAINER_FFMPEG_NO_ERROR; } #endif + static int32_t container_set_ffmpeg_buf_size(int32_t *size) { if (ffmpeg_buf == NULL) @@ -203,6 +217,7 @@ static int32_t container_set_ffmpeg_buf_size(int32_t *size) ffmpeg_buf_size = (*size) + FILLBUFDIFF; } } + ffmpeg_printf(10, "size=%d, buffer size=%d\n", (*size), ffmpeg_buf_size); return cERR_CONTAINER_FFMPEG_NO_ERROR; } @@ -216,6 +231,7 @@ static int32_t container_get_ffmpeg_buf_size(int32_t *size) static int32_t container_get_fillbufstatus(int32_t *size) { int32_t rwdiff = 0; + if (ffmpeg_buf != NULL && ffmpeg_buf_read != NULL && ffmpeg_buf_write != NULL) { if (ffmpeg_buf_read < ffmpeg_buf_write) @@ -225,10 +241,13 @@ static int32_t container_get_fillbufstatus(int32_t *size) rwdiff = (ffmpeg_buf + ffmpeg_buf_size) - ffmpeg_buf_read; rwdiff += ffmpeg_buf_write - ffmpeg_buf; } + *size = rwdiff; } + return cERR_CONTAINER_FFMPEG_NO_ERROR; } + #if 0 static int32_t container_stop_buffer() { @@ -236,6 +255,7 @@ static int32_t container_stop_buffer() return 0; } #endif + //flag 0: start direct //flag 1: from thread static void ffmpeg_filler(Context_t *context, int32_t id, int32_t *inpause, int32_t flag) @@ -243,11 +263,13 @@ static void ffmpeg_filler(Context_t *context, int32_t id, int32_t *inpause, int3 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)) { @@ -255,11 +277,13 @@ static void ffmpeg_filler(Context_t *context, int32_t id, int32_t *inpause, int3 { 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) @@ -270,42 +294,53 @@ static void ffmpeg_filler(Context_t *context, int32_t id, int32_t *inpause, int3 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) { @@ -333,11 +368,13 @@ static void ffmpeg_filler(Context_t *context, int32_t id, int32_t *inpause, int3 { 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; @@ -355,13 +392,17 @@ static void ffmpeg_fillerTHREAD(Context_t *context) { int32_t inpause = 0; int32_t id = hasfillerThreadStartedID; + ffmpeg_printf(10, "Running ID=%d!\n", id); + while (hasfillerThreadStarted[id] == 1) { ffmpeg_filler(context, id, &inpause, 1); usleep(10000); } + hasfillerThreadStarted[id] = 0; + ffmpeg_printf(10, "terminating ID=%d\n", id); } @@ -370,7 +411,9 @@ static int32_t ffmpeg_start_fillerTHREAD(Context_t *context) int32_t error; int32_t ret = 0, i = 0; pthread_attr_t attr; + ffmpeg_printf(10, "\n"); + if (context && context->playback && context->playback->isPlaying) { ffmpeg_printf(10, "is Playing\n"); @@ -379,6 +422,7 @@ static int32_t ffmpeg_start_fillerTHREAD(Context_t *context) { ffmpeg_printf(10, "is NOT Playing\n"); } + //get filler thread ID //if the thread hangs for long time, we use a new id for (i = 0; i < 10; i++) @@ -389,15 +433,18 @@ static int32_t ffmpeg_start_fillerTHREAD(Context_t *context) break; } } + if (hasfillerThreadStarted[hasfillerThreadStartedID] == 0) { pthread_attr_init(&attr); pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED); + hasfillerThreadStarted[hasfillerThreadStartedID] = 1; if ((error = pthread_create(&fillerThread, &attr, (void *)&ffmpeg_fillerTHREAD, context)) != 0) { hasfillerThreadStarted[hasfillerThreadStartedID] = 0; ffmpeg_printf(10, "Error creating filler thread, error:%d:%s\n", error, strerror(error)); + ret = cERR_CONTAINER_FFMPEG_ERR; } else @@ -408,8 +455,10 @@ static int32_t ffmpeg_start_fillerTHREAD(Context_t *context) else { ffmpeg_printf(10, "All filler thread ID's in use!\n"); + ret = cERR_CONTAINER_FFMPEG_ERR; } + ffmpeg_printf(10, "exiting with value %d\n", ret); return ret; } @@ -418,9 +467,11 @@ static int32_t ffmpeg_read_real(void *opaque __attribute__((unused)), uint8_t *b { int32_t len = buf_size; int32_t rwdiff = 0; + if (buf_size > 0) { getfillerMutex(__FILE__, __FUNCTION__, __LINE__); + if (ffmpeg_buf_read < ffmpeg_buf_write) rwdiff = ffmpeg_buf_write - ffmpeg_buf_read; if (ffmpeg_buf_read > ffmpeg_buf_write) @@ -429,18 +480,22 @@ static int32_t ffmpeg_read_real(void *opaque __attribute__((unused)), uint8_t *b 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) @@ -452,6 +507,7 @@ static int32_t ffmpeg_read_real(void *opaque __attribute__((unused)), uint8_t *b ffmpeg_buf_valid_size += len; } } + if (ffmpeg_buf_read == ffmpeg_buf + ffmpeg_buf_size) { ffmpeg_buf_read = ffmpeg_buf; @@ -463,6 +519,7 @@ static int32_t ffmpeg_read_real(void *opaque __attribute__((unused)), uint8_t *b } releasefillerMutex(__FILE__, __FUNCTION__, __LINE__); } + return len; } @@ -471,6 +528,7 @@ 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); @@ -481,6 +539,7 @@ static int32_t ffmpeg_read(void *opaque, uint8_t *buf, int32_t buf_size) usleep(10000); } } + if (count == 0) { if (sumlen == 0) @@ -492,6 +551,7 @@ static int32_t ffmpeg_read(void *opaque, uint8_t *buf, int32_t buf_size) ffmpeg_err("Timeout, not all buffered data availabel (buf_size=%d sumlen=%d)!\n", buf_size, sumlen); } } + return sumlen; } @@ -500,10 +560,12 @@ static int64_t ffmpeg_seek(void *opaque __attribute__((unused)), int64_t offset, int64_t diff; int32_t rwdiff = 0; whence &= ~AVSEEK_FORCE; + if (whence != SEEK_CUR && whence != SEEK_SET) { return AVERROR(EINVAL); } + if (whence == SEEK_CUR) { diff = offset; @@ -512,20 +574,25 @@ static int64_t ffmpeg_seek(void *opaque __attribute__((unused)), int64_t offset, { diff = offset - avContextTab[0]->pb->pos; } + if (diff == 0) { return avContextTab[0]->pb->pos; } + getfillerMutex(__FILE__, __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 */ @@ -557,29 +624,35 @@ static int64_t ffmpeg_seek(void *opaque __attribute__((unused)), int64_t offset, { releasefillerMutex(__FILE__, __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 int32_t count = ffmpeg_buf_seek_time * 10; int32_t size = 0; + container_get_fillbufstatus(&size); while (size < ffmpeg_buf_size - FILLBUFDIFF && (--count) > 0) { usleep(100000); container_get_fillbufstatus(&size); } + return avContextTab[0]->pb->pos + diff; } + releasefillerMutex(__FILE__, __FUNCTION__, __LINE__); return avContextTab[0]->pb->pos + diff; } diff --git a/libeplayer3-arm/container/container.c b/libeplayer3-arm/container/container.c index 3f56f21..48ea13a 100644 --- a/libeplayer3-arm/container/container.c +++ b/libeplayer3-arm/container/container.c @@ -56,8 +56,10 @@ static void printContainerCapabilities() { int32_t i = 0; int32_t j = 0; + container_printf(10, "%s::%s\n", __FILE__, __FUNCTION__); container_printf(10, "Capabilities: "); + for (i = 0; AvailableContainer[i] != NULL; i++) { for (j = 0; AvailableContainer[i]->Capabilities[j] != NULL; j++) @@ -73,7 +75,9 @@ static int32_t selectContainer(Context_t *context, char *extension) int32_t i = 0; int32_t j = 0; int32_t ret = -1; + container_printf(10, "%s::%s\n", __FILE__, __FUNCTION__); + for (i = 0; AvailableContainer[i] != NULL; i++) { for (j = 0; AvailableContainer[i]->Capabilities[j] != NULL; j++) @@ -81,26 +85,32 @@ static int32_t selectContainer(Context_t *context, char *extension) if (!strcasecmp(AvailableContainer[i]->Capabilities[j], extension)) { context->container->selectedContainer = AvailableContainer[i]; + container_printf(10, "Selected Container: %s\n", context->container->selectedContainer->Name); ret = 0; break; } } + if (ret == 0) { break; } } + if (ret != 0) { container_err("No Container found :-(\n"); } + return ret; } + static int Command(Context_t *context, ContainerCmd_t command, void *argument __attribute__((unused))) { int ret = 0; + container_printf(10, "%s::%s\n", __FILE__, __FUNCTION__); switch (command) @@ -124,9 +134,11 @@ static int Command(Context_t *context, ContainerCmd_t command, void *argument __ container_err("%s::%s ContainerCmd %d not supported!\n", __FILE__, __FUNCTION__, command); break; } + return ret; } + ContainerHandler_t ContainerHandler = { "Output", diff --git a/libeplayer3-arm/container/container_ffmpeg.c b/libeplayer3-arm/container/container_ffmpeg.c index 874e78f..f0f17c6 100644 --- a/libeplayer3-arm/container/container_ffmpeg.c +++ b/libeplayer3-arm/container/container_ffmpeg.c @@ -166,17 +166,21 @@ static void initMutex(void) 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); } @@ -194,6 +198,7 @@ static int32_t Write(Write_FN WriteFun, Context_t *context, void *privateData, i return ret; } + #include "buff_ffmpeg.c" #include "wrapped_ffmpeg.c" #if LIBAVCODEC_VERSION_INT >= AV_VERSION_INT(56, 34, 100) @@ -430,10 +435,12 @@ static char *Codec2Encoding(int32_t codec_id, int32_t media_type, uint8_t *extra return pcm_resampling ? "A_IPCM" : "A_PCM"; case AV_CODEC_ID_AMR_NB: return "A_IPCM";//return "A_AMR"; + /* In exteplayer3 embedded text subtitle simple printed * to output like other data. Maybe worth to consider is to use * linux socket or pipe to put */ + /* subtitle */ case AV_CODEC_ID_SSA: #if LIBAVCODEC_VERSION_INT >= AV_VERSION_INT(55, 3, 100) @@ -477,10 +484,12 @@ static int64_t calcPts(uint32_t avContextIdx, AVStream *stream, int64_t pts) { pts = av_rescale(pts, (int64_t)stream->time_base.num * 90000, stream->time_base.den); } + if (avContextTab[avContextIdx]->start_time != AV_NOPTS_VALUE) { pts -= 90000 * avContextTab[avContextIdx]->start_time / AV_TIME_BASE; } + if (pts & 0x8000000000000000ull) { pts = INVALID_PTS_VALUE; @@ -489,6 +498,7 @@ static int64_t calcPts(uint32_t avContextIdx, AVStream *stream, int64_t pts) { pts &= 0x01FFFFFFFF; // PES header can handle only 33 bit PTS } + return pts; } @@ -504,6 +514,7 @@ static char *searchMeta(void *metadata, char *ourTag) AVDictionaryEntry *tag = NULL; #endif int i = 0; + while (metadata_map[i] != NULL) { if (strcmp(ourTag, metadata_map[i]) == 0) @@ -522,6 +533,7 @@ static char *searchMeta(void *metadata, char *ourTag) } i++; } + return NULL; } @@ -540,22 +552,27 @@ static void FFMPEGThread(Context_t *context) //int64_t lastPts = -1; int64_t currentVideoPts = -1; int64_t currentAudioPts = -1; + /* lastVideoDts and lastAudioDts * used in isTSLiveMode */ int64_t lastVideoDts = -1; int64_t lastAudioDts = -1; + int64_t showtime = 0; int64_t bofcount = 0; //int32_t err = 0; AudioVideoOut_t avOut; + g_context = context; + SwrContext *swr = NULL; AVFrame *decoded_frame = NULL; int32_t out_sample_rate = 44100; int32_t out_channels = 2; uint64_t out_channel_layout = AV_CH_LAYOUT_STEREO; uint32_t cAVIdx = 0; + #if LIBAVCODEC_VERSION_INT >= AV_VERSION_INT(56, 34, 100) Mpeg4P2Context mpeg4p2_context; memset(&mpeg4p2_context, 0, sizeof(Mpeg4P2Context)); @@ -572,16 +589,17 @@ static void FFMPEGThread(Context_t *context) usleep(1000); } ffmpeg_printf(10, "Running!\n"); + int8_t isWaitingForFinish = 0; while (context && context->playback && context->playback->isPlaying) { - /* When user press PAUSE we call pause on AUDIO and VIDEO decoders, - * we will not wait here because we can still fill - * DVB drivers buffers at PAUSE time - * - * In the future we can add buffering queue before injection in to - * AUDIO, VIDEO decoders, so we can not wait here - */ + /* When user press PAUSE we call pause on AUDIO and VIDEO decoders, + * we will not wait here because we can still fill + * DVB drivers buffers at PAUSE time + * + * In the future we can add buffering queue before injection in to + * AUDIO, VIDEO decoders, so we can not wait here + */ #ifdef __sh__ //IF MOVIE IS PAUSED, WAIT if (context->playback->isPaused) @@ -592,6 +610,7 @@ static void FFMPEGThread(Context_t *context) continue; } #endif + if (context->playback->isSeeking) { ffmpeg_printf(10, "seeking\n"); @@ -599,7 +618,9 @@ static void FFMPEGThread(Context_t *context) usleep(10000); continue; } + getMutex(__FILE__, __FUNCTION__, __LINE__); + if (!context->playback || !context->playback->isPlaying) { releaseMutex(__FILE__, __FUNCTION__, __LINE__); @@ -648,6 +669,7 @@ static void FFMPEGThread(Context_t *context) { bofcount = 0; } + if (do_seek_target_seconds || do_seek_target_bytes) { int res = -1; @@ -685,11 +707,13 @@ static void FFMPEGThread(Context_t *context) } do_seek_target_seconds = 0; do_seek_target_bytes = 0; + restart_audio_resampling = 1; currentVideoPts = -1; currentAudioPts = -1; latestPts = 0; seek_target_flag = 0; + // flush streams uint32_t i = 0; for (i = 0; i < IPTV_AV_CONTEXT_MAX_NUM; i += 1) @@ -718,6 +742,7 @@ static void FFMPEGThread(Context_t *context) flv2mpeg4_context_reset(&flv2mpeg4_context); #endif } + int ffmpegStatus = 0; if (!isWaitingForFinish) { @@ -736,6 +761,7 @@ static void FFMPEGThread(Context_t *context) cAVIdx = 0; } } + if (!isWaitingForFinish && (ffmpegStatus = av_read_frame(avContextTab[cAVIdx], &packet)) == 0) { int64_t pts = 0; @@ -743,7 +769,9 @@ static void FFMPEGThread(Context_t *context) Track_t *videoTrack = NULL; Track_t *audioTrack = NULL; Track_t *subtitleTrack = NULL; + int32_t pid = avContextTab[cAVIdx]->streams[packet.stream_index]->id; + reset_finish_timeout(); if (avContextTab[cAVIdx]->streams[packet.stream_index]->discard != AVDISCARD_ALL) { @@ -751,10 +779,12 @@ static void FFMPEGThread(Context_t *context) { 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"); @@ -764,7 +794,9 @@ static void FFMPEGThread(Context_t *context) { ffmpeg_printf(1, "SKIP DISCARDED PACKET stream_index[%d] pid[%d]\n", packet.size, (int)packet.stream_index, pid); } + ffmpeg_printf(200, "packet.size %d - index %d\n", packet.size, pid); + if (videoTrack && (videoTrack->AVIdx == (int)cAVIdx) && (videoTrack->Id == pid)) { #if LIBAVCODEC_VERSION_INT >= AV_VERSION_INT(56, 34, 100) @@ -799,11 +831,13 @@ static void FFMPEGThread(Context_t *context) uint8_t skipPacket = 0; currentVideoPts = videoTrack->pts = pts = calcPts(cAVIdx, videoTrack->stream, packet.pts); videoTrack->dts = dts = calcPts(cAVIdx, videoTrack->stream, packet.dts); + if ((currentVideoPts != INVALID_PTS_VALUE) && (currentVideoPts > latestPts)) { latestPts = currentVideoPts; update_max_injected_pts(latestPts); } + if (context->playback->isTSLiveMode) { if (dts != INVALID_PTS_VALUE) @@ -826,13 +860,16 @@ static void FFMPEGThread(Context_t *context) skipPacket = 1; } } + if (skipPacket) { wrapped_packet_unref(&packet); releaseMutex(__FILE__, __FUNCTION__, __LINE__); continue; } + ffmpeg_printf(200, "VideoTrack index = %d %lld\n", pid, currentVideoPts); + avOut.data = packet.data; avOut.len = packet.size; avOut.pts = pts; @@ -844,10 +881,12 @@ static void FFMPEGThread(Context_t *context) avOut.width = videoTrack->width; avOut.height = videoTrack->height; avOut.type = "video"; + if (avContextTab[cAVIdx]->iformat->flags & AVFMT_TS_DISCONT) { avOut.infoFlags = 1; // TS container } + if (Write(context->output->video->Write, context, &avOut, pts) < 0) { ffmpeg_err("writing data to video device failed\n"); @@ -859,11 +898,13 @@ static void FFMPEGThread(Context_t *context) uint8_t skipPacket = 0; currentAudioPts = audioTrack->pts = pts = calcPts(cAVIdx, audioTrack->stream, packet.pts); dts = calcPts(cAVIdx, audioTrack->stream, packet.dts); + if ((currentAudioPts != INVALID_PTS_VALUE) && (currentAudioPts > latestPts) && (!videoTrack)) { latestPts = currentAudioPts; update_max_injected_pts(latestPts); } + if (context->playback->isTSLiveMode) { if (dts != INVALID_PTS_VALUE) @@ -886,12 +927,14 @@ static void FFMPEGThread(Context_t *context) skipPacket = 1; } } + if (skipPacket) { wrapped_packet_unref(&packet); releaseMutex(__FILE__, __FUNCTION__, __LINE__); continue; } + pcmPrivateData_t pcmExtradata; pcmExtradata.channels = get_codecpar(audioTrack->stream)->channels; pcmExtradata.bits_per_coded_sample = get_codecpar(audioTrack->stream)->bits_per_coded_sample; @@ -899,13 +942,16 @@ static void FFMPEGThread(Context_t *context) pcmExtradata.bit_rate = get_codecpar(audioTrack->stream)->bit_rate; pcmExtradata.ffmpeg_codec_id = get_codecpar(audioTrack->stream)->codec_id; pcmExtradata.bResampling = restart_audio_resampling; + uint8_t *pAudioExtradata = get_codecpar(audioTrack->stream)->extradata; uint32_t audioExtradataSize = get_codecpar(audioTrack->stream)->extradata_size; + ffmpeg_printf(200, "AudioTrack index = %d\n", pid); if (audioTrack->inject_raw_pcm == 1) { ffmpeg_printf(200, "write audio raw pcm\n"); restart_audio_resampling = 0; + avOut.data = packet.data; avOut.len = packet.size; avOut.pts = pts; @@ -916,6 +962,7 @@ static void FFMPEGThread(Context_t *context) avOut.width = 0; avOut.height = 0; avOut.type = "audio"; + if (Write(context->output->audio->Write, context, &avOut, pts) < 0) { ffmpeg_err("(raw pcm) writing data to audio device failed\n"); @@ -924,6 +971,7 @@ static void FFMPEGThread(Context_t *context) else if (audioTrack->inject_as_pcm == 1 && audioTrack->avCodecCtx) { AVCodecContext *c = audioTrack->avCodecCtx; + if (restart_audio_resampling) { restart_audio_resampling = 0; @@ -948,6 +996,7 @@ static void FFMPEGThread(Context_t *context) { break; } + if (!decoded_frame) { decoded_frame = wrapped_frame_alloc(); @@ -968,10 +1017,12 @@ static void FFMPEGThread(Context_t *context) restart_audio_resampling = 1; break; } + if (ret >= 0) { packet.size = 0; } + ret = avcodec_receive_frame(c, decoded_frame); if (ret < 0) { @@ -993,8 +1044,10 @@ static void FFMPEGThread(Context_t *context) ffmpeg_err("avcodec_decode_audio4: %d\n", len); break; } + packet.data += len; packet.size -= len; + if (!got_frame) { continue; @@ -1018,13 +1071,16 @@ static void FFMPEGThread(Context_t *context) } out_sample_rate = *rate ? *rate : 44100; } + swr = swr_alloc(); out_channels = c->channels; + if (c->channel_layout == 0) { c->channel_layout = av_get_default_channel_layout(c->channels); } out_channel_layout = c->channel_layout; + uint8_t downmix = stereo_software_decoder && out_channels > 2 ? 1 : 0; #ifdef __sh__ // player2 won't play mono @@ -1038,12 +1094,15 @@ static void FFMPEGThread(Context_t *context) out_channel_layout = AV_CH_LAYOUT_STEREO_DOWNMIX; out_channels = 2; } + av_opt_set_int(swr, "in_channel_layout", c->channel_layout, 0); av_opt_set_int(swr, "out_channel_layout", out_channel_layout, 0); av_opt_set_int(swr, "in_sample_rate", c->sample_rate, 0); av_opt_set_int(swr, "out_sample_rate", out_sample_rate, 0); av_opt_set_int(swr, "in_sample_fmt", c->sample_fmt, 0); av_opt_set_int(swr, "out_sample_fmt", AV_SAMPLE_FMT_S16, 0); + + e = swr_init(swr); if (e < 0) { @@ -1053,6 +1112,7 @@ static void FFMPEGThread(Context_t *context) swr = NULL; } } + uint8_t *output[8] = {NULL}; int32_t in_samples = decoded_frame->nb_samples; int32_t out_samples = av_rescale_rnd(swr_get_delay(swr, c->sample_rate) + in_samples, out_sample_rate, c->sample_rate, AV_ROUND_UP); @@ -1068,8 +1128,10 @@ static void FFMPEGThread(Context_t *context) int64_t next_out_pts = av_rescale(swr_next_pts(swr, next_in_pts), ((AVStream *) audioTrack->stream)->time_base.den, ((AVStream *) audioTrack->stream)->time_base.num * (int64_t)out_sample_rate * c->sample_rate); + currentAudioPts = audioTrack->pts = pts = calcPts(cAVIdx, audioTrack->stream, next_out_pts); out_samples = swr_convert(swr, &output[0], out_samples, (const uint8_t **) &decoded_frame->data[0], in_samples); + ////////////////////////////////////////////////////////////////////// // Update pcmExtradata according to decode parameters pcmExtradata.channels = av_get_channel_layout_nb_channels(out_channel_layout); @@ -1081,9 +1143,12 @@ static void FFMPEGThread(Context_t *context) #else pcmExtradata.ffmpeg_codec_id = AV_CODEC_ID_PCM_S16LE; #endif + ////////////////////////////////////////////////////////////////////// + avOut.data = output[0]; avOut.len = out_samples * sizeof(int16_t) * out_channels; + avOut.pts = pts; avOut.extradata = (unsigned char *) &pcmExtradata; avOut.extralen = sizeof(pcmExtradata); @@ -1092,6 +1157,7 @@ static void FFMPEGThread(Context_t *context) avOut.width = 0; avOut.height = 0; avOut.type = "audio"; + if (!context->playback->BackWard && Write(context->output->audio->Write, context, &avOut, pts) < 0) { ffmpeg_err("writing data to audio device failed\n"); @@ -1103,6 +1169,7 @@ static void FFMPEGThread(Context_t *context) { ffmpeg_printf(200, "write audio aac\n"); ffmpeg_printf(200, ">>>>>>> %x %x %x %x %x %x %x\n", packet.data[0], packet.data[1], packet.data[2], packet.data[3], packet.data[4], packet.data[5], packet.data[6]); + avOut.data = packet.data; avOut.len = packet.size; avOut.pts = pts; @@ -1113,6 +1180,7 @@ static void FFMPEGThread(Context_t *context) avOut.width = 0; avOut.height = 0; avOut.type = "audio"; + if (!context->playback->BackWard && Write(context->output->audio->Write, context, &avOut, pts) < 0) { ffmpeg_err("(aac) writing data to audio device failed\n"); @@ -1130,6 +1198,7 @@ static void FFMPEGThread(Context_t *context) avOut.width = 0; avOut.height = 0; avOut.type = "audio"; + if (!context->playback->BackWard && Write(context->output->audio->Write, context, &avOut, pts) < 0) { ffmpeg_err("writing data to audio device failed\n"); @@ -1141,6 +1210,7 @@ static void FFMPEGThread(Context_t *context) int64_t duration = -1; pts = calcPts(cAVIdx, subtitleTrack->stream, packet.pts); AVStream *stream = subtitleTrack->stream; + if (packet.duration != 0) { // duration in milliseconds @@ -1151,6 +1221,7 @@ static void FFMPEGThread(Context_t *context) // duration in milliseconds duration = (int64_t)av_rescale(get_packet_duration(&packet), (int64_t)stream->time_base.num * 1000, stream->time_base.den); } + if (duration > 0) { SubtitleOut_t subOut; @@ -1171,11 +1242,13 @@ static void FFMPEGThread(Context_t *context) if (0 != ffmpegStatus) { static char errbuf[256]; + if (0 == av_strerror(ffmpegStatus, errbuf, sizeof(errbuf))) { /* In this way we inform user about error within the core */ printf("{\"log\":\"Frame read error: '%s'\"}\n", errbuf); } + /* if(ffmpegStatus == AVERROR(EAGAIN)) { @@ -1184,6 +1257,7 @@ static void FFMPEGThread(Context_t *context) */ ffmpegStatus = 0; } + if (!is_finish_timeout() && !context->playback->isTSLiveMode) { isWaitingForFinish = 1; @@ -1224,6 +1298,7 @@ static void FFMPEGThread(Context_t *context) printf("{\"log\":\"Loop mode: jump to the start.\"}\n"); } } + // av_read_frame failed ffmpeg_err("no data ->end of file reached ? \n"); wrapped_packet_unref(&packet); @@ -1241,14 +1316,17 @@ static void FFMPEGThread(Context_t *context) wrapped_packet_unref(&packet); releaseMutex(__FILE__, __FUNCTION__, __LINE__); } /* while */ + if (swr) { swr_free(&swr); } + if (decoded_frame) { wrapped_frame_free(&decoded_frame); } + #if LIBAVCODEC_VERSION_INT >= AV_VERSION_INT(56, 34, 100) mpeg4p2_context_reset(&mpeg4p2_context); if (NULL != mpeg4p2_bsf_context) @@ -1256,6 +1334,7 @@ static void FFMPEGThread(Context_t *context) av_bitstream_filter_close(mpeg4p2_bsf_context); } #endif + hasPlayThreadStarted = 0; context->playback->isPlaying = 0; PlaybackDieNow(1); @@ -1301,13 +1380,16 @@ AVIOContext *container_ffmpeg_get_avio_context(char *filename, size_t avio_ctx_b { filename += 7; } + FILE *pFile = fopen(filename, "rb"); if (NULL == pFile) { return NULL; } + AVIOContext *avio_ctx = NULL; uint8_t *avio_ctx_buffer = NULL; + avio_ctx_buffer = av_malloc(avio_ctx_buffer_size); if (!avio_ctx_buffer) { @@ -1329,8 +1411,10 @@ int32_t container_ffmpeg_init_av_context(Context_t *context, char *filename, int avContextTab[AVIdx] = avformat_alloc_context(); avContextTab[AVIdx]->interrupt_callback.callback = interrupt_cb; avContextTab[AVIdx]->interrupt_callback.opaque = context->playback; + #ifdef SAM_CUSTOM_IO - if (0 == strstr(filename, "://") || 0 == strncmp(filename, "file://", 7)) + if (0 == strstr(filename, "://") || + 0 == strncmp(filename, "file://", 7)) { AVIOContext *avio_ctx = container_ffmpeg_get_avio_context(filename, 4096); if (avio_ctx) @@ -1344,6 +1428,7 @@ int32_t container_ffmpeg_init_av_context(Context_t *context, char *filename, int } } #endif + AVDictionary **pavio_opts = NULL; eRTMPProtoImplType rtmpProtoImplType = RTMP_NONE; uint8_t numOfRTMPImpl = 0; @@ -1352,6 +1437,7 @@ int32_t container_ffmpeg_init_av_context(Context_t *context, char *filename, int filename = filename + 2; rtmpProtoImplType = RTMP_NATIVE; } + if (1 == rtmp_proto_impl) { rtmpProtoImplType = RTMP_NATIVE; @@ -1360,6 +1446,7 @@ int32_t container_ffmpeg_init_av_context(Context_t *context, char *filename, int { rtmpProtoImplType = RTMP_LIBRTMP; } + if (0 == strncmp(filename, "rtmp://", 7) || 0 == strncmp(filename, "rtmpe://", 8) || 0 == strncmp(filename, "rtmps://", 8) || @@ -1373,6 +1460,7 @@ int32_t container_ffmpeg_init_av_context(Context_t *context, char *filename, int void *opaque = NULL; const char *protoName = NULL; uint8_t haveNativeProto = 0; + while ((protoName = avio_enum_protocols(&opaque, 1))) { if (0 == strcmp("rtmp", protoName)) @@ -1392,6 +1480,7 @@ int32_t container_ffmpeg_init_av_context(Context_t *context, char *filename, int haveNativeProto = 1; } } + if (haveNativeProto > 0) { if (numOfRTMPImpl > 1) // we have both @@ -1402,7 +1491,8 @@ int32_t container_ffmpeg_init_av_context(Context_t *context, char *filename, int * unless uri contain param wich can be understandable * only by librtmp */ - if (strstr(filename, " token=") || strstr(filename, " jtv=")) + if (strstr(filename, " token=") || + strstr(filename, " jtv=")) { rtmpProtoImplType = RTMP_LIBRTMP; } @@ -1421,10 +1511,12 @@ int32_t container_ffmpeg_init_av_context(Context_t *context, char *filename, int { rtmpProtoImplType = RTMP_LIBRTMP; } + if (RTMP_NATIVE == rtmpProtoImplType) { char *baseUri = strdup(filename); char *token = NULL; + // check if uri have additional params if ((token = strtok(baseUri, " ")) != NULL) { @@ -1512,11 +1604,13 @@ int32_t container_ffmpeg_init_av_context(Context_t *context, char *filename, int } token = NULL; } + if (conn[0] != '\0') { av_dict_set(&avio_opts, "rtmp_conn", conn, 0); } free(conn); + if (swfUrl[0] != '\0') { if (swfVfy[0] == '1' || !strncasecmp(swfVfy, "true", 4)) @@ -1531,6 +1625,7 @@ int32_t container_ffmpeg_init_av_context(Context_t *context, char *filename, int free(swfUrl); free(swfVfy); } + if (2 == haveNativeProto) { filename = malloc(strlen(baseUri) + 2 + 1); @@ -1546,7 +1641,8 @@ int32_t container_ffmpeg_init_av_context(Context_t *context, char *filename, int } } } - else if (0 == strncmp(filename, "http://", 7) || 0 == strncmp(filename, "https://", 8)) + else if (0 == strncmp(filename, "http://", 7) || + 0 == strncmp(filename, "https://", 8)) { av_dict_set(&avio_opts, "timeout", "20000000", 0); //20sec av_dict_set(&avio_opts, "reconnect", "1", 0); @@ -1557,7 +1653,9 @@ int32_t container_ffmpeg_init_av_context(Context_t *context, char *filename, int av_dict_set(&avio_opts, "reconnect_streamed", "1", 0); } } + pavio_opts = &avio_opts; + if ((err = avformat_open_input(&avContextTab[AVIdx], filename, fmt, pavio_opts)) != 0) { if (rtmp_proto_impl == 0 && //err == AVERROR_UNKNOWN && @@ -1568,12 +1666,15 @@ int32_t container_ffmpeg_init_av_context(Context_t *context, char *filename, int err = avformat_open_input(&avContextTab[AVIdx], filename + 2, fmt, pavio_opts); // filename2 - another memory leak, and also only once, so does not matter } + if (err != 0) { char error[512]; + ffmpeg_err("avformat_open_input failed %d (%s)\n", err, filename); av_strerror(err, error, 512); fprintf(stderr, "{\"FF_ERROR\":{\"msg\":\"%s\",\"code\":%i}}\n", error, err); + if (avio_opts != NULL) { av_dict_free(&avio_opts); @@ -1582,22 +1683,29 @@ int32_t container_ffmpeg_init_av_context(Context_t *context, char *filename, int return cERR_CONTAINER_FFMPEG_OPEN; } } + avContextTab[AVIdx]->iformat->flags |= AVFMT_SEEK_TO_PTS; avContextTab[AVIdx]->flags = AVFMT_FLAG_GENPTS; + printf("minimal Probe: %d\n", context->playback->noprobe); + if (context->playback->noprobe) { wrapped_set_max_analyze_duration(avContextTab[AVIdx], 1); } + ffmpeg_printf(20, "find_streaminfo\n"); + if (avformat_find_stream_info(avContextTab[AVIdx], NULL) < 0) { ffmpeg_err("Error avformat_find_stream_info\n"); } + //for buffered io if (avContextTab[AVIdx] != NULL && avContextTab[AVIdx]->pb != NULL && !context->playback->isTSLiveMode) { ffmpeg_real_read_org = avContextTab[AVIdx]->pb->read_packet; + if (0 == AVIdx && strstr(filename, "://") != 0 && strncmp(filename, "file://", 7) != 0) { if (ffmpeg_buf_size > 0 && ffmpeg_buf_size > FILLBUFDIFF + FILLBUFPAKET) @@ -1605,15 +1713,18 @@ int32_t container_ffmpeg_init_av_context(Context_t *context, char *filename, int if (avContextTab[AVIdx] != NULL && avContextTab[AVIdx]->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 = avContextTab[AVIdx]->pb->read_packet; avContextTab[AVIdx]->pb->read_packet = ffmpeg_read; ffmpeg_seek_org = avContextTab[AVIdx]->pb->seek; avContextTab[AVIdx]->pb->seek = ffmpeg_seek; ffmpeg_buf_read = ffmpeg_buf; ffmpeg_buf_write = ffmpeg_buf; + //fill buffer ffmpeg_filler(context, -1, NULL, 0); ffmpeg_start_fillerTHREAD(context); @@ -1627,28 +1738,34 @@ int32_t container_ffmpeg_init_av_context(Context_t *context, char *filename, int } } //for buffered io (end) + return 0; } int32_t container_ffmpeg_init(Context_t *context, PlayFiles_t *playFilesNames) { //int32_t err = 0; + ffmpeg_printf(10, ">\n"); + if (playFilesNames == NULL) { ffmpeg_err("playFilesNames NULL\n"); return cERR_CONTAINER_FFMPEG_NULL; } + if (playFilesNames->szFirstFile == NULL) { ffmpeg_err("playFilesNames->szFirstFile NULL\n"); return cERR_CONTAINER_FFMPEG_NULL; } + if (context == NULL) { ffmpeg_err("context NULL\n"); return cERR_CONTAINER_FFMPEG_NULL; } + ffmpeg_printf(10, "filename %s\n", playFilesNames->szFirstFile); if (playFilesNames->szSecondFile) { @@ -1658,24 +1775,29 @@ int32_t container_ffmpeg_init(Context_t *context, PlayFiles_t *playFilesNames) avcodec_register_all(); av_register_all(); avformat_network_init(); + // SULGE DEBUG ENABLED // make ffmpeg silen // av_log_set_level(AV_LOG_DEBUG); av_log_set_callback(ffmpeg_silen_callback); + context->playback->abortRequested = 0; int32_t res = container_ffmpeg_init_av_context(context, playFilesNames->szFirstFile, 0); if (0 != res) { return res; } + if (playFilesNames->szSecondFile) { res = container_ffmpeg_init_av_context(context, playFilesNames->szSecondFile, 1); } + if (0 != res) { return res; } + terminating = 0; latestPts = 0; res = container_ffmpeg_update_tracks(context, playFilesNames->szFirstFile, 1); @@ -1687,35 +1809,45 @@ int32_t container_ffmpeg_update_tracks(Context_t *context, char *filename, int32 Track_t *currAudioTrack = NULL; Track_t *currSubtitleTrack = NULL; uint32_t addedVideoTracksCount = 0; + if (terminating) { return cERR_CONTAINER_FFMPEG_NO_ERROR; } + getMutex(__FILE__, __FUNCTION__, __LINE__); + if (initial && context->manager->subtitle) { context->manager->subtitle->Command(context, MANAGER_GET_TRACK, &currSubtitleTrack); } + if (context->manager->audio) { context->manager->audio->Command(context, MANAGER_GET_TRACK, &currAudioTrack); } + if (context->manager->video) { context->manager->video->Command(context, MANAGER_INIT_UPDATE, NULL); } + if (context->manager->audio) { context->manager->audio->Command(context, MANAGER_INIT_UPDATE, NULL); } + #if 0 if (context->manager->subtitle) { context->manager->subtitle->Command(context, MANAGER_INIT_UPDATE, NULL); } #endif + ffmpeg_printf(20, "dump format\n"); av_dump_format(avContextTab[0], 0, filename, 0); + + uint32_t cAVIdx = 0; for (cAVIdx = 0; cAVIdx < IPTV_AV_CONTEXT_MAX_NUM; cAVIdx += 1) { @@ -1726,7 +1858,9 @@ int32_t container_ffmpeg_update_tracks(Context_t *context, char *filename, int32 AVFormatContext *avContext = avContextTab[cAVIdx]; uint32_t *stream_index = NULL; uint32_t nb_stream_indexes = 0; + ffmpeg_printf(1, "cAVIdx[%d]: number of streams: %d\n", cAVIdx, avContext->nb_streams); + if (avContext->nb_programs > 0) { uint32_t n = 0; @@ -1764,6 +1898,7 @@ int32_t container_ffmpeg_update_tracks(Context_t *context, char *filename, int32 } } } + uint32_t n = 0; for (n = 0; n < avContext->nb_streams; n++) { @@ -1771,6 +1906,7 @@ int32_t container_ffmpeg_update_tracks(Context_t *context, char *filename, int32 AVStream *stream = avContext->streams[n]; int32_t version = 0; char *encoding = NULL; + if (nb_stream_indexes > 0 && stream_index != NULL) { uint32_t isStreamFromSelProg = 0; @@ -1783,6 +1919,7 @@ int32_t container_ffmpeg_update_tracks(Context_t *context, char *filename, int32 break; } } + if (!isStreamFromSelProg) { stream->discard = AVDISCARD_ALL; @@ -1790,27 +1927,33 @@ int32_t container_ffmpeg_update_tracks(Context_t *context, char *filename, int32 continue; // skip this stream } } + encoding = Codec2Encoding((int32_t)get_codecpar(stream)->codec_id, (int32_t)get_codecpar(stream)->codec_type, \ (uint8_t *)get_codecpar(stream)->extradata, \ (int)get_codecpar(stream)->extradata_size, \ (int)get_codecpar(stream)->profile, &version); + if (encoding != NULL && !strncmp(encoding, "A_IPCM", 6) && insert_pcm_as_lpcm) { encoding = "A_LPCM"; } + if (encoding != NULL) { ffmpeg_printf(1, "%d. encoding = %s - version %d\n", n, encoding, version); } + if (!stream->id) { stream->id = n; } + /* some values in track are unset and therefor copyTrack segfaults. * so set it by default to NULL! */ memset(&track, 0, sizeof(track)); track.AVIdx = cAVIdx; + switch (get_codecpar(stream)->codec_type) { case AVMEDIA_TYPE_VIDEO: @@ -1820,8 +1963,10 @@ int32_t container_ffmpeg_update_tracks(Context_t *context, char *filename, int32 { track.type = eTypeES; track.version = version; + track.width = get_codecpar(stream)->width; track.height = get_codecpar(stream)->height; + /* We will return here PAR (Pixel Aspect Ratio) client need to calculate DAR(Display Aspect Ratio) * example: PAR 64:45 DAR 16:9 * Resolution 720x576 @@ -1835,15 +1980,19 @@ int32_t container_ffmpeg_update_tracks(Context_t *context, char *filename, int32 track.aspect_ratio_num = get_codecpar(stream)->sample_aspect_ratio.num; track.aspect_ratio_den = get_codecpar(stream)->sample_aspect_ratio.den; } + track.extraData = get_codecpar(stream)->extradata; track.extraSize = get_codecpar(stream)->extradata_size; + track.aacbuf = 0; track.have_aacheader = -1; + AVRational rateRational = get_frame_rate(stream); if (rateRational.den != 0) { track.frame_rate = (uint32_t)(1000 * (int64_t)(rateRational.num) / (int64_t)(rateRational.den)); } + /* fixme: revise this */ if (track.frame_rate < 23970) { @@ -1853,6 +2002,7 @@ int32_t container_ffmpeg_update_tracks(Context_t *context, char *filename, int32 { track.TimeScale = 1000; } + ffmpeg_printf(10, "bit_rate [%lld]\n", get_codecpar(stream)->bit_rate); ffmpeg_printf(10, "time_base.den [%d]\n", stream->time_base.den); ffmpeg_printf(10, "time_base.num [%d]\n", stream->time_base.num); @@ -1860,19 +2010,24 @@ int32_t container_ffmpeg_update_tracks(Context_t *context, char *filename, int32 ffmpeg_printf(10, "height [%d]\n", get_codecpar(stream)->height); ffmpeg_printf(10, "frame_rate num [%d]\n", rateRational.num); ffmpeg_printf(10, "frame_rate den [%d]\n", rateRational.den); + ffmpeg_printf(10, "frame_rate [%u]\n", track.frame_rate); ffmpeg_printf(10, "TimeScale [%d]\n", track.TimeScale); + track.Name = "und"; track.Encoding = encoding; track.stream = stream; track.Id = ((AVStream *)(track.stream))->id; + track.duration = (int64_t)av_rescale(stream->duration, (int64_t)stream->time_base.num * 1000, stream->time_base.den); if (stream->duration == AV_NOPTS_VALUE || 0 == strncmp(avContext->iformat->name, "dash", 4)) { ffmpeg_printf(10, "Stream has no duration so we take the duration from context\n"); track.duration = (int64_t) avContext->duration / 1000; } + ffmpeg_printf(10, "duration [%lld]\n", track.duration); + if (context->manager->video) { if (get_codecpar(stream)->codec_id == AV_CODEC_ID_MPEG4) @@ -1907,20 +2062,26 @@ int32_t container_ffmpeg_update_tracks(Context_t *context, char *filename, int32 { AVDictionaryEntry *lang; track.type = eTypeES; + lang = av_dict_get(stream->metadata, "language", NULL, 0); + track.Name = lang ? lang->value : "und"; + ffmpeg_printf(10, "Language %s\n", track.Name); + track.Encoding = encoding; track.stream = stream; track.Id = ((AVStream *)(track.stream))->id; track.aacbuf = 0; track.have_aacheader = -1; + track.duration = (int64_t)av_rescale(stream->duration, (int64_t)stream->time_base.num * 1000, stream->time_base.den); if (stream->duration == AV_NOPTS_VALUE) { ffmpeg_printf(10, "Stream has no duration so we take the duration from context\n"); track.duration = (int64_t) avContext->duration / 1000; } + if (!strncmp(encoding, "A_IPCM", 6) || !strncmp(encoding, "A_LPCM", 6)) { track.inject_as_pcm = 1; @@ -1928,7 +2089,9 @@ int32_t container_ffmpeg_update_tracks(Context_t *context, char *filename, int32 if (track.avCodecCtx) { ffmpeg_printf(10, " Handle inject_as_pcm = %d\n", track.inject_as_pcm); + AVCodec *codec = avcodec_find_decoder(get_codecpar(stream)->codec_id); + int errorCode = avcodec_open2(track.avCodecCtx, codec, NULL); if (codec != NULL && !errorCode) { @@ -1950,6 +2113,7 @@ int32_t container_ffmpeg_update_tracks(Context_t *context, char *filename, int32 track.aacbuflen = sizeof(marker) / sizeof(char); track.aacbuf = malloc(track.aacbuflen); memcpy(track.aacbuf, marker, track.aacbuflen); + ffmpeg_printf(10, "AV_CODEC_ID_AAC_LATM no extradata ACC header should be available in each frame\n"); track.have_aacheader = 1; } @@ -1966,6 +2130,7 @@ int32_t container_ffmpeg_update_tracks(Context_t *context, char *filename, int32 track.aacbuflen = sizeof(marker) / sizeof(char); track.aacbuf = malloc(track.aacbuflen); memcpy(track.aacbuf, marker, track.aacbuflen); + ffmpeg_printf(10, "AV_CODEC_ID_AAC no extradata ACC header should be available in each frame\n"); track.have_aacheader = 1; } @@ -1974,6 +2139,7 @@ int32_t container_ffmpeg_update_tracks(Context_t *context, char *filename, int32 ffmpeg_printf(10, "Create AAC ExtraData\n"); ffmpeg_printf(10, "get_codecpar(stream)->extradata_size %d\n", get_codecpar(stream)->extradata_size); //Hexdump(get_codecpar(stream)->extradata, get_codecpar(stream)->extradata_size); + /* extradata: 13 10 56 e5 9d 48 00 (anderen cops) object_type: 00010 2 = LC @@ -1988,12 +2154,14 @@ int32_t container_ffmpeg_update_tracks(Context_t *context, char *filename, int32 ps = 0 0000000 */ + int32_t object_type = 2; // LC int32_t sample_index = aac_get_sample_rate_index(get_codecpar(stream)->sample_rate); int32_t chan_config = get_codecpar(stream)->channels - 1; ffmpeg_printf(1, "aac object_type %d\n", object_type); ffmpeg_printf(1, "aac sample_index %d\n", sample_index); ffmpeg_printf(1, "aac chan_config %d\n", chan_config); + if (get_codecpar(stream)->extradata_size >= 2) { MPEG4AudioConfig m4ac; @@ -2009,11 +2177,15 @@ int32_t container_ffmpeg_update_tracks(Context_t *context, char *filename, int32 chan_config = m4ac.chan_config; } } + ffmpeg_printf(1, "aac object_type %d\n", object_type); ffmpeg_printf(1, "aac sample_index %d\n", sample_index); ffmpeg_printf(1, "aac chan_config %d\n", chan_config); + + // https://wiki.multimedia.cx/index.php/ADTS object_type -= 1; //ADTS - profile, the MPEG-4 Audio Object Type minus 1 + track.aacbuflen = AAC_HEADER_LENGTH; track.aacbuf = malloc(8); track.aacbuf[0] = 0xFF; @@ -2025,6 +2197,7 @@ int32_t container_ffmpeg_update_tracks(Context_t *context, char *filename, int32 track.aacbuf[4] = 0x00; track.aacbuf[5] = 0x1F; track.aacbuf[6] = 0xFC; + //printf("AAC_HEADER -> "); //Hexdump(track.aacbuf,7); track.have_aacheader = 1; @@ -2035,6 +2208,7 @@ int32_t container_ffmpeg_update_tracks(Context_t *context, char *filename, int32 ffmpeg_err("AV_CODEC_ID_AAC extradata not available\n"); } */ + } else if (get_codecpar(stream)->codec_id == AV_CODEC_ID_WMAV1 || get_codecpar(stream)->codec_id == AV_CODEC_ID_WMAV2 || @@ -2049,6 +2223,7 @@ int32_t container_ffmpeg_update_tracks(Context_t *context, char *filename, int32 uint16_t depth = get_codecpar(stream)->bits_per_coded_sample; uint32_t codec_data_size = get_codecpar(stream)->extradata_size; uint8_t *codec_data_pointer = get_codecpar(stream)->extradata; + // type_specific_data #define WMA_VERSION_1 0x160 #define WMA_VERSION_2_9 0x161 @@ -2076,40 +2251,58 @@ int32_t container_ffmpeg_update_tracks(Context_t *context, char *filename, int32 track.aacbuflen = 104 + get_codecpar(stream)->extradata_size; track.aacbuf = malloc(track.aacbuflen); memset(track.aacbuf, 0, track.aacbuflen); + uint8_t ASF_Stream_Properties_Object[16] = {0x91, 0x07, 0xDC, 0xB7, 0xB7, 0xA9, 0xCF, 0x11, 0x8E, 0xE6, 0x00, 0xC0, 0x0C, 0x20, 0x53, 0x65}; + memcpy(track.aacbuf + 0, ASF_Stream_Properties_Object, 16); // ASF_Stream_Properties_Object memcpy(track.aacbuf + 16, &track.aacbuflen, 4); //FrameDateLength + uint32_t sizehi = 0; memcpy(track.aacbuf + 20, &sizehi, 4); // sizehi (not used) + uint8_t ASF_Audio_Media[16] = {0x40, 0x9E, 0x69, 0xF8, 0x4D, 0x5B, 0xCF, 0x11, 0xA8, 0xFD, 0x00, 0x80, 0x5F, 0x5C, 0x44, 0x2B}; + memcpy(track.aacbuf + 24, ASF_Audio_Media, 16); //ASF_Audio_Media + uint8_t ASF_Audio_Spread[16] = {0x50, 0xCD, 0xC3, 0xBF, 0x8F, 0x61, 0xCF, 0x11, 0x8B, 0xB2, 0x00, 0xAA, 0x00, 0xB4, 0xE2, 0x20}; + memcpy(track.aacbuf + 40, ASF_Audio_Spread, 16); //ASF_Audio_Spread + memset(track.aacbuf + 56, 0, 4); // time_offset (not used) memset(track.aacbuf + 60, 0, 4); // time_offset_hi (not used) + uint8_t type_specific_data_length = 18 + get_codecpar(stream)->extradata_size; memcpy(track.aacbuf + 64, &type_specific_data_length, 4); //type_specific_data_length + uint8_t error_correction_data_length = 8; memcpy(track.aacbuf + 68, &error_correction_data_length, 4); //error_correction_data_length + uint16_t flags = 1; // stream_number memcpy(track.aacbuf + 72, &flags, 2); //flags + uint32_t reserved = 0; memcpy(track.aacbuf + 74, &reserved, 4); // reserved + memcpy(track.aacbuf + 78, &codec_id, 2); //codec_id + uint16_t number_of_channels = get_codecpar(stream)->channels; memcpy(track.aacbuf + 80, &number_of_channels, 2); //number_of_channels + uint32_t samples_per_second = get_codecpar(stream)->sample_rate; ffmpeg_printf(1, "samples_per_second = %d\n", samples_per_second); memcpy(track.aacbuf + 82, &samples_per_second, 4); //samples_per_second + uint32_t average_number_of_bytes_per_second = get_codecpar(stream)->bit_rate / 8; ffmpeg_printf(1, "average_number_of_bytes_per_second = %d\n", average_number_of_bytes_per_second); memcpy(track.aacbuf + 86, &average_number_of_bytes_per_second, 4); //average_number_of_bytes_per_second + uint16_t block_alignment = get_codecpar(stream)->block_align; ffmpeg_printf(1, "block_alignment = %d\n", block_alignment); memcpy(track.aacbuf + 90, &block_alignment, 2); //block_alignment + #if (LIBAVFORMAT_VERSION_MAJOR > 57) || ((LIBAVFORMAT_VERSION_MAJOR == 57) && (LIBAVFORMAT_VERSION_MINOR > 32)) enum AVSampleFormat sample_fmt = get_codecpar(stream)->format; #else @@ -2118,12 +2311,15 @@ int32_t container_ffmpeg_update_tracks(Context_t *context, char *filename, int32 uint16_t bits_per_sample = sample_fmt >= 0 ? (sample_fmt + 1) * 8 : 8; ffmpeg_printf(1, "bits_per_sample = %d (%d)\n", bits_per_sample, sample_fmt); memcpy(track.aacbuf + 92, &bits_per_sample, 2); //bits_per_sample + memcpy(track.aacbuf + 94, &get_codecpar(stream)->extradata_size, 2); //bits_per_sample + memcpy(track.aacbuf + 96, get_codecpar(stream)->extradata, get_codecpar(stream)->extradata_size); #else track.aacbuflen = 18 + get_codecpar(stream)->extradata_size; track.aacbuf = malloc(track.aacbuflen); memset(track.aacbuf, 0, track.aacbuflen); + uint8_t *data = track.aacbuf; /* codec tag */ *(data++) = codec_id & 0xff; @@ -2155,10 +2351,13 @@ int32_t container_ffmpeg_update_tracks(Context_t *context, char *filename, int32 #endif ffmpeg_printf(1, "aacbuf:\n"); //Hexdump(track.aacbuf, track.aacbuflen); + //ffmpeg_printf(1, "priv_data:\n"); //Hexdump(get_codecpar(stream)->priv_data, track.aacbuflen); + track.have_aacheader = 1; } + if (context->manager->audio) { ffmpeg_printf(1, "cAVIdx[%d]: MANAGER_ADD track AUDIO\n"); @@ -2190,26 +2389,34 @@ int32_t container_ffmpeg_update_tracks(Context_t *context, char *filename, int32 { AVDictionaryEntry *lang = NULL; memset(&track, 0, sizeof(track)); + ffmpeg_printf(10, "CODEC_TYPE_SUBTITLE %d\n", get_codecpar(stream)->codec_type); + lang = av_dict_get(stream->metadata, "language", NULL, 0); track.Name = lang ? lang->value : "und"; ffmpeg_printf(10, "Language %s\n", track.Name); + track.Encoding = encoding; track.stream = stream; track.Id = ((AVStream *)(track.stream))->id; track.duration = (int64_t)av_rescale(stream->duration, (int64_t)stream->time_base.num * 1000, stream->time_base.den); + if (stream->duration == AV_NOPTS_VALUE) { ffmpeg_printf(10, "Stream has no duration so we take the duration from context\n"); track.duration = (int64_t) avContext->duration / 1000; } + track.extraData = get_codecpar(stream)->extradata; track.extraSize = get_codecpar(stream)->extradata_size; + ffmpeg_printf(1, "subtitle codec %d\n", get_codecpar(stream)->codec_id); ffmpeg_printf(1, "subtitle width %d\n", get_codecpar(stream)->width); ffmpeg_printf(1, "subtitle height %d\n", get_codecpar(stream)->height); ffmpeg_printf(1, "subtitle stream %p\n", stream); + ffmpeg_printf(10, "FOUND SUBTITLE %s\n", track.Name); + if (context->manager->subtitle->Command(context, MANAGER_ADD, &track) < 0) { ffmpeg_err("failed to add subtitle track %d\n", n); @@ -2228,11 +2435,13 @@ int32_t container_ffmpeg_update_tracks(Context_t *context, char *filename, int32 } } /* 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) @@ -2242,14 +2451,17 @@ int32_t container_ffmpeg_update_tracks(Context_t *context, char *filename, int32 { 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; @@ -2260,6 +2472,7 @@ int32_t container_ffmpeg_update_tracks(Context_t *context, char *filename, int32 } } } + releaseMutex(__FILE__, __FUNCTION__, __LINE__); return cERR_CONTAINER_FFMPEG_NO_ERROR; } @@ -2269,7 +2482,9 @@ static int32_t container_ffmpeg_play(Context_t *context) int32_t error = 0; int32_t ret = 0; pthread_attr_t attr; + ffmpeg_printf(10, "\n"); + if (context && context->playback && context->playback->isPlaying) { ffmpeg_printf(10, "is Playing\n"); @@ -2278,19 +2493,23 @@ static int32_t container_ffmpeg_play(Context_t *context) { ffmpeg_printf(10, "is NOT Playing\n"); } + if (hasPlayThreadStarted == 0) { pthread_attr_init(&attr); pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED); + if ((error = pthread_create(&PlayThread, &attr, (void *)&FFMPEGThread, context)) != 0) { ffmpeg_printf(10, "Error creating thread, error:%d:%s\n", error, strerror(error)); + hasPlayThreadStarted = 0; ret = cERR_CONTAINER_FFMPEG_ERR; } else { ffmpeg_printf(10, "Created thread\n"); + hasPlayThreadStarted = 1; } } @@ -2299,6 +2518,7 @@ static int32_t container_ffmpeg_play(Context_t *context) ffmpeg_printf(10, "A thread already exists!\n"); ret = cERR_CONTAINER_FFMPEG_ERR; } + ffmpeg_printf(10, "exiting with value %d\n", ret); return ret; } @@ -2311,16 +2531,20 @@ static int32_t container_ffmpeg_stop(Context_t *context) * in this case, ffmpeg thread will not be terminated * and causes in most cases a segfault */ + ffmpeg_printf(10, "\n"); + if (context->playback) { context->playback->isPlaying = 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); usleep(100000); } + if (wait_time == 0) { /* force close */ @@ -2331,10 +2555,14 @@ static int32_t container_ffmpeg_stop(Context_t *context) */ return ret; } + hasPlayThreadStarted = 0; terminating = 1; + getMutex(__FILE__, __FUNCTION__, __LINE__); + free_all_stored_avcodec_context(); + uint32_t i = 0; for (i = 0; i < IPTV_AV_CONTEXT_MAX_NUM; i += 1) { @@ -2360,13 +2588,17 @@ static int32_t container_ffmpeg_stop(Context_t *context) break; } } + if (avio_opts != NULL) { av_dict_free(&avio_opts); } + avformat_network_deinit(); ffmpeg_buf_free(); + releaseMutex(__FILE__, __FUNCTION__, __LINE__); + ffmpeg_printf(10, "ret %d\n", ret); return ret; } @@ -2375,19 +2607,25 @@ static int32_t container_ffmpeg_seek_bytes(off_t pos) { int32_t flag = AVSEEK_FLAG_BYTE; off_t current_pos = avio_tell(avContextTab[0]->pb); + ffmpeg_printf(20, "seeking to position %lld (bytes)\n", pos); + if (current_pos > pos) { flag |= AVSEEK_FLAG_BACKWARD; } + if (avformat_seek_file(avContextTab[0], -1, INT64_MIN, pos, INT64_MAX, flag) < 0) { ffmpeg_err("Error seeking\n"); return cERR_CONTAINER_FFMPEG_ERR; } + ffmpeg_printf(30, "current_pos after seek %lld\n", avio_tell(avContextTab[0]->pb)); + return cERR_CONTAINER_FFMPEG_NO_ERROR; } + #if 0 //unused /* seeking relative to a given byteposition N seconds ->for reverse playback needed */ static int32_t container_ffmpeg_seek_rel(Context_t *context, off_t pos, int64_t pts, int64_t sec) @@ -2396,9 +2634,12 @@ static int32_t container_ffmpeg_seek_rel(Context_t *context, off_t pos, int64_t Track_t *audioTrack = NULL; Track_t *current = NULL; seek_target_flag = 0; + ffmpeg_printf(10, "seeking %f sec relativ to %lld\n", sec, pos); + context->manager->video->Command(context, MANAGER_GET_TRACK, &videoTrack); context->manager->audio->Command(context, MANAGER_GET_TRACK, &audioTrack); + if (videoTrack != NULL) { current = videoTrack; @@ -2407,23 +2648,28 @@ static int32_t container_ffmpeg_seek_rel(Context_t *context, off_t pos, int64_t { current = audioTrack; } + if (current == NULL) { ffmpeg_err("no track avaibale to seek\n"); return cERR_CONTAINER_FFMPEG_ERR; } + if (pos == -1) { pos = avio_tell(avContextTab[0]->pb); } + if (pts == -1) { pts = current->pts; } + if (sec < 0) { seek_target_flag |= AVSEEK_FLAG_BACKWARD; } + ffmpeg_printf(10, "iformat->flags %d\n", avContextTab[0]->iformat->flags); #if defined(TS_BYTES_SEEKING) && TS_BYTES_SEEKING if (avContextTab[0]->iformat->flags & AVFMT_TS_DISCONT) @@ -2437,41 +2683,53 @@ static int32_t container_ffmpeg_seek_rel(Context_t *context, off_t pos, int64_t { sec *= 180000; } + pos += sec; + if (pos < 0) { ffmpeg_err("end of file reached\n"); releaseMutex(__FILE__, __FUNCTION__, __LINE__); return cERR_CONTAINER_FFMPEG_END_OF_FILE; } + ffmpeg_printf(10, "1. seeking to position %lld bytes ->sec %f\n", pos, sec); + seek_target_bytes = pos; do_seek_target_bytes = 1; + return pos; } else #endif { sec += pts / 90000; + if (sec < 0) { sec = 0; } + ffmpeg_printf(10, "2. seeking to position %f sec ->time base %f %d\n", sec, av_q2d(((AVStream *) current->stream)->time_base), AV_TIME_BASE); + seek_target_seconds = sec * AV_TIME_BASE; do_seek_target_seconds = 1; } + releaseMutex(__FILE__, __FUNCTION__, __LINE__); return cERR_CONTAINER_FFMPEG_NO_ERROR; } #endif + static int32_t container_ffmpeg_seek(Context_t *context, int64_t sec, uint8_t absolute) { Track_t *videoTrack = NULL; Track_t *audioTrack = NULL; // Track_t *current = NULL; seek_target_flag = 0; + sec *= AV_TIME_BASE; + if (!absolute) { ffmpeg_printf(10, "seeking %lld sec\n", sec / AV_TIME_BASE); @@ -2497,9 +2755,12 @@ static int32_t container_ffmpeg_seek(Context_t *context, int64_t sec, uint8_t ab sec = 0; } } + ffmpeg_printf(10, "goto %lld sec\n", sec / AV_TIME_BASE); + context->manager->video->Command(context, MANAGER_GET_TRACK, &videoTrack); context->manager->audio->Command(context, MANAGER_GET_TRACK, &audioTrack); + if (!videoTrack && !audioTrack) { ffmpeg_err("no track available to seek\n"); @@ -2526,11 +2787,13 @@ static int32_t container_ffmpeg_seek(Context_t *context, int64_t sec, uint8_t ab { seek_target_flag |= AVSEEK_FLAG_BACKWARD; } + if (!context->playback || !context->playback->isPlaying) { releaseMutex(__FILE__, __FUNCTION__, __LINE__); return cERR_CONTAINER_FFMPEG_NO_ERROR; } + ffmpeg_printf(10, "iformat->flags 0x%08x\n", avContextTab[0]->iformat->flags); #if defined(TS_BYTES_SEEKING) && TS_BYTES_SEEKING if (avContextTab[0]->iformat->flags & AVFMT_TS_DISCONT) @@ -2541,10 +2804,13 @@ 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 * about 10 seconds, backward does not work. */ + getMutex(__FILE__, __FUNCTION__, __LINE__); off_t pos = avio_tell(avContextTab[0]->pb); releaseMutex(__FILE__, __FUNCTION__, __LINE__); + ffmpeg_printf(10, "pos %lld %lld\n", pos, avContextTab[0]->bit_rate); + if (avContextTab[0]->bit_rate) { sec *= avContextTab[0]->bit_rate / 8; @@ -2554,12 +2820,16 @@ static int32_t container_ffmpeg_seek(Context_t *context, int64_t sec, uint8_t ab { sec *= 180000; } + pos = sec; + if (pos < 0) { pos = 0; } + ffmpeg_printf(10, "1. seeking to position %lld bytes ->sec %lld\n", pos / AV_TIME_BASE, sec / AV_TIME_BASE); + seek_target_bytes = pos / AV_TIME_BASE; do_seek_target_bytes = 1; } @@ -2569,6 +2839,7 @@ static int32_t container_ffmpeg_seek(Context_t *context, int64_t sec, uint8_t ab seek_target_seconds = sec; do_seek_target_seconds = 1; } + return cERR_CONTAINER_FFMPEG_NO_ERROR; } @@ -2578,13 +2849,16 @@ static int32_t container_ffmpeg_get_length(Context_t *context, int64_t *length) Track_t *videoTrack = NULL; Track_t *audioTrack = NULL; Track_t *current = NULL; + if (length == NULL) { ffmpeg_err("null pointer passed\n"); return cERR_CONTAINER_FFMPEG_ERR; } + context->manager->video->Command(context, MANAGER_GET_TRACK, &videoTrack); context->manager->audio->Command(context, MANAGER_GET_TRACK, &audioTrack); + if (videoTrack != NULL) { current = videoTrack; @@ -2593,7 +2867,9 @@ static int32_t container_ffmpeg_get_length(Context_t *context, int64_t *length) { current = audioTrack; } + *length = 0; + if (current != NULL) { if (current->duration == 0) @@ -2617,6 +2893,7 @@ static int32_t container_ffmpeg_get_length(Context_t *context, int64_t *length) return cERR_CONTAINER_FFMPEG_ERR; } } + return cERR_CONTAINER_FFMPEG_NO_ERROR; } @@ -2628,6 +2905,7 @@ static int32_t container_ffmpeg_switch_audio(Context_t *context, int32_t *arg __ { 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) @@ -2640,6 +2918,7 @@ static int32_t container_ffmpeg_switch_audio(Context_t *context, int32_t *arg __ } } releaseMutex(__FILE__, __FUNCTION__, __LINE__); + /* Hellmaster1024: nothing to do here! */ int64_t sec = -1; context->playback->Command(context, PLAYBACK_SEEK, (void *)&sec); @@ -2649,6 +2928,7 @@ static int32_t container_ffmpeg_switch_audio(Context_t *context, int32_t *arg __ static int32_t container_ffmpeg_switch_subtitle(Context_t *context, int32_t *arg __attribute__((unused))) { ffmpeg_printf(10, "track %d\n", *arg); + /* This is made to flush inside the buffer because * subtitles frame was already read and ignored * we seek to force ffmpeg to read once again the same data @@ -2672,7 +2952,9 @@ static int32_t container_ffmpeg_get_info(Context_t *context, char **infoString) Track_t *videoTrack = NULL; Track_t *audioTrack = NULL; char *meta = NULL; + ffmpeg_printf(20, ">\n"); + if (avContextTab[0] != NULL) { if ((infoString == NULL) || (*infoString == NULL)) @@ -2680,9 +2962,12 @@ static int32_t container_ffmpeg_get_info(Context_t *context, char **infoString) ffmpeg_err("infostring NULL\n"); return cERR_CONTAINER_FFMPEG_ERR; } + ffmpeg_printf(20, "%s\n", *infoString); + context->manager->video->Command(context, MANAGER_GET_TRACK, &videoTrack); context->manager->audio->Command(context, MANAGER_GET_TRACK, &audioTrack); + if ((meta = searchMeta(avContextTab[0]->metadata, *infoString)) == NULL) { if (audioTrack != NULL) @@ -2690,12 +2975,14 @@ static int32_t container_ffmpeg_get_info(Context_t *context, char **infoString) AVStream *stream = audioTrack->stream; meta = searchMeta(stream->metadata, *infoString); } + if ((meta == NULL) && (videoTrack != NULL)) { AVStream *stream = videoTrack->stream; meta = searchMeta(stream->metadata, *infoString); } } + if (meta != NULL) { *infoString = strdup(meta); @@ -2786,7 +3073,9 @@ static int container_ffmpeg_get_metadata(Context_t * context, char ***p) static int32_t Command(Context_t *context, ContainerCmd_t command, void *argument) { int ret = cERR_CONTAINER_FFMPEG_NO_ERROR; + ffmpeg_printf(50, "Command %d\n", command); + if (command != CONTAINER_SET_BUFFER_SEEK_TIME && command != CONTAINER_SET_BUFFER_SIZE && command != CONTAINER_GET_BUFFER_SIZE && @@ -2796,6 +3085,7 @@ static int32_t Command(Context_t *context, ContainerCmd_t command, void *argumen { return cERR_CONTAINER_FFMPEG_ERR; } + switch (command) { case CONTAINER_INIT: @@ -2878,6 +3168,7 @@ static int32_t Command(Context_t *context, ContainerCmd_t command, void *argumen ret = cERR_CONTAINER_FFMPEG_ERR; break; } + ffmpeg_printf(50, "exiting with value %d\n", ret); return ret; } diff --git a/libeplayer3-arm/container/flv2mpeg4_ffmpeg.c b/libeplayer3-arm/container/flv2mpeg4_ffmpeg.c index 8f72216..cc00144 100644 --- a/libeplayer3-arm/container/flv2mpeg4_ffmpeg.c +++ b/libeplayer3-arm/container/flv2mpeg4_ffmpeg.c @@ -5,6 +5,7 @@ #include "flv2mpeg4/flv2mpeg4.h" + typedef struct { flv2mpeg4_CTX *ctx; @@ -15,6 +16,7 @@ typedef struct Track_t *track; } Flv2Mpeg4Context; + static int flv2mpeg4_context_write_packet_cb(void *usr_data, int keyframe, int pts, const uint8_t *buf, int size) { Flv2Mpeg4Context *ctx = usr_data; @@ -22,6 +24,7 @@ static int flv2mpeg4_context_write_packet_cb(void *usr_data, int keyframe, int p { return -1; } + AudioVideoOut_t avOut; avOut.data = (char *)buf; avOut.len = size; @@ -34,10 +37,12 @@ static int flv2mpeg4_context_write_packet_cb(void *usr_data, int keyframe, int p avOut.width = ctx->track->width; avOut.height = ctx->track->height; avOut.type = "video"; + if (Write(ctx->out_ctx->output->video->Write, ctx->out_ctx, &avOut, avOut.pts) < 0) { ffmpeg_err("writing data to video device failed\n"); } + return 0; } @@ -48,10 +53,12 @@ static int flv2mpeg4_context_write_extradata_cb(void *usr_data, int width, int h { return -1; } + free(ctx->extradata); ctx->extradata = malloc(extradatasize); memcpy(ctx->extradata, extradata, extradatasize); ctx->extradatasize = extradatasize; + return 0; } @@ -59,6 +66,7 @@ static void flv2mpeg4_context_reset(Flv2Mpeg4Context *context) { if (context == NULL || context->ctx == NULL) return; + flv2mpeg4_set_frame(context->ctx, 0, 0); } @@ -69,14 +77,19 @@ static int flv2mpeg4_write_packet(Context_t *out_ctx, Flv2Mpeg4Context *mpeg4p2_ mpeg4p2_ctx->ctx = flv2mpeg4_init_ctx(mpeg4p2_ctx, track->width, track->height, flv2mpeg4_context_write_packet_cb, flv2mpeg4_context_write_extradata_cb); flv2mpeg4_prepare_extra_data(mpeg4p2_ctx->ctx); } + *pts_current = track->pts = calcPts(cAVIdx, track->stream, pkt->pts); if ((*pts_current > *pts_latest) && (*pts_current != INVALID_PTS_VALUE)) { *pts_latest = *pts_current; } track->dts = calcPts(cAVIdx, track->stream, pkt->dts); + mpeg4p2_ctx->out_ctx = out_ctx; mpeg4p2_ctx->track = track; + uint32_t time_ms = (uint32_t)(track->pts / 90); + return flv2mpeg4_process_flv_packet(mpeg4p2_ctx->ctx, 0, pkt->data, pkt->size, time_ms); } + diff --git a/libeplayer3-arm/container/mpeg4p2_ffmpeg.c b/libeplayer3-arm/container/mpeg4p2_ffmpeg.c index 74a5559..0565912 100644 --- a/libeplayer3-arm/container/mpeg4p2_ffmpeg.c +++ b/libeplayer3-arm/container/mpeg4p2_ffmpeg.c @@ -14,6 +14,7 @@ typedef struct AVPacket *second_ip_frame; } Mpeg4P2Context; + static void set_packet(AVPacket **pkt_dest, AVPacket *pkt_src) { if (pkt_dest == NULL) @@ -82,6 +83,7 @@ static void mpeg4p2_context_reset(Mpeg4P2Context *context) av_free(context->second_ip_frame); } context->second_ip_frame = NULL; + context->b_frames_count = 0; context->first_ip_frame_written = 0; context->packet_duration = 0; @@ -95,6 +97,7 @@ static void mpeg4p2_write(Context_t *ctx, Track_t *track, int avContextIdx, int6 *pts_latest = *pts_current; } track->dts = calcPts(avContextIdx, track->stream, pkt->dts); + AudioVideoOut_t avOut; avOut.data = pkt->data; avOut.len = pkt->size; @@ -107,6 +110,7 @@ static void mpeg4p2_write(Context_t *ctx, Track_t *track, int avContextIdx, int6 avOut.width = track->width; avOut.height = track->height; avOut.type = "video"; + if (Write(ctx->output->video->Write, ctx, &avOut, avOut.pts) < 0) { ffmpeg_err("writing data to video device failed\n"); @@ -206,3 +210,4 @@ static int mpeg4p2_write_packet(Context_t *ctx, Mpeg4P2Context *mpeg4p2_ctx, Tra } return 0; } + diff --git a/libeplayer3-arm/container/wrapped_ffmpeg.c b/libeplayer3-arm/container/wrapped_ffmpeg.c index 3ca4738..2bf6bb7 100644 --- a/libeplayer3-arm/container/wrapped_ffmpeg.c +++ b/libeplayer3-arm/container/wrapped_ffmpeg.c @@ -121,9 +121,11 @@ int store_avcodec_context(AVCodecContext *avCodecCtx __attribute__((unused)), ui { return -1; } + memset(ptr, 0x00, sizeof(CodecCtxStoreItem_t)); ptr->next = g_codecCtxStoreListHead; g_codecCtxStoreListHead = ptr; + return 0; } #else @@ -144,6 +146,7 @@ static AVCodecContext *wrapped_avcodec_get_context(uint32_t cAVIdx, AVStream *st fprintf(stderr, "context3 alloc for stream %d failed\n", (int)stream->id); return NULL; } + if (avcodec_parameters_to_context(avCodecCtx, stream->codecpar) < 0) { fprintf(stderr, "parameters to context for stream %d failed\n", (int)stream->id); @@ -151,8 +154,10 @@ static AVCodecContext *wrapped_avcodec_get_context(uint32_t cAVIdx, AVStream *st return NULL; } av_codec_set_pkt_timebase(avCodecCtx, stream->time_base); + store_avcodec_context(avCodecCtx, cAVIdx, stream->id); } + return avCodecCtx; #else return stream->codec; diff --git a/libeplayer3-arm/external/ffmpeg/get_bits.h b/libeplayer3-arm/external/ffmpeg/get_bits.h index b0f49e3..e40e201 100644 --- a/libeplayer3-arm/external/ffmpeg/get_bits.h +++ b/libeplayer3-arm/external/ffmpeg/get_bits.h @@ -100,9 +100,11 @@ typedef struct GetBitContext unsigned int name ## _index = (gb)->index; \ unsigned int av_unused name ## _cache + #define OPEN_READER(name, gb) OPEN_READER_NOSIZE(name, gb) #define BITS_AVAILABLE(name, gb) 1 + #define CLOSE_READER(name, gb) (gb)->index = name ## _index # ifdef LONG_BITSTREAM_READER @@ -123,6 +125,7 @@ typedef struct GetBitContext #endif + #ifdef BITSTREAM_READER_LE # define UPDATE_CACHE(name, gb) UPDATE_CACHE_LE(name, gb) @@ -139,6 +142,7 @@ typedef struct GetBitContext #define SKIP_COUNTER(name, gb, num) name ## _index += (num) + #define BITS_LEFT(name, gb) ((int)((gb)->size_in_bits - name ## _index)) #define SKIP_BITS(name, gb, num) \ @@ -282,6 +286,7 @@ static inline unsigned int get_bits1(GetBitContext *s) #endif index++; s->index = index; + return result; } @@ -349,6 +354,7 @@ static inline int get_sbits_long(GetBitContext *s, int n) /* sign_extend(x, 0) is undefined */ if (!n) return 0; + return sign_extend(get_bits_long(s, n), n); } @@ -387,18 +393,22 @@ static inline int init_get_bits(GetBitContext *s, const uint8_t *buffer, { int buffer_size; int ret = 0; + if (bit_size >= INT_MAX - 7 || bit_size < 0 || !buffer) { bit_size = 0; buffer = NULL; ret = AVERROR_INVALIDDATA; } + buffer_size = (bit_size + 7) >> 3; + s->buffer = buffer; s->size_in_bits = bit_size; s->size_in_bits_plus8 = bit_size + 8; s->buffer_end = buffer + buffer_size; s->index = 0; + return ret; } @@ -500,6 +510,7 @@ static inline const uint8_t *align_get_bits(GetBitContext *s) SKIP_BITS(name, gb, n); \ } while (0) + static inline int decode012(GetBitContext *gb) { int n; @@ -527,12 +538,14 @@ static inline int skip_1stop_8data_bits(GetBitContext *gb) { if (get_bits_left(gb) <= 0) return AVERROR_INVALIDDATA; + while (get_bits1(gb)) { skip_bits(gb, 8); if (get_bits_left(gb) <= 0) return AVERROR_INVALIDDATA; } + return 0; } diff --git a/libeplayer3-arm/external/ffmpeg/latmenc.h b/libeplayer3-arm/external/ffmpeg/latmenc.h index 8e6a847..e5d3345 100644 --- a/libeplayer3-arm/external/ffmpeg/latmenc.h +++ b/libeplayer3-arm/external/ffmpeg/latmenc.h @@ -42,3 +42,4 @@ int latmenc_decode_extradata(LATMContext *ctx, uint8_t *buf, int size); int latmenc_write_packet(LATMContext *ctx, uint8_t *data, int size, uint8_t *extradata, int extradata_size); #endif /* AVCODEC_LATMENC_H */ + diff --git a/libeplayer3-arm/external/ffmpeg/put_bits.h b/libeplayer3-arm/external/ffmpeg/put_bits.h index f99cfac..40cc722 100644 --- a/libeplayer3-arm/external/ffmpeg/put_bits.h +++ b/libeplayer3-arm/external/ffmpeg/put_bits.h @@ -54,6 +54,7 @@ static inline void init_put_bits(PutBitContext *s, uint8_t *buffer, buffer_size = 0; buffer = NULL; } + s->size_in_bits = 8 * buffer_size; s->buf = buffer; s->buf_end = s->buf + buffer_size; @@ -73,6 +74,7 @@ static inline void rebase_put_bits(PutBitContext *s, uint8_t *buffer, int buffer_size) { av_assert0(8 * buffer_size > s->size_in_bits); + s->buf_end = buffer + buffer_size; s->buf_ptr = buffer + (s->buf_ptr - s->buf); s->buf = buffer; @@ -154,9 +156,12 @@ static inline void put_bits(PutBitContext *s, int n, unsigned int value) { unsigned int bit_buf; int bit_left; + av_assert2(n <= 31 && value < (1U << n)); + bit_buf = s->bit_buf; bit_left = s->bit_left; + /* XXX: optimize */ #ifdef BITSTREAM_WRITER_LE bit_buf |= value << (32 - bit_left); @@ -200,6 +205,7 @@ static inline void put_bits(PutBitContext *s, int n, unsigned int value) bit_buf = value; } #endif + s->bit_buf = bit_buf; s->bit_left = bit_left; } @@ -207,6 +213,7 @@ static inline void put_bits(PutBitContext *s, int n, unsigned int value) static inline void put_sbits(PutBitContext *pb, int n, int32_t value) { av_assert2(n >= 0 && n <= 31); + put_bits(pb, n, av_mod_uintp2(value, n)); } diff --git a/libeplayer3-arm/external/ffmpeg/src/bitstream.c b/libeplayer3-arm/external/ffmpeg/src/bitstream.c index 8c0f795..c992273 100644 --- a/libeplayer3-arm/external/ffmpeg/src/bitstream.c +++ b/libeplayer3-arm/external/ffmpeg/src/bitstream.c @@ -31,6 +31,7 @@ #include #include + void avpriv_align_put_bits(PutBitContext *s) { put_bits(s, s->bit_left & 7, 0); @@ -52,9 +53,12 @@ void avpriv_copy_bits(PutBitContext *pb, const uint8_t *src, int length) int words = length >> 4; int bits = length & 15; int i; + if (length == 0) return; + av_assert0(length <= put_bits_left(pb)); + if (words < 16 || put_bits_count(pb) & 7) { for (i = 0; i < words; i++) @@ -68,5 +72,7 @@ void avpriv_copy_bits(PutBitContext *pb, const uint8_t *src, int length) memcpy(put_bits_ptr(pb), src + i, 2 * words - i); skip_put_bytes(pb, 2 * words - i); } + put_bits(pb, bits, AV_RB16(src + 2 * words) >> (16 - bits)); } + diff --git a/libeplayer3-arm/external/ffmpeg/src/latmenc.c b/libeplayer3-arm/external/ffmpeg/src/latmenc.c index 86a11f4..9c13c32 100644 --- a/libeplayer3-arm/external/ffmpeg/src/latmenc.c +++ b/libeplayer3-arm/external/ffmpeg/src/latmenc.c @@ -38,9 +38,11 @@ #define latmenc_err(fmt, x...) #endif + int latmenc_decode_extradata(LATMContext *ctx, uint8_t *buf, int size) { MPEG4AudioConfig m4ac; + if (size > MAX_EXTRADATA_SIZE) { latmenc_err("Extradata is larger than currently supported.\n"); @@ -49,6 +51,7 @@ int latmenc_decode_extradata(LATMContext *ctx, uint8_t *buf, int size) ctx->off = avpriv_mpeg4audio_get_config(&m4ac, buf, size * 8, 1); if (ctx->off < 0) return ctx->off; + if (ctx->object_type == AOT_ALS && (ctx->off & 7)) { // as long as avpriv_mpeg4audio_get_config works correctly this is impossible @@ -56,6 +59,7 @@ int latmenc_decode_extradata(LATMContext *ctx, uint8_t *buf, int size) return AVERROR_INVALIDDATA; } /* FIXME: are any formats not allowed in LATM? */ + if (m4ac.object_type > AOT_SBR && m4ac.object_type != AOT_ALS) { latmenc_err("Muxing MPEG-4 AOT %d in LATM is not supported\n", m4ac.object_type); @@ -63,14 +67,17 @@ int latmenc_decode_extradata(LATMContext *ctx, uint8_t *buf, int size) } ctx->channel_conf = m4ac.chan_config; ctx->object_type = m4ac.object_type; + return 0; } static void latmenc_write_frame_header(LATMContext *ctx, uint8_t *extradata, int extradata_size, PutBitContext *bs) { int header_size; + /* AudioMuxElement */ put_bits(bs, 1, !!ctx->counter); + if (!ctx->counter) { /* StreamMuxConfig */ @@ -79,6 +86,7 @@ static void latmenc_write_frame_header(LATMContext *ctx, uint8_t *extradata, int put_bits(bs, 6, 0); /* numSubFrames */ put_bits(bs, 4, 0); /* numProgram */ put_bits(bs, 3, 0); /* numLayer */ + /* AudioSpecificConfig */ if (ctx->object_type == AOT_ALS) { @@ -90,6 +98,7 @@ static void latmenc_write_frame_header(LATMContext *ctx, uint8_t *extradata, int // + 3 assumes not scalable and dependsOnCoreCoder == 0, // see decode_ga_specific_config in libavcodec/aacdec.c avpriv_copy_bits(bs, extradata, ctx->off + 3); + if (!ctx->channel_conf) { GetBitContext gb; @@ -99,11 +108,14 @@ static void latmenc_write_frame_header(LATMContext *ctx, uint8_t *extradata, int avpriv_copy_pce_data(bs, &gb); } } + put_bits(bs, 3, 0); /* frameLengthType */ put_bits(bs, 8, 0xff); /* latmBufferFullness */ + put_bits(bs, 1, 0); /* otherDataPresent */ put_bits(bs, 1, 0); /* crcCheckPresent */ } + ctx->counter++; ctx->counter %= ctx->mod; } @@ -112,15 +124,22 @@ int latmenc_write_packet(LATMContext *ctx, uint8_t *data, int size, uint8_t *ext { PutBitContext bs; int i, len; + if (size > 0x1fff) goto too_large; + init_put_bits(&bs, ctx->buffer, size + 1024 + MAX_EXTRADATA_SIZE); + latmenc_write_frame_header(ctx, extradata, extradata_size, &bs); + /* PayloadLengthInfo() */ for (i = 0; i <= size - 255; i += 255) put_bits(&bs, 8, 255); + put_bits(&bs, 8, size - i); + /* The LATM payload is written unaligned */ + /* PayloadMux() */ if (size && (data[0] & 0xe1) == 0x81) { @@ -137,17 +156,23 @@ int latmenc_write_packet(LATMContext *ctx, uint8_t *data, int size, uint8_t *ext } else avpriv_copy_bits(&bs, data, 8 * size); + avpriv_align_put_bits(&bs); flush_put_bits(&bs); + len = put_bits_count(&bs) >> 3; + if (len > 0x1fff) goto too_large; + memcpy(ctx->loas_header, "\x56\xe0\x00", 3); ctx->loas_header[1] |= (len >> 8) & 0x1f; ctx->loas_header[2] |= len & 0xff; ctx->len = len; return 0; + too_large: latmenc_err("LATM packet size larger than maximum size 0x1fff\n"); return AVERROR_INVALIDDATA; } + diff --git a/libeplayer3-arm/external/ffmpeg/src/mpeg4audio.c b/libeplayer3-arm/external/ffmpeg/src/mpeg4audio.c index f43a568..934dc18 100644 --- a/libeplayer3-arm/external/ffmpeg/src/mpeg4audio.c +++ b/libeplayer3-arm/external/ffmpeg/src/mpeg4audio.c @@ -34,16 +34,21 @@ static int parse_config_ALS(GetBitContext *gb, MPEG4AudioConfig *c) { if (get_bits_left(gb) < 112) return -1; + if (get_bits_long(gb, 32) != MKBETAG('A', 'L', 'S', '\0')) return -1; + // override AudioSpecificConfig channel configuration and sample rate // which are buggy in old ALS conformance files c->sample_rate = get_bits_long(gb, 32); + // skip number of samples skip_bits_long(gb, 32); + // read number of channels c->chan_config = 0; c->channels = get_bits(gb, 16) + 1; + return 0; } @@ -79,11 +84,14 @@ int avpriv_mpeg4audio_get_config(MPEG4AudioConfig *c, const uint8_t *buf, { GetBitContext gb; int specific_config_bitindex, ret; + if (bit_size <= 0) return AVERROR_INVALIDDATA; + ret = init_get_bits(&gb, buf, bit_size); if (ret < 0) return ret; + c->object_type = get_object_type(&gb); c->sample_rate = get_sample_rate(&gb, &c->sampling_index); c->chan_config = get_bits(&gb, 4); @@ -110,15 +118,19 @@ int avpriv_mpeg4audio_get_config(MPEG4AudioConfig *c, const uint8_t *buf, c->ext_sample_rate = 0; } specific_config_bitindex = get_bits_count(&gb); + if (c->object_type == AOT_ALS) { skip_bits(&gb, 5); if (show_bits_long(&gb, 24) != MKBETAG('\0', 'A', 'L', 'S')) skip_bits_long(&gb, 24); + specific_config_bitindex = get_bits_count(&gb); + if (parse_config_ALS(&gb, c)) return -1; } + if (c->ext_object_type != AOT_SBR && sync_extension) { while (get_bits_left(&gb) > 15) @@ -141,12 +153,14 @@ int avpriv_mpeg4audio_get_config(MPEG4AudioConfig *c, const uint8_t *buf, get_bits1(&gb); // skip 1 bit } } + //PS requires SBR if (!c->sbr) c->ps = 0; //Limit implicit PS to the HE-AACv2 Profile if ((c->ps == -1 && c->object_type != AOT_AAC_LC) || c->channels & ~0x01) c->ps = 0; + return specific_config_bitindex; } @@ -163,6 +177,7 @@ int avpriv_copy_pce_data(PutBitContext *pb, GetBitContext *gb) { int five_bit_ch, four_bit_ch, comment_size, bits; int offset = put_bits_count(pb); + copy_bits(pb, gb, 10); //Tag, Object Type, Frequency five_bit_ch = copy_bits(pb, gb, 4); //Front five_bit_ch += copy_bits(pb, gb, 4); //Side @@ -185,5 +200,6 @@ int avpriv_copy_pce_data(PutBitContext *pb, GetBitContext *gb) comment_size = copy_bits(pb, gb, 8); for (; comment_size > 0; comment_size--) copy_bits(pb, gb, 8); + return put_bits_count(pb) - offset; } diff --git a/libeplayer3-arm/external/flv2mpeg4/src/bitreader.h b/libeplayer3-arm/external/flv2mpeg4/src/bitreader.h index 4b3d2c9..d375839 100644 --- a/libeplayer3-arm/external/flv2mpeg4/src/bitreader.h +++ b/libeplayer3-arm/external/flv2mpeg4/src/bitreader.h @@ -56,6 +56,7 @@ static uint32 get_u24(BR *p) uint32 a = get_u8(p); uint32 b = get_u8(p); uint32 c = get_u8(p); + return (a << 16) | (b << 8) | c; } @@ -65,6 +66,7 @@ static uint32 get_u32(BR *p) uint32 b = get_u8(p); uint32 c = get_u8(p); uint32 d = get_u8(p); + return (a << 24) | (b << 16) | (c << 8) | d; } @@ -82,10 +84,12 @@ static uint32 show_bits(BR *p, uint32 bits) { const uint8 *pp; uint32 tmp; + pp = p->buf + p->read; tmp = (pp[0] << 24) | (pp[1] << 16) | (pp[2] << 8) | (pp[3]); tmp <<= p->bitoffset; tmp >>= 32 - bits; + return tmp; } @@ -93,10 +97,12 @@ static int32 show_sbits(BR *p, uint32 bits) { const uint8 *pp; int32 tmp; + pp = p->buf + p->read; tmp = (pp[0] << 24) | (pp[1] << 16) | (pp[2] << 8) | (pp[3]); tmp <<= p->bitoffset; tmp >>= 32 - bits; + return tmp; } @@ -150,14 +156,17 @@ static int __inline get_vlc(BR *br, const VLCtab *table, int bits, int max_depth index = show_bits(br, bits); code = table[index].code; n = table[index].n; + if (max_depth > 1 && n < 0) { flash_bits(br, bits); nb_bits = -n; + index = show_bits(br, nb_bits) + code; code = table[index].code; n = table[index].n; } + flash_bits(br, n); return code; } diff --git a/libeplayer3-arm/external/flv2mpeg4/src/bitwriter.h b/libeplayer3-arm/external/flv2mpeg4/src/bitwriter.h index 3e76f36..ead9639 100644 --- a/libeplayer3-arm/external/flv2mpeg4/src/bitwriter.h +++ b/libeplayer3-arm/external/flv2mpeg4/src/bitwriter.h @@ -57,12 +57,14 @@ static void __inline init_bw(BW *p, uint8 *buf, uint32 size) static void __inline forword_bits(BW *p, uint32 bits) { p->bitoffset += bits; + if (p->bitoffset >= 32) { p->buf[p->pos++] = (p->tmp >> 24) & 0xff; p->buf[p->pos++] = (p->tmp >> 16) & 0xff; p->buf[p->pos++] = (p->tmp >> 8) & 0xff; p->buf[p->pos++] = (p->tmp >> 0) & 0xff; + p->tmp = 0; p->bitoffset -= 32; } @@ -71,6 +73,7 @@ static void __inline forword_bits(BW *p, uint32 bits) static void __inline put_bits(BW *p, uint32 bits, uint32 value) { uint32 shift = 32 - p->bitoffset - bits; + if (shift <= 32) { p->tmp |= value << shift; @@ -81,6 +84,7 @@ static void __inline put_bits(BW *p, uint32 bits, uint32 value) shift = bits - (32 - p->bitoffset); p->tmp |= value >> shift; forword_bits(p, bits - shift); + p->tmp |= value << (32 - shift); forword_bits(p, shift); } @@ -98,6 +102,7 @@ static void __inline pad_to_boundary(BW *p) static void __inline flash_bw(BW *p) { pad_to_boundary(p); + switch (p->bitoffset) { case 0: // nothing to do @@ -118,6 +123,7 @@ static void __inline flash_bw(BW *p) // fprintf(stderr, "flash_bw error!(%d)\n", p->bitoffset); break; } + p->tmp = 0; p->bitoffset = 0; } @@ -136,6 +142,7 @@ static void __inline put_vlcdec(BW *bw, VLCDEC *vlcdec) static void __inline m4v_stuffing(BW *p) { int length; + put_bits(p, 1, 0); length = (- p->bitoffset) & 7; if (length) put_bits(p, length, (1 << length) - 1); diff --git a/libeplayer3-arm/external/flv2mpeg4/src/dcprediction.c b/libeplayer3-arm/external/flv2mpeg4/src/dcprediction.c index 90e350f..dfe2261 100644 --- a/libeplayer3-arm/external/flv2mpeg4/src/dcprediction.c +++ b/libeplayer3-arm/external/flv2mpeg4/src/dcprediction.c @@ -25,6 +25,7 @@ #include "dcprediction.h" + // M4V ADDED static const uint8 mpeg4_y_dc_scale_table[32] = { @@ -43,10 +44,12 @@ static int __inline get_pred(int *dc_cur, int stride, int scale) { /* B C A X */ + int A = dc_cur[-1]; int B = dc_cur[-1 - stride]; int C = dc_cur[-stride]; int pred; + if (abs(A - B) < abs(B - C)) { pred = C; @@ -55,6 +58,7 @@ static int __inline get_pred(int *dc_cur, int stride, int scale) { pred = A; } + return (pred + (scale >> 1)) / scale; } @@ -68,6 +72,7 @@ static void __inline set_dc_to_dc_cur(int *dc_cur, int level, int scale) else level = 2047; } + dc_cur[0] = level; } @@ -118,6 +123,7 @@ int dcpred_for_enc(M4V_DCPRED *p, int n, int level) int *dc_cur = p->dc_cur[n]; int scale = get_scale(p, n); int pred = get_pred(dc_cur, p->stride[n], scale); + set_dc_to_dc_cur(dc_cur, level, scale); return level - pred; } @@ -127,6 +133,7 @@ int dcpred_for_dec(M4V_DCPRED *p, int n, int level) int *dc_cur = p->dc_cur[n]; int scale = get_scale(p, n); int pred = get_pred(dc_cur, p->stride[n], scale); + level += pred; set_dc_to_dc_cur(dc_cur, level, scale); return level; @@ -137,6 +144,7 @@ static void init_plane(M4V_DCPRED *pred, int n) { int x, len = pred->stride[n] * pred->height[n]; int *p = pred->_dc[n]; + for (x = 0; x < len; x++) { p[x] = 1024; @@ -156,16 +164,20 @@ void alloc_dcpred(M4V_DCPRED *pred, int mb_width, int mb_height) const int h2 = mb_height * 2 + 1; const int w = mb_width + 1; const int h = mb_height + 1; + pred->_dc[0] = pred->_dc[1] = pred->_dc[2] = pred->_dc[3] = (int *)malloc(sizeof(int) * w2 * h2); pred->_dc[4] = (int *)malloc(sizeof(int) * w * h); pred->_dc[5] = (int *)malloc(sizeof(int) * w * h); + pred->dc[0] = pred->dc[1] = pred->dc[2] = pred->dc[3] = pred->_dc[0] + w2 + 1; pred->dc[4] = pred->_dc[4] + w + 1; pred->dc[5] = pred->_dc[5] + w + 1; + pred->stride[0] = pred->stride[1] = pred->stride[2] = pred->stride[3] = w2; pred->height[0] = pred->height[1] = pred->height[2] = pred->height[3] = h2; pred->stride[4] = pred->stride[5] = w; pred->height[4] = pred->height[5] = h; + pred->block_offset[0] = 0; pred->block_offset[1] = 1; pred->block_offset[2] = w2; diff --git a/libeplayer3-arm/external/flv2mpeg4/src/dcprediction.h b/libeplayer3-arm/external/flv2mpeg4/src/dcprediction.h index 456a685..936b741 100644 --- a/libeplayer3-arm/external/flv2mpeg4/src/dcprediction.h +++ b/libeplayer3-arm/external/flv2mpeg4/src/dcprediction.h @@ -40,6 +40,7 @@ typedef struct _M4V_DCPRED int y_dc_scale; int c_dc_scale; + } M4V_DCPRED; ////////////////////////////////////////////////////////////////////////////////////////////////////////////////// diff --git a/libeplayer3-arm/external/flv2mpeg4/src/flv.h b/libeplayer3-arm/external/flv2mpeg4/src/flv.h index 22874b3..e2f08ce 100644 --- a/libeplayer3-arm/external/flv2mpeg4/src/flv.h +++ b/libeplayer3-arm/external/flv2mpeg4/src/flv.h @@ -65,6 +65,7 @@ typedef struct _PICTURE int width; int height; + #define FLV_I_TYPE 0 #define FLV_P_TYPE 1 @@ -156,4 +157,5 @@ static const int8 rl_inter_run[102] = static const int rl_inter_n = 102; static const int rl_inter_last = 58; + #endif // FLV_H diff --git a/libeplayer3-arm/external/flv2mpeg4/src/flv2mpeg4.c b/libeplayer3-arm/external/flv2mpeg4/src/flv2mpeg4.c index 3e22d98..36049dd 100644 --- a/libeplayer3-arm/external/flv2mpeg4/src/flv2mpeg4.c +++ b/libeplayer3-arm/external/flv2mpeg4/src/flv2mpeg4.c @@ -41,6 +41,7 @@ typedef struct _CONVCTX M4V_VOL vol; } CONVCTX; + typedef struct { uint8 *out_buf; @@ -64,6 +65,7 @@ static const uint8 ff_mpeg4_c_dc_scale_table[32] = 0, 8, 8, 8, 8, 9, 9, 10, 10, 11, 11, 12, 12, 13, 13, 14, 14, 15, 15, 16, 16, 17, 17, 18, 18, 19, 20, 21, 22, 23, 24, 25 }; + static void copy_vol(PICTURE *flv_pic, M4V_VOL *vol) { vol->width = flv_pic->width; @@ -74,9 +76,11 @@ static void copy_vol(PICTURE *flv_pic, M4V_VOL *vol) static void copy_vop(PICTURE *flv_pic, M4V_VOP *vop, CONVCTX *c) { vop->qscale = flv_pic->qscale; + vop->time = c->frame % 30; vop->icount = (c->icounter + 29) / 30; vop->intra_dc_threshold = 99; + if (flv_pic->picture_type == FLV_I_TYPE) { vop->picture_type = M4V_I_TYPE; @@ -91,13 +95,16 @@ static void copy_vop(PICTURE *flv_pic, M4V_VOP *vop, CONVCTX *c) static void copy_microblock(MICROBLOCK *flv_mb, M4V_MICROBLOCK *m4v_mb) { int i; + m4v_mb->dquant = flv_mb->dquant; memcpy(m4v_mb->block, flv_mb->block, sizeof(m4v_mb->block)); // !!!!!!! m4v_mb->intra = flv_mb->intra; m4v_mb->skip = flv_mb->skip; m4v_mb->mv_type = flv_mb->mv_type; + memcpy(m4v_mb->mv_x, flv_mb->mv_x, sizeof(m4v_mb->mv_x)); // !!!!!! memcpy(m4v_mb->mv_y, flv_mb->mv_y, sizeof(m4v_mb->mv_y)); // !!!!!! + // dc rescale if (m4v_mb->intra) { @@ -106,6 +113,7 @@ static void copy_microblock(MICROBLOCK *flv_mb, M4V_MICROBLOCK *m4v_mb) m4v_mb->block[i].block[0] *= 8; m4v_mb->block[i].block[0] /= ff_mpeg4_y_dc_scale_table[m4v_mb->qscale]; } + for (i = 4; i < 6; i++) { m4v_mb->block[i].block[0] *= 8; @@ -126,7 +134,9 @@ static int write_pad_not_coded_frames(flv2mpeg4_CTX *pub_ctx, CONVCTX *c, BW *bw vop.icount = (c->icounter + 29) / 30; m4v_encode_vop_header(bw, &vop, VOL_TIME_BITS, 1); m4v_stuffing(bw); + flash_bw(bw); + // write frame if (pub_ctx->write_packet_cb(pub_ctx->usr_data, 0, @@ -136,10 +146,13 @@ static int write_pad_not_coded_frames(flv2mpeg4_CTX *pub_ctx, CONVCTX *c, BW *bw { return -1; } + clear_bw(bw); + c->frame++; c->icounter++; } + return 0; } @@ -151,9 +164,12 @@ static int write_m4v_picture_frame(flv2mpeg4_CTX *pub_ctx, CONVCTX *c, BR *br, B int x, y; int mb_width = (flvpic->width + 15) / 16; int mb_height = (flvpic->height + 15) / 16; + memset(&vop, 0, sizeof(vop)); + copy_vop(flvpic, &vop, c); m4v_encode_vop_header(bw, &vop, VOL_TIME_BITS, 0); + // transcode flv to mpeg4 for (y = 0; y < mb_height; y++) { @@ -161,6 +177,7 @@ static int write_m4v_picture_frame(flv2mpeg4_CTX *pub_ctx, CONVCTX *c, BR *br, B { memset(&mb, 0, sizeof(mb)); memset(&m4v_mb, 0, sizeof(m4v_mb)); + if (vop.picture_type == M4V_I_TYPE) { mb.intra = 1; @@ -180,8 +197,10 @@ static int write_m4v_picture_frame(flv2mpeg4_CTX *pub_ctx, CONVCTX *c, BR *br, B } } } + m4v_stuffing(bw); flash_bw(bw); + // write frame if (pub_ctx->write_packet_cb(pub_ctx->usr_data, vop.picture_type == M4V_I_TYPE, @@ -191,19 +210,25 @@ static int write_m4v_picture_frame(flv2mpeg4_CTX *pub_ctx, CONVCTX *c, BR *br, B { return -1; } + c->frame++; c->icounter++; + return 0; } static int write_m4v_frame(flv2mpeg4_CTX *pub_ctx, CONVCTX *c, BR *br, BW *bw, uint32 time) { PICTURE picture; + memset(&picture, 0, sizeof(picture)); init_dcpred(&c->vol.dcpred); + if (decode_picture_header(br, &picture) < 0) return -1; if (c->width != picture.width || c->height != picture.height) return -1; //size changed.. + copy_vol(&picture, &c->vol); + if (picture.picture_type == FLV_I_TYPE) { c->icounter = 0; @@ -212,10 +237,12 @@ static int write_m4v_frame(flv2mpeg4_CTX *pub_ctx, CONVCTX *c, BR *br, BW *bw, u { if (write_pad_not_coded_frames(pub_ctx, c, bw, time) < 0) return -1; } + if (write_m4v_picture_frame(pub_ctx, c, br, bw, &picture, time) < 0) { return -1; } + return 0; } @@ -235,16 +262,23 @@ int flv2mpeg4_prepare_extra_data(flv2mpeg4_CTX *ctx) CTX *p = ctx->priv; BW bw; CONVCTX *c = &(p->conv); + M4V_VOP vop; memset(&vop, 0, sizeof(vop)); + init_bw(&bw, p->out_buf, PACKETBUFFER_SIZE); + c->vol.width = c->width; c->vol.height = c->height; c->vol.time_bits = VOL_TIME_BITS; // 0-31 + m4v_encode_m4v_header(&bw, &c->vol, 0); + m4v_stuffing(&bw); flash_bw(&bw); + alloc_dcpred(&c->vol.dcpred, (c->width + 15) / 16, (c->height + 15) / 16); + return ctx->write_extradata_cb(ctx->usr_data, c->width, c->height, 200 * 1000, bw.buf, bw.pos); } @@ -265,20 +299,26 @@ flv2mpeg4_CTX *flv2mpeg4_init_ctx(void *priv_data, int width, int height, flv2mp pub_ctx->priv = malloc(sizeof(CTX)); memset(pub_ctx->priv, 0x0, sizeof(CTX)); CTX *ctx = pub_ctx->priv; + ctx->conv.width = width; ctx->conv.height = height; ctx->out_buf = malloc(PACKETBUFFER_SIZE); memset(ctx->out_buf, 0x0, PACKETBUFFER_SIZE); memset(&(ctx->vol), 0x0, sizeof(ctx->vol)); + return pub_ctx; } void flv2mpeg4_release_ctx(flv2mpeg4_CTX **pub_ctx) { CTX *ctx = (*pub_ctx)->priv; + free_dcpred(&ctx->conv.vol.dcpred); free(ctx->out_buf); free(ctx); free(*pub_ctx); *pub_ctx = NULL; } + + + diff --git a/libeplayer3-arm/external/flv2mpeg4/src/flvdecoder.c b/libeplayer3-arm/external/flv2mpeg4/src/flvdecoder.c index edfba70..9d84a31 100644 --- a/libeplayer3-arm/external/flv2mpeg4/src/flvdecoder.c +++ b/libeplayer3-arm/external/flv2mpeg4/src/flvdecoder.c @@ -38,6 +38,7 @@ static const uint8 zig_zag_scan[64] = 58, 59, 52, 45, 38, 31, 39, 46, 53, 60, 61, 54, 47, 55, 62, 63 }; + static const VLCtab vlc_table_intra_MCBPC[] = //: table_size=72 table_allocated=128 bits=6 { {64, -3}, @@ -127,6 +128,7 @@ static const VLCtab vlc_table_rl_inter[] = //: table_size=554 table_allocated=10 {100, 3}, {101, 3}, {8, 1}, {7, 1} }; + static const VLCtab vlc_table_mv[] = //mv_vlc: table_size=538 table_allocated=1024 bits=9 { {512, -3}, {520, -2}, {524, -1}, {526, -1}, {528, -1}, {530, -1}, {532, -1}, {534, -1}, {536, -1}, {10, 9}, @@ -181,6 +183,7 @@ static int __inline decode_DC(BR *p) return -1; } if (level == 255) level = 128; + // printf("DC: %d\n", level); return level; } @@ -188,6 +191,7 @@ static int __inline decode_DC(BR *p) static int __inline decode_AC(BR *p, BLOCK *block, int escape_type, int i) { int code, run, level, last, sign; + while (1) { code = get_vlc(p, vlc_table_rl_inter, 9, 2); @@ -196,12 +200,14 @@ static int __inline decode_AC(BR *p, BLOCK *block, int escape_type, int i) printf("invalid Huffman code in getblock()\n"); return -1; } + if (code == rl_inter_n) { //escape if (escape_type == 1) { int is11bit = get_bits(p, 1); + last = get_bits(p, 1); run = get_bits(p, 6); if (is11bit) @@ -227,9 +233,11 @@ static int __inline decode_AC(BR *p, BLOCK *block, int escape_type, int i) run = rl_inter_run[code]; level = rl_inter_level[code]; last = code >= rl_inter_last; + sign = get_bits(p, 1); if (sign) level = -level; } + i += run; if (i >= 64) { @@ -240,6 +248,7 @@ static int __inline decode_AC(BR *p, BLOCK *block, int escape_type, int i) if (last) break; i++; } + block->last_index = i; return 0; } @@ -252,12 +261,15 @@ static int __inline decode_intra_block(BR *p, BLOCK *block, int escape_type, int printf("dc error.\n"); return -1; } + block->block[0] = level; block->last_index = 0; + if (!coded) { return 0; } + if (decode_AC(p, block, escape_type, 1) < 0) return -1; return 0; } @@ -265,10 +277,12 @@ static int __inline decode_intra_block(BR *p, BLOCK *block, int escape_type, int static int __inline decode_inter_block(BR *p, BLOCK *block, int escape_type, int coded) { block->last_index = -1; + if (!coded) { return 0; } + if (decode_AC(p, block, escape_type, 0) < 0) return -1; return 0; } @@ -298,6 +312,7 @@ static int __inline get_inter_MCBPC(BR *br) if (cbpc < 0) return -1; } while (cbpc == 20); + return cbpc; } @@ -316,11 +331,14 @@ static int __inline decode_motion(BR *br, VLCDEC *vlcdec) { int tmp; int code = get_vlcdec(br, vlc_table_mv, 9, 2, vlcdec); + vlcdec->bits_ex = 0; + if (code == 0) return 0; if (code < 0) return -1; + tmp = get_bits(br, 1); /* vlcdec->value |= (tmp << vlcdec->bits); @@ -331,6 +349,7 @@ static int __inline decode_motion(BR *br, VLCDEC *vlcdec) */ vlcdec->bits_ex = 1; vlcdec->value_ex = tmp; + return 0; } @@ -338,23 +357,28 @@ static int __inline decode_intra_mb_internal(BR *p, MICROBLOCK *mb, int escape_t { int cbpy, cbp; int i; + cbpy = get_cbpy(p); if (cbpy < 0) { printf("cbpy error\n"); return -1; } + cbp = (cbpc & 3) | (cbpy << 2); + if (dquant) { mb->dquant = decode_dquant(p); qscale += mb->dquant; } + for (i = 0; i < 6; i++) { if (decode_intra_block(p, &mb->block[i], escape_type, cbp & 32) != 0) return -1; cbp += cbp; } + return 0; } @@ -362,19 +386,23 @@ static int __inline decode_inter_mb_internal(BR *p, MICROBLOCK *mb, int escape_t { int cbpy, cbp; int i; + cbpy = get_cbpy(p); if (cbpy < 0) { printf("cbpy error\n"); return -1; } + cbpy ^= 0xF; cbp = (cbpc & 3) | (cbpy << 2); + if (dquant) { mb->dquant = decode_dquant(p); qscale += mb->dquant; } + if ((cbpc & 16) == 0) { // 16x16 motion prediction @@ -392,11 +420,13 @@ static int __inline decode_inter_mb_internal(BR *p, MICROBLOCK *mb, int escape_t } mb->mv_type = MV_TYPE_8X8; } + for (i = 0; i < 6; i++) { if (decode_inter_block(p, &mb->block[i], escape_type, cbp & 32) != 0) return -1; cbp += cbp; } + return 0; } @@ -410,18 +440,22 @@ int decode_I_mb(BR *p, MICROBLOCK *mb, int escape_type, int qscale) printf("intra_MCBPC error\n"); return -1; } + dquant = cbpc & 4; decode_intra_mb_internal(p, mb, escape_type, qscale, cbpc, dquant); + if (show_bits(p, 16) == 0) { // printf("slice end???\n"); } + return 0; } int decode_P_mb(BR *p, MICROBLOCK *mb, int escape_type, int qscale) { int cbpc = get_inter_MCBPC(p); + if (cbpc == -1) { printf("inter_MCBPC error\n"); @@ -435,6 +469,7 @@ int decode_P_mb(BR *p, MICROBLOCK *mb, int escape_type, int qscale) { int dquant = cbpc & 8; mb->skip = 0; + if ((cbpc & 4) != 0) { mb->intra = 1; @@ -446,31 +481,38 @@ int decode_P_mb(BR *p, MICROBLOCK *mb, int escape_type, int qscale) decode_inter_mb_internal(p, mb, escape_type, qscale, cbpc, dquant); } } + if (show_bits(p, 16) == 0) { // printf("slice end???\n"); } + return 0; } int decode_picture_header(BR *p, PICTURE *picture) { int tmp, width = 0, height = 0; + if (get_bits(p, 17) != 1) { fprintf(stderr, "start code error\n"); return -1; } + tmp = get_bits(p, 5); if (tmp != 0 && tmp != 1) { fprintf(stderr, "picture format error\n"); return -1; } + picture->escape_type = tmp; picture->frame_number = get_bits(p, 8); + // printf("picture_format: %d\n", tmp); // printf("picture_number: %d\n", get_bits(p, 8)); + tmp = get_bits(p, 3); switch (tmp) { @@ -501,21 +543,27 @@ int decode_picture_header(BR *p, PICTURE *picture) fprintf(stderr, "size error\n"); return -1; } + picture->width = width; picture->height = height; // printf("width: %d height: %d\n", width, height); + picture->picture_type = get_bits(p, 2); // printf("picture_type: %d\n", tmp); + tmp = get_bits(p, 1); // printf("deblocking flag: %d\n", tmp); + tmp = get_bits(p, 5); picture->qscale = tmp; // printf("qscale: %d\n", tmp); + // PEI while (get_bits(p, 1) != 0) { flash_bits(p, 8); } + // dump_marker(0, "dd header end"); return 0; } diff --git a/libeplayer3-arm/external/flv2mpeg4/src/m4v.h b/libeplayer3-arm/external/flv2mpeg4/src/m4v.h index eddb7dd..df5fd2e 100644 --- a/libeplayer3-arm/external/flv2mpeg4/src/m4v.h +++ b/libeplayer3-arm/external/flv2mpeg4/src/m4v.h @@ -134,4 +134,6 @@ static const uint8 alternate_vertical_scan[64] = 38, 46, 54, 62, 39, 47, 55, 63, }; + #endif // M4V_H + diff --git a/libeplayer3-arm/external/flv2mpeg4/src/m4vencode.c b/libeplayer3-arm/external/flv2mpeg4/src/m4vencode.c index 7860d83..139a91b 100644 --- a/libeplayer3-arm/external/flv2mpeg4/src/m4vencode.c +++ b/libeplayer3-arm/external/flv2mpeg4/src/m4vencode.c @@ -63,6 +63,7 @@ static const uint32 vlce_inter_MCBPC_bits[28] = static void __inline encode_DC(BW *p, int level, int n) { if (level < -255 || level > 255) printf("dc overflow\n"); + #if 1 level += 256; if (n < 4) @@ -74,6 +75,7 @@ static void __inline encode_DC(BW *p, int level, int n) put_bits(p, uni_DCtab_chrom_len[level], uni_DCtab_chrom_bits[level]); } #else + int size, v; /* find number of bits */ size = 0; @@ -83,6 +85,7 @@ static void __inline encode_DC(BW *p, int level, int n) v >>= 1; size++; } + if (n < 4) { /* luminance */ @@ -93,6 +96,7 @@ static void __inline encode_DC(BW *p, int level, int n) /* chrominance */ put_bits(p, DCtab_chrom[size][1], DCtab_chrom[size][0]); } + /* encode remaining bits */ if (size > 0) { @@ -102,7 +106,9 @@ static void __inline encode_DC(BW *p, int level, int n) if (size > 8) put_bits(p, 1, 1); } + #endif + } static void __inline encode_escape_3(BW *p, int last, int run, int level) @@ -129,10 +135,13 @@ static void __inline encode_AC(BW *p, M4V_BLOCK *block, int intra) int i = intra; int last_index = block->last_index; int last_non_zero = i - 1; + const uint8 *scan_table = zig_zag_scan; // !!! + #if 1 const uint8 *len_tab; const uint32 *bits_tab; + if (intra) { len_tab = uni_mpeg4_intra_rl_len; @@ -143,6 +152,7 @@ static void __inline encode_AC(BW *p, M4V_BLOCK *block, int intra) len_tab = uni_mpeg4_inter_rl_len; bits_tab = uni_mpeg4_inter_rl_bits; } + for (; i < last_index; i++) { int level = block->block[scan_table[i]]; @@ -159,9 +169,11 @@ static void __inline encode_AC(BW *p, M4V_BLOCK *block, int intra) { encode_escape_3(p, 0, run, level); } + last_non_zero = i; } } + { int level = block->block[scan_table[i]]; int run = i - last_non_zero - 1; @@ -179,6 +191,7 @@ static void __inline encode_AC(BW *p, M4V_BLOCK *block, int intra) #else const RL *rl; int last, sign, code; + if (intra) { rl = &rl_intra; @@ -187,6 +200,7 @@ static void __inline encode_AC(BW *p, M4V_BLOCK *block, int intra) { rl = &rl_inter; } + for (; i <= last_index; i++) { const int slevel = block->block[scan_table[i]]; @@ -202,6 +216,7 @@ static void __inline encode_AC(BW *p, M4V_BLOCK *block, int intra) sign = 1; level = -level; } + code = get_rl_index(rl, last, run, level); put_bits(p, rl->table_vlc[code][1], rl->table_vlc[code][0]); if (code == rl->n) @@ -210,6 +225,7 @@ static void __inline encode_AC(BW *p, M4V_BLOCK *block, int intra) level1 = level - rl->max_level[run][last]; if (level1 < 1) goto esc2; + code = get_rl_index(rl, last, run, level1); if (code == rl->n) { @@ -255,7 +271,10 @@ esc3: last_non_zero = i; } } + #endif + + } static void __inline encode_intra_block(BW *bw, M4V_BLOCK *block, int n) @@ -293,6 +312,7 @@ static void __inline encode_inter_8x8_MCBPC(BW *bw, int cbpc) put_bits(bw, vlce_inter_MCBPC_bits[cbpc + 16], vlce_inter_MCBPC_code[cbpc + 16]); } + // same as H.263 static void __inline encode_cbpy(BW *bw, int cbpy) { @@ -320,6 +340,7 @@ static void __inline encode_motion(BW *bw, VLCDEC *mv_x, VLCDEC *mv_y) { put_bits(bw, mv_x->bits_ex - 1, mv_x->value_ex >> 1); } + } put_vlcdec(bw, mv_y); if (mv_y->bits_ex) @@ -337,6 +358,7 @@ static void __inline encode_mb_inter_internal(BW *bw, M4V_MICROBLOCK *mb) { int cbp = 0, cbpc, cbpy; int i; + for (i = 0; i < 6; i++) { if (mb->block[i].last_index >= 0) @@ -344,10 +366,13 @@ static void __inline encode_mb_inter_internal(BW *bw, M4V_MICROBLOCK *mb) cbp |= 1 << (5 - i); } } + cbpc = cbp & 3; cbpy = cbp >> 2; cbpy ^= 0xF; + if (mb->dquant) cbpc += 8; + switch (mb->mv_type) { case MV_TYPE_16X16: @@ -366,6 +391,7 @@ static void __inline encode_mb_inter_internal(BW *bw, M4V_MICROBLOCK *mb) } break; } + for (i = 0; i < 6; i++) { encode_inter_block(bw, &mb->block[i]); @@ -376,6 +402,7 @@ static void __inline encode_mb_intra_internal(BW *bw, M4V_MICROBLOCK *mb, int if { int cbp = 0, cbpc, cbpy; int i; + for (i = 0; i < 6; i++) { if (mb->block[i].last_index >= 1) @@ -383,6 +410,7 @@ static void __inline encode_mb_intra_internal(BW *bw, M4V_MICROBLOCK *mb, int if cbp |= 1 << (5 - i); } } + cbpc = cbp & 3; if (iframe) { @@ -394,10 +422,15 @@ static void __inline encode_mb_intra_internal(BW *bw, M4V_MICROBLOCK *mb, int if if (mb->dquant) cbpc += 8; encode_intra_P_MCBPC(bw, cbpc); } + put_bits(bw, 1, 0); // AC Prediction = no + cbpy = cbp >> 2; + encode_cbpy(bw, cbpy); encode_dquant(bw, mb->dquant); + + for (i = 0; i < 6; i++) { encode_intra_block(bw, &mb->block[i], i); @@ -409,15 +442,20 @@ static int __inline encode_vo_header(BW *p) { put_bits(p, 16, 0); put_bits(p, 16, VOS_STARTCODE); + put_bits(p, 8, 1); // *** profile_and_level_indidation + put_bits(p, 16, 0); put_bits(p, 16, VISUAL_OBJECT_STARTCODE); + put_bits(p, 1, 1); put_bits(p, 4, 1); // vo_vel_id put_bits(p, 3, 1); // priority put_bits(p, 4, 1); // visual_object_type = video object put_bits(p, 1, 0); // video signal type = no clue + m4v_stuffing(p); + return 0; } @@ -425,19 +463,28 @@ static int __inline encode_vol_header(BW *p, M4V_VOL *vol) { const int vo_number = 0; const int vol_number = 0; + put_bits(p, 16, 0); put_bits(p, 16, 0x100 + vo_number); + put_bits(p, 16, 0); put_bits(p, 16, 0x120 + vol_number); + put_bits(p, 1, 0); // random_accessible_vol put_bits(p, 8, 1); // video_object_type_indication = Simple Object Type + put_bits(p, 1, 0); //is_object_layer_identifier + put_bits(p, 4, 1); // *** aspect_ratio_info = 1(1:1) + put_bits(p, 1, 0); //vol_control_parameters + put_bits(p, 2, 0); // shape_type put_bits(p, 1, 1); // marker + if (vol->time_bits != 5) return -1; // for vop_time_increment_resolution = 30 put_bits(p, 16, 30); // *** vop_time_increment_resolution = 30 + put_bits(p, 1, 1); // marker put_bits(p, 1, 0); // fixed vop rate = no put_bits(p, 1, 1); // marker @@ -450,10 +497,12 @@ static int __inline encode_vol_header(BW *p, M4V_VOL *vol) put_bits(p, 1, 0); // sprite = disable put_bits(p, 1, 0); // not8bit = false put_bits(p, 1, 0); // quant type = H.263 + put_bits(p, 1, 1); // complexity estimaition disable = true put_bits(p, 1, 1); // resync marker disable = true put_bits(p, 1, 0); // data pertitioning = false put_bits(p, 1, 0); // scalability = false + m4v_stuffing(p); return 0; } @@ -461,14 +510,21 @@ static int __inline encode_vol_header(BW *p, M4V_VOL *vol) static int __inline encode_vop_header(BW *p, M4V_VOP *vop, int time_bits, int vop_not_coded) { // static int time_old = 0; + int time_incr = vop->icount; if (vop->time != 0) time_incr = 0; + put_bits(p, 16, 0); put_bits(p, 16, VOP_STARTCODE); + put_bits(p, 2, vop->picture_type); + + // printf("not_code:%d vop_time: %d\n", vop_not_coded, vop->time); + // printf("pic:%d icount:%d vop_time: %d\n", vop->picture_type, time_incr, vop->time); + /* if (time_old > vop->time) { put_bits(p, 1, 1); @@ -476,54 +532,70 @@ static int __inline encode_vop_header(BW *p, M4V_VOP *vop, int time_bits, int vo time_old = vop->time; */ + // !!!!! while (time_incr--) put_bits(p, 1, 1); put_bits(p, 1, 0); + put_bits(p, 1, 1); // marker put_bits(p, time_bits, vop->time); // time_increment put_bits(p, 1, 1); // marker + if (vop_not_coded) { put_bits(p, 1, 0); // vop coded return 0; } + put_bits(p, 1, 1); // vop coded + if (vop->picture_type == M4V_P_TYPE) { put_bits(p, 1, vop->rounding_type); // rounding type } + put_bits(p, 3, 0); // intra dc VLC threashold + put_bits(p, 5, vop->qscale); // qscale + if (vop->picture_type != M4V_I_TYPE) { put_bits(p, 3, vop->f_code); } + if (vop->picture_type == M4V_B_TYPE) { put_bits(p, 3, vop->b_code); } + return 0; } static __inline int encode_gop_header(BW *bw, uint32 time_ms) { int sec, min, hour; + sec = time_ms / 1000; min = sec / 60; sec %= 60; hour = min / 60; min %= 60; hour %= 24; + put_bits(bw, 16, 0); put_bits(bw, 16, GOP_STARTCODE); + put_bits(bw, 5, hour); put_bits(bw, 6, min); put_bits(bw, 1, 1); put_bits(bw, 6, sec); + put_bits(bw, 1, 0); // closed_gop == NO put_bits(bw, 1, 0); // broken link == NO + printf("GOP %02d:%02d:%02d\n", hour, min, sec); + m4v_stuffing(bw); return 0; } @@ -532,6 +604,7 @@ static int __inline encode_user_header(BW *p) { put_bits(p, 16, 0); put_bits(p, 16, USERDATA_STARTCODE); + put_bits(p, 8, 'v'); put_bits(p, 8, 'i'); put_bits(p, 8, 'x'); @@ -540,6 +613,7 @@ static int __inline encode_user_header(BW *p) put_bits(p, 8, 'n'); put_bits(p, 8, 'e'); put_bits(p, 8, 't'); + m4v_stuffing(p); return 0; } @@ -575,6 +649,7 @@ void m4v_encode_P_mb(BW *bw, M4V_MICROBLOCK *mb) { put_bits(bw, 1, 0); // coded } + if (mb->intra) { encode_mb_intra_internal(bw, mb, 0); @@ -592,6 +667,7 @@ int m4v_encode_I_dcpred(M4V_MICROBLOCK *mb, M4V_DCPRED *dcpred, int mb_x, int mb { dcpred_set_qscale(dcpred, mb->qscale); dcpred_set_pos(dcpred, mb_x, mb_y); + for (n = 0; n < 6; n ++) { int level = dcpred_for_enc(dcpred, n, mb->block[n].block[0]); diff --git a/libeplayer3-arm/include/aac.h b/libeplayer3-arm/include/aac.h index 4455043..33f32fd 100644 --- a/libeplayer3-arm/include/aac.h +++ b/libeplayer3-arm/include/aac.h @@ -29,6 +29,7 @@ static inline int HasADTSHeader(uint8_t *data, int size) { return 1; } + return 0; } diff --git a/libeplayer3-arm/include/bcm_ioctls.h b/libeplayer3-arm/include/bcm_ioctls.h index ef118e5..d52f298 100644 --- a/libeplayer3-arm/include/bcm_ioctls.h +++ b/libeplayer3-arm/include/bcm_ioctls.h @@ -35,6 +35,7 @@ typedef enum CT_VP9 } video_codec_type_t; + typedef enum { STREAMTYPE_UNKNOWN = -1, @@ -56,6 +57,8 @@ typedef enum STREAMTYPE_SPARK = 21, } video_stream_type_t; + + typedef enum { AUDIOTYPE_UNKNOWN = -1, @@ -75,4 +78,8 @@ typedef enum AUDIOTYPE_RAW = 0xf } audio_stream_type_t; + + + #endif /* H_DVB_BCM_H */ + diff --git a/libeplayer3-arm/include/debug.h b/libeplayer3-arm/include/debug.h index 9149895..1740868 100644 --- a/libeplayer3-arm/include/debug.h +++ b/libeplayer3-arm/include/debug.h @@ -6,6 +6,7 @@ static inline void Hexdump(unsigned char *Data, int length) { + int k; for (k = 0; k < length; k++) { @@ -14,6 +15,7 @@ static inline void Hexdump(unsigned char *Data, int length) printf("\n"); } printf("\n"); + } #endif diff --git a/libeplayer3-arm/include/manager.h b/libeplayer3-arm/include/manager.h index 81515bc..baed788 100644 --- a/libeplayer3-arm/include/manager.h +++ b/libeplayer3-arm/include/manager.h @@ -94,6 +94,7 @@ typedef struct TrackDescription_s int32_t aspect_ratio_num; int32_t aspect_ratio_den; int progressive; + } TrackDescription_t; struct Context_s; @@ -104,6 +105,7 @@ typedef struct Manager_s char *Name; int (* Command)(Context_t *, ManagerCmd_t, void *); char **Capabilities; + } Manager_t; typedef struct ManagerHandler_s diff --git a/libeplayer3-arm/include/misc.h b/libeplayer3-arm/include/misc.h index 4934180..f1114b4 100644 --- a/libeplayer3-arm/include/misc.h +++ b/libeplayer3-arm/include/misc.h @@ -56,14 +56,17 @@ static inline char *basename(char *name) { int i = 0; int pos = 0; + while (name[i] != 0) { if (name[i] == '/') pos = i; i++; } + if (name[pos] == '/') pos++; + return name + pos; } @@ -73,6 +76,7 @@ static inline char *dirname(char *name) static char path[100]; uint32_t i = 0; int32_t pos = 0; + while ((name[i] != 0) && (i < sizeof(path))) { if (name[i] == '/') @@ -82,8 +86,10 @@ static inline char *dirname(char *name) path[i] = name[i]; i++; } + path[i] = 0; path[pos] = 0; + return path; } diff --git a/libeplayer3-arm/include/output.h b/libeplayer3-arm/include/output.h index 16a61f1..533e60a 100644 --- a/libeplayer3-arm/include/output.h +++ b/libeplayer3-arm/include/output.h @@ -74,6 +74,7 @@ typedef struct Output_s int32_t (* Command)(Context_t *, OutputCmd_t, void *); int32_t (* Write)(Context_t *, void *); char **Capabilities; + } Output_t; extern Output_t LinuxDvbOutput; diff --git a/libeplayer3-arm/include/pes.h b/libeplayer3-arm/include/pes.h index 2026d4f..1b2d019 100644 --- a/libeplayer3-arm/include/pes.h +++ b/libeplayer3-arm/include/pes.h @@ -12,8 +12,10 @@ #define PES_START_CODE_RESERVED_4 0xfd #define PES_VERSION_FAKE_START_CODE 0x31 + #define MAX_PES_PACKET_SIZE (65535) + /* start codes */ #define PCM_PES_START_CODE 0xbd #define PRIVATE_STREAM_1_PES_START_CODE 0xbd diff --git a/libeplayer3-arm/include/stm_ioctls.h b/libeplayer3-arm/include/stm_ioctls.h index bdcd8dc..fcb19ee 100644 --- a/libeplayer3-arm/include/stm_ioctls.h +++ b/libeplayer3-arm/include/stm_ioctls.h @@ -92,6 +92,7 @@ typedef enum VIDEO_ENCODING_PRIVATE } video_encoding_t; + /* * List of possible audio encodings - used to select frame parser and codec. */ @@ -198,6 +199,7 @@ typedef struct dvb_play_info_s typedef dvb_play_info_t video_play_info_t; typedef dvb_play_info_t audio_play_info_t; + typedef enum { #define DVB_OPTION_VALUE_DISABLE 0 @@ -283,6 +285,7 @@ typedef enum // Legacy typo correction #define DVP_OPTION_H264_FORCE_PIC_ORDER_CNT_IGNORE_DPB_DISPLAY_FRAME_ORDERING DVB_OPTION_H264_FORCE_PIC_ORDER_CNT_IGNORE_DPB_DISPLAY_FRAME_ORDERING + typedef dvb_option_t video_option_t; /* Decoder commands */ @@ -293,6 +296,7 @@ typedef dvb_option_t video_option_t; #define VIDEO_CMD_SET_OPTION (4) #define VIDEO_CMD_GET_OPTION (5) + /* Flags for VIDEO_CMD_FREEZE */ #define VIDEO_CMD_FREEZE_TO_BLACK (1 << 0) diff --git a/libeplayer3-arm/include/writer.h b/libeplayer3-arm/include/writer.h index 5f09166..b72636a 100644 --- a/libeplayer3-arm/include/writer.h +++ b/libeplayer3-arm/include/writer.h @@ -26,6 +26,8 @@ typedef struct ssize_t (* WriteV) (int, const struct iovec *, size_t); } WriterAVCallData_t; + + typedef struct WriterCaps_s { char *name; @@ -88,6 +90,6 @@ Writer_t *getDefaultVideoWriter(); Writer_t *getDefaultAudioWriter(); ssize_t write_with_retry(int fd, const void *buf, size_t size); ssize_t writev_with_retry(int fd, const struct iovec *iov, size_t ic); -ssize_t WriteWithRetry(Context_t *context, int pipefd, int fd, const void *buf, size_t size); +ssize_t WriteWithRetry(Context_t *context, int pipefd, int fd, const void *buf, size_t size); #endif diff --git a/libeplayer3-arm/main/exteplayer.c b/libeplayer3-arm/main/exteplayer.c index 54526c8..a6e0aea 100644 --- a/libeplayer3-arm/main/exteplayer.c +++ b/libeplayer3-arm/main/exteplayer.c @@ -101,34 +101,42 @@ static void *TermThreadFun(void *arg __attribute__((unused))) 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); @@ -139,10 +147,12 @@ static void *TermThreadFun(void *arg __attribute__((unused))) kill(getpid(), SIGINT); pthread_mutex_unlock(&playbackStartMtx); } + finish: close(cl); close(fd); pthread_exit(NULL); + } static void map_inter_file_path(char *filename) @@ -170,19 +180,24 @@ static int kbhit(void) { struct timeval tv; fd_set readfds; + tv.tv_sec = 1; tv.tv_usec = 0; + FD_ZERO(&readfds); - FD_SET(0,&readfds); + FD_SET(0, &readfds); FD_SET(g_pfd[0], &readfds); - if(-1 == select(g_pfd[0] + 1, &readfds, NULL, NULL, &tv)) + + if (-1 == select(g_pfd[0] + 1, &readfds, NULL, NULL, &tv)) { return 0; } + if (FD_ISSET(0, &readfds)) { return 1; } + return 0; } @@ -194,6 +209,7 @@ static void SetBuffering() { printf("SetBuffering: failed to change the buffer of stderr\n"); } + // make fgets not blocking int flags = fcntl(stdin->_fileno, F_GETFL, 0); fcntl(stdin->_fileno, F_SETFL, flags | O_NONBLOCK); @@ -203,6 +219,7 @@ static void SetNice(int prio) { #if 0 setpriority(PRIO_PROCESS, 0, -8); + int prio = sched_get_priority_max(SCHED_RR) / 2; struct sched_param param = { @@ -221,10 +238,12 @@ static void SetNice(int prio) static int HandleTracks(const Manager_t *ptrManager, const PlaybackCmd_t playbackSwitchCmd, const char *argvBuff) { int commandRetVal = 0; + if (NULL == ptrManager || NULL == argvBuff || 2 != strnlen(argvBuff, 2)) { return -1; } + switch (argvBuff[1]) { case 'l': @@ -340,6 +359,7 @@ static int HandleTracks(const Manager_t *ptrManager, const PlaybackCmd_t playbac { ok = sscanf(argvBuff + 1, "%d", &id); } + if (id >= 0 || (1 == ok && id == -1)) { commandRetVal = g_player->playback->Command(g_player, playbackSwitchCmd, (void *)&id); @@ -349,8 +369,10 @@ static int HandleTracks(const Manager_t *ptrManager, const PlaybackCmd_t playbac break; } } + return commandRetVal; } + #if 0 static int HandleTracks(const Manager_t *ptrManager, const PlaybackCmd_t playbackSwitchCmd, const char *argvBuff) { @@ -391,6 +413,7 @@ static int HandleTracks(const Manager_t *ptrManager, const PlaybackCmd_t playbac } case 'c': { + TrackDescription_t *track = NULL; ptrManager->Command(g_player, MANAGER_GET_TRACK_DESC, &track); if (NULL != track) @@ -461,6 +484,7 @@ static int HandleTracks(const Manager_t *ptrManager, const PlaybackCmd_t playbac { ok = sscanf(argvBuff + 1, "%d", &id); } + if (id >= 0 || (1 == ok && id == -1)) { commandRetVal = g_player->playback->Command(g_player, playbackSwitchCmd, (void *)&id); @@ -470,6 +494,7 @@ static int HandleTracks(const Manager_t *ptrManager, const PlaybackCmd_t playbac break; } } + return commandRetVal; } #endif @@ -486,7 +511,7 @@ static int ParseParams(int argc, char *argv[], char *file, char *audioFile, int //int digit_optind = 0; //int aopt = 0, bopt = 0; //char *copt = 0, *dopt = 0; - while ((c = getopt(argc, argv, "we3dlsrimva:n:x:u:c:h:o:p:P:t:9:0:1:4:f:b:")) != -1) + while ((c = getopt(argc, argv, "we3dlsrimva:n:x:u:c:h:o:p:P:t:9:0:1:4:f:b:")) != -1) { switch (c) { @@ -604,9 +629,11 @@ static int ParseParams(int argc, char *argv[], char *file, char *audioFile, int ret = -1; } } + if (0 == ret && optind < argc) { ret = 0; + if (NULL == strstr(argv[optind], "://")) { strcpy(file, "file://"); @@ -629,16 +656,21 @@ int main(int argc, char *argv[]) int isTermThreadStarted = 0; char file[IPTV_MAX_FILE_PATH]; memset(file, '\0', sizeof(file)); + char audioFile[IPTV_MAX_FILE_PATH]; memset(audioFile, '\0', sizeof(audioFile)); + int audioTrackIdx = -1; int subtitleTrackIdx = -1; - uint32_t linuxDvbBufferSizeMB = 0; + + 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", 45); + if (0 != ParseParams(argc, argv, file, audioFile, &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"); @@ -671,59 +703,76 @@ int main(int argc, char *argv[]) printf("[-f ffopt=ffval] any other ffmpeg option\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 + + //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(file, "rtmp", 4) && strncmp(file, "ffrtmp", 4)) { g_player->playback->noprobe = 1; } + PlayFiles_t playbackFiles = {file, NULL}; if ('\0' != audioFile[0]) { playbackFiles.szSecondFile = audioFile; } + 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, file, commandRetVal); if (commandRetVal < 0) @@ -734,17 +783,21 @@ int main(int argc, char *argv[]) } 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) @@ -754,6 +807,7 @@ int main(int argc, char *argv[]) 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) { @@ -763,6 +817,7 @@ int main(int argc, char *argv[]) } HandleTracks(g_player->manager->subtitle, (PlaybackCmd_t) - 1, "sc"); } + while (g_player->playback->isPlaying && 0 == PlaybackDieNow(0)) { /* we made fgets non blocking */ @@ -772,10 +827,12 @@ int main(int argc, char *argv[]) kbhit(); continue; } + if (0 == argvBuff[0]) { continue; } + switch (argvBuff[0]) { case 'v': @@ -815,6 +872,7 @@ int main(int argc, char *argv[]) { 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; @@ -833,6 +891,7 @@ int main(int argc, char *argv[]) { 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; @@ -841,6 +900,7 @@ int main(int argc, char *argv[]) { 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; @@ -852,11 +912,13 @@ int main(int argc, char *argv[]) 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\":%lld, \"sts\":%d}}\n", length, commandRetVal); + lengthInt = (int32_t)length; if (10 <= lengthInt || force) { @@ -865,6 +927,7 @@ int main(int argc, char *argv[]) { sec = lengthInt - 10; } + commandRetVal = g_player->playback->Command(g_player, PLAYBACK_SEEK_ABS, (void *)&sec); fprintf(stderr, "{\"PLAYBACK_SEEK_ABS\":{\"sec\":%lld, \"sts\":%d}}\n", sec, commandRetVal); } @@ -880,7 +943,9 @@ int main(int argc, char *argv[]) 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) @@ -891,6 +956,7 @@ int main(int argc, char *argv[]) { commandRetVal = g_player->playback->Command(g_player, PLAYBACK_LENGTH, (void *)&length); fprintf(stderr, "{\"PLAYBACK_LENGTH\":{\"length\":%lld, \"sts\":%d}}\n", length, commandRetVal); + lengthInt = (int32_t)length; if (10 <= lengthInt || force) { @@ -959,6 +1025,7 @@ int main(int argc, char *argv[]) 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': @@ -975,24 +1042,31 @@ int main(int argc, char *argv[]) } 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); } diff --git a/libeplayer3-arm/manager/audio.c b/libeplayer3-arm/manager/audio.c index 6e5abde..6543f51 100644 --- a/libeplayer3-arm/manager/audio.c +++ b/libeplayer3-arm/manager/audio.c @@ -84,6 +84,7 @@ static int CurrentTrack = 0; //TRACK[0] as default. static int ManagerAdd(Context_t *context, Track_t track) { audio_mgr_printf(10, "%s::%s name=\"%s\" encoding=\"%s\" id=%d\n", __FILE__, __FUNCTION__, track.Name, track.Encoding, track.Id); + if (Tracks == NULL) { Tracks = malloc(sizeof(Track_t) * TRACKWRAP); @@ -93,11 +94,13 @@ static int ManagerAdd(Context_t *context, Track_t track) Tracks[i].Id = -1; } } + if (Tracks == NULL) { audio_mgr_err("%s:%s malloc failed\n", __FILE__, __FUNCTION__); return cERR_AUDIO_MGR_ERROR; } + int i = 0; for (i = 0; i < TRACKWRAP; i++) { @@ -107,6 +110,7 @@ static int ManagerAdd(Context_t *context, Track_t track) return cERR_AUDIO_MGR_NO_ERROR; } } + if (TrackCount < TRACKWRAP) { copyTrack(&Tracks[TrackCount], &track); @@ -117,10 +121,12 @@ static int ManagerAdd(Context_t *context, Track_t track) audio_mgr_err("%s:%s TrackCount out if range %d - %d\n", __FILE__, __FUNCTION__, TrackCount, TRACKWRAP); return cERR_AUDIO_MGR_ERROR; } + if (TrackCount > 0) { context->playback->isAudio = 1; } + audio_mgr_printf(10, "%s::%s\n", __FILE__, __FUNCTION__); return cERR_AUDIO_MGR_NO_ERROR; } @@ -129,28 +135,36 @@ static char **ManagerList(Context_t *context __attribute__((unused))) { int i = 0, j = 0; char **tracklist = NULL; + audio_mgr_printf(10, "%s::%s\n", __FILE__, __FUNCTION__); if (Tracks != NULL) { tracklist = malloc(sizeof(char *) * ((TrackCount * 2) + 1)); + if (tracklist == NULL) { audio_mgr_err("%s:%s malloc failed\n", __FILE__, __FUNCTION__); return NULL; } + for (i = 0, j = 0; i < TrackCount; i++, j += 2) { if (Tracks[i].pending) + { continue; + } + size_t len = strlen(Tracks[i].Name) + 20; char tmp[len]; snprintf(tmp, len, "%d %s", Tracks[i].Id, Tracks[i].Name); tracklist[j] = strdup(tmp); tracklist[j + 1] = strdup(Tracks[i].Encoding); } + tracklist[j] = NULL; } audio_mgr_printf(10, "%s::%s return %p (%d - %d)\n", __FILE__, __FUNCTION__, tracklist, j, TrackCount); + return tracklist; } @@ -159,15 +173,18 @@ static TrackDescription_t *ManagerList(Context_t *context __attribute__((unused { int i = 0; TrackDescription_t *tracklist = NULL; + audio_mgr_printf(10, "%s::%s\n", __FILE__, __FUNCTION__); if (Tracks != NULL) { tracklist = malloc(sizeof(TrackDescription_t) * ((TrackCount) + 1)); + if (tracklist == NULL) { audio_mgr_err("%s:%s malloc failed\n", __FILE__, __FUNCTION__); return NULL; } + int j = 0; for (i = 0; i < TrackCount; ++i) { @@ -175,14 +192,17 @@ static TrackDescription_t *ManagerList(Context_t *context __attribute__((unused { continue; } + tracklist[j].Id = Tracks[i].Id; tracklist[j].Name = strdup(Tracks[i].Name); tracklist[j].Encoding = strdup(Tracks[i].Encoding); ++j; } + tracklist[j].Id = -1; } //audio_mgr_printf(10, "%s::%s return %p (%d - %d)\n", __FILE__, __FUNCTION__, tracklist, j, TrackCount); + return tracklist; } #endif @@ -190,13 +210,16 @@ static TrackDescription_t *ManagerList(Context_t *context __attribute__((unused static int ManagerDel(Context_t *context) { int i = 0; + audio_mgr_printf(10, "%s::%s\n", __FILE__, __FUNCTION__); + if (Tracks != NULL) { for (i = 0; i < TrackCount; i++) { freeTrack(&Tracks[i]); } + free(Tracks); Tracks = NULL; } @@ -205,17 +228,22 @@ static int ManagerDel(Context_t *context) audio_mgr_err("%s::%s nothing to delete!\n", __FILE__, __FUNCTION__); return cERR_AUDIO_MGR_ERROR; } + TrackCount = 0; CurrentTrack = 0; context->playback->isAudio = 0; + audio_mgr_printf(10, "%s::%s return no error\n", __FILE__, __FUNCTION__); + return cERR_AUDIO_MGR_NO_ERROR; } static int Command(Context_t *context, ManagerCmd_t command, void *argument) { int ret = cERR_AUDIO_MGR_NO_ERROR; + audio_mgr_printf(10, "%s::%s\n", __FILE__, __FUNCTION__); + switch (command) { case MANAGER_ADD: @@ -244,6 +272,7 @@ static int Command(Context_t *context, ManagerCmd_t command, void *argument) case MANAGER_GET: { audio_mgr_printf(20, "%s::%s MANAGER_GET\n", __FILE__, __FUNCTION__); + if ((TrackCount > 0) && (CurrentTrack >= 0)) { *((int *)argument) = (int)Tracks[CurrentTrack].Id; @@ -277,9 +306,10 @@ static int Command(Context_t *context, ManagerCmd_t command, void *argument) case MANAGER_GET_TRACK: { audio_mgr_printf(20, "%s::%s MANAGER_GET_TRACK\n", __FILE__, __FUNCTION__); + if ((TrackCount > 0) && (CurrentTrack >= 0)) { - *((Track_t **)argument) = (Track_t *) & Tracks[CurrentTrack]; + *((Track_t **)argument) = (Track_t *) &Tracks[CurrentTrack]; } else { @@ -315,6 +345,7 @@ static int Command(Context_t *context, ManagerCmd_t command, void *argument) { int i; audio_mgr_printf(20, "%s::%s MANAGER_SET id=%d\n", __FILE__, __FUNCTION__, *((int *)argument)); + for (i = 0; i < TrackCount; i++) { if (Tracks[i].Id == *((int *)argument)) @@ -323,6 +354,7 @@ static int Command(Context_t *context, ManagerCmd_t command, void *argument) break; } } + if (i == TrackCount) { audio_mgr_err("%s::%s track id %d unknown\n", __FILE__, __FUNCTION__, *((int *)argument)); @@ -349,10 +381,13 @@ static int Command(Context_t *context, ManagerCmd_t command, void *argument) ret = cERR_AUDIO_MGR_ERROR; break; } + audio_mgr_printf(10, "%s:%s: returning %d\n", __FILE__, __FUNCTION__, ret); + return ret; } + struct Manager_s AudioManager = { "Audio", diff --git a/libeplayer3-arm/manager/chapter.c b/libeplayer3-arm/manager/chapter.c index 14167a9..4a6fc11 100644 --- a/libeplayer3-arm/manager/chapter.c +++ b/libeplayer3-arm/manager/chapter.c @@ -181,8 +181,7 @@ static int ManagerDel(Context_t *context __attribute__((unused))) TrackCount = 0; CurrentTrack = 0; - chapter_mgr_printf(10, "%s::%s return no error\n", FILENAME, - __FUNCTION__); + chapter_mgr_printf(10, "%s::%s return no error\n", FILENAME, __FUNCTION__); return cERR_CHAPTER_MGR_NO_ERROR; } diff --git a/libeplayer3-arm/manager/manager.c b/libeplayer3-arm/manager/manager.c index 7ad53e8..c2b5c23 100644 --- a/libeplayer3-arm/manager/manager.c +++ b/libeplayer3-arm/manager/manager.c @@ -72,6 +72,7 @@ void copyTrack(Track_t *to, Track_t *from) { to->Name = strdup("Unknown"); } + if (from->Encoding != NULL) { to->Encoding = strdup(from->Encoding); @@ -80,6 +81,7 @@ void copyTrack(Track_t *to, Track_t *from) { to->Encoding = strdup("Unknown"); } + if (from->language != NULL) { to->language = strdup(from->language); @@ -100,16 +102,19 @@ void freeTrack(Track_t *track) free(track->Name); track->Name = NULL; } + if (track->Encoding != NULL) { free(track->Encoding); track->Encoding = NULL; } + if (track->language != NULL) { free(track->language); track->language = NULL; } + if (track->aacbuf != NULL) { free(track->aacbuf); diff --git a/libeplayer3-arm/manager/subtitle.c b/libeplayer3-arm/manager/subtitle.c index 4cff07c..144cb5c 100644 --- a/libeplayer3-arm/manager/subtitle.c +++ b/libeplayer3-arm/manager/subtitle.c @@ -33,12 +33,14 @@ #define TRACKWRAP 20 +//#define SAM_WITH_DEBUG #ifdef SAM_WITH_DEBUG #define SUBTITLE_MGR_DEBUG #else #define SUBTITLE_MGR_SILENT #endif + #ifdef SUBTITLE_MGR_DEBUG static short debug_level = 20; @@ -256,7 +258,7 @@ static int Command(Context_t *context, ManagerCmd_t command, void *argument) { if ((TrackCount > 0) && (CurrentTrack >= 0)) { - *((Track_t **)argument) = (Track_t *) & Tracks[CurrentTrack]; + *((Track_t **)argument) = (Track_t *) &Tracks[CurrentTrack]; } else { diff --git a/libeplayer3-arm/manager/video.c b/libeplayer3-arm/manager/video.c index adaa841..8a94d4a 100644 --- a/libeplayer3-arm/manager/video.c +++ b/libeplayer3-arm/manager/video.c @@ -84,6 +84,7 @@ static void (* updatedTrackInfoFnc)(void) = NULL; static int ManagerAdd(Context_t *context, Track_t track) { video_mgr_printf(10, "%s::%s\n", __FILE__, __FUNCTION__); + if (Tracks == NULL) { Tracks = malloc(sizeof(Track_t) * TRACKWRAP); @@ -93,11 +94,13 @@ static int ManagerAdd(Context_t *context, Track_t track) Tracks[i].Id = -1; } } + if (Tracks == NULL) { video_mgr_err("%s:%s malloc failed\n", __FILE__, __FUNCTION__); return cERR_VIDEO_MGR_ERROR; } + int i; for (i = 0; i < TRACKWRAP; i++) { @@ -107,6 +110,7 @@ static int ManagerAdd(Context_t *context, Track_t track) return cERR_VIDEO_MGR_NO_ERROR; } } + if (TrackCount < TRACKWRAP) { copyTrack(&Tracks[TrackCount], &track); @@ -117,10 +121,12 @@ static int ManagerAdd(Context_t *context, Track_t track) video_mgr_err("%s:%s TrackCount out if range %d - %d\n", __FILE__, __FUNCTION__, TrackCount, TRACKWRAP); return cERR_VIDEO_MGR_ERROR; } + if (TrackCount > 0) { context->playback->isVideo = 1; } + video_mgr_printf(10, "%s::%s\n", __FILE__, __FUNCTION__); return cERR_VIDEO_MGR_NO_ERROR; } @@ -129,15 +135,19 @@ static char **ManagerList(Context_t *context __attribute__((unused))) { int i = 0, j = 0; char **tracklist = NULL; + video_mgr_printf(10, "%s::%s\n", __FILE__, __FUNCTION__); + if (Tracks != NULL) { tracklist = malloc(sizeof(char *) * ((TrackCount * 2) + 1)); + if (tracklist == NULL) { video_mgr_err("%s:%s malloc failed\n", __FILE__, __FUNCTION__); return NULL; } + for (i = 0, j = 0; i < TrackCount; i++, j += 2) { if (Tracks[i].pending) @@ -152,6 +162,7 @@ static char **ManagerList(Context_t *context __attribute__((unused))) } tracklist[j] = NULL; } + video_mgr_printf(10, "%s::%s return %p (%d - %d)\n", __FILE__, __FUNCTION__, tracklist, j, TrackCount); return tracklist; } @@ -159,7 +170,9 @@ static char **ManagerList(Context_t *context __attribute__((unused))) static int ManagerDel(Context_t *context) { int i = 0; + video_mgr_printf(10, "%s::%s\n", __FILE__, __FUNCTION__); + if (Tracks != NULL) { for (i = 0; i < TrackCount; i++) @@ -174,9 +187,11 @@ static int ManagerDel(Context_t *context) video_mgr_err("%s::%s nothing to delete!\n", __FILE__, __FUNCTION__); return cERR_VIDEO_MGR_ERROR; } + TrackCount = 0; CurrentTrack = 0; context->playback->isVideo = 0; + video_mgr_printf(10, "%s::%s return no error\n", __FILE__, __FUNCTION__); return cERR_VIDEO_MGR_NO_ERROR; } @@ -184,7 +199,9 @@ static int ManagerDel(Context_t *context) static int Command(Context_t *context, ManagerCmd_t command, void *argument) { int ret = cERR_VIDEO_MGR_NO_ERROR; + video_mgr_printf(10, "%s::%s\n", __FILE__, __FUNCTION__); + switch (command) { case MANAGER_ADD: @@ -240,9 +257,10 @@ static int Command(Context_t *context, ManagerCmd_t command, void *argument) case MANAGER_GET_TRACK: { video_mgr_printf(20, "%s::%s MANAGER_GET_TRACK\n", __FILE__, __FUNCTION__); + if ((TrackCount > 0) && (CurrentTrack >= 0)) { - *((Track_t **)argument) = (Track_t *) & Tracks[CurrentTrack]; + *((Track_t **)argument) = (Track_t *) &Tracks[CurrentTrack]; } else { @@ -285,6 +303,7 @@ static int Command(Context_t *context, ManagerCmd_t command, void *argument) break; } } + if (i == TrackCount) { video_mgr_err("%s::%s track id %d unknown\n", __FILE__, __FUNCTION__, *((int *)argument)); @@ -322,10 +341,12 @@ static int Command(Context_t *context, ManagerCmd_t command, void *argument) ret = cERR_VIDEO_MGR_ERROR; break; } + video_mgr_printf(10, "%s:%s: returning %d\n", __FILE__, __FUNCTION__, ret); return ret; } + struct Manager_s VideoManager = { "Video", diff --git a/libeplayer3-arm/output/linuxdvb_buffering.c b/libeplayer3-arm/output/linuxdvb_buffering.c index 343296d..2fc472f 100644 --- a/libeplayer3-arm/output/linuxdvb_buffering.c +++ b/libeplayer3-arm/output/linuxdvb_buffering.c @@ -41,13 +41,15 @@ /* ***************************** */ /* Types */ /* ***************************** */ -typedef enum OutputType_e{ +typedef enum OutputType_e +{ OUTPUT_UNK, OUTPUT_AUDIO, OUTPUT_VIDEO, } OutputType_t; -typedef struct BufferingNode_s { +typedef struct BufferingNode_s +{ uint32_t dataSize; OutputType_t dataType; struct BufferingNode_s *next; @@ -56,8 +58,8 @@ typedef struct BufferingNode_s { /* ***************************** */ /* Makros/Constants */ /* ***************************** */ -#define cERR_LINUX_DVB_BUFFERING_NO_ERROR 0 -#define cERR_LINUX_DVB_BUFFERING_ERROR -1 +#define cERR_LINUX_DVB_BUFFERING_NO_ERROR 0 +#define cERR_LINUX_DVB_BUFFERING_ERROR -1 //#define SAM_WITH_DEBUG #ifdef SAM_WITH_DEBUG @@ -83,8 +85,9 @@ if (debug_level >= level) printf("[%s:%d:%s] " fmt, __FILE__, __LINE__, __FUNCTI #endif /* ***************************** */ -/* Varaibles */ +/* Variables */ /* ***************************** */ + static pthread_t bufferingThread; static pthread_mutex_t bufferingMtx; static pthread_cond_t bufferingExitCond; @@ -108,46 +111,54 @@ static int g_pfd[2] = {-1, -1}; /* ***************************** */ /* MISC Functions */ /* ***************************** */ + static void WriteWakeUp() { write(g_pfd[1], "x", 1); } -/* **************************** */ -/* Worker Thread */ -/* **************************** */ -static void LinuxDvbBuffThread(Context_t *context) +/* ***************************** */ +/* Worker Thread */ +/* ***************************** */ + +static void LinuxDvbBuffThread(Context_t *context) { int flags = 0; static BufferingNode_t *nodePtr = NULL; buff_printf(20, "ENTER\n"); - + if (pipe(g_pfd) == -1) { buff_err("critical error\n"); } + /* Make read and write ends of pipe nonblocking */ if ((flags = fcntl(g_pfd[0], F_GETFL)) == -1) { buff_err("critical error\n"); } + /* Make read end nonblocking */ flags |= O_NONBLOCK; if (fcntl(g_pfd[0], F_SETFL, flags) == -1) { buff_err("critical error\n"); } + if ((flags = fcntl(g_pfd[1], F_GETFL)) == -1) { buff_err("critical error\n"); } + /* Make write end nonblocking */ flags |= O_NONBLOCK; if (fcntl(g_pfd[1], F_SETFL, flags) == -1) { buff_err("critical error\n"); } + PlaybackDieNowRegisterCallback(WriteWakeUp); + while (0 == PlaybackDieNow(0)) { pthread_mutex_lock(&bufferingMtx); @@ -158,11 +169,11 @@ static void LinuxDvbBuffThread(Context_t *context) /* signal that we free some space in queue */ pthread_cond_signal(&bufferingDataConsumedCond); } - + if (!bufferingQueueHead) { assert(bufferingQueueTail == NULL); - + /* Queue is empty we need to wait for data to be added */ pthread_cond_wait(&bufferingdDataAddedCond, &bufferingMtx); pthread_mutex_unlock(&bufferingMtx); @@ -176,7 +187,7 @@ static void LinuxDvbBuffThread(Context_t *context) { bufferingQueueTail = NULL; } - + if (bufferingDataSize >= (nodePtr->dataSize + sizeof(BufferingNode_t))) { bufferingDataSize -= (nodePtr->dataSize + sizeof(BufferingNode_t)); @@ -188,12 +199,12 @@ static void LinuxDvbBuffThread(Context_t *context) } } pthread_mutex_unlock(&bufferingMtx); - + /* We will write data without mutex - * this have some disadvantage because we can - * write some portion of data after LinuxDvbBuffFlush, - * for example after seek, this will be fixed later - */ + * this have some disadvantage because we can + * write some portion of data after LinuxDvbBuffFlush, + * for example after seek, this will be fixed later + */ if (nodePtr && !context->playback->isSeeking) { /* Write data to valid output */ @@ -205,11 +216,11 @@ static void LinuxDvbBuffThread(Context_t *context) } } } - + pthread_mutex_lock(&bufferingMtx); pthread_cond_signal(&bufferingExitCond); pthread_mutex_unlock(&bufferingMtx); - + buff_printf(20, "EXIT\n"); hasBufferingThreadStarted = false; close(g_pfd[0]); @@ -228,36 +239,36 @@ int32_t LinuxDvbBuffOpen(Context_t *context, char *type, int outfd) { int32_t error = 0; int32_t ret = cERR_LINUX_DVB_BUFFERING_NO_ERROR; - + buff_printf(10, "\n"); - if (!hasBufferingThreadStarted) + if (!hasBufferingThreadStarted) { pthread_attr_t attr; pthread_attr_init(&attr); pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED); - if((error = pthread_create(&bufferingThread, &attr, (void *)&LinuxDvbBuffThread, context)) != 0) + if ((error = pthread_create(&bufferingThread, &attr, (void *)&LinuxDvbBuffThread, context)) != 0) { buff_printf(10, "Creating thread, error:%d:%s\n", error, strerror(error)); hasBufferingThreadStarted = false; ret = cERR_LINUX_DVB_BUFFERING_ERROR; } - else + else { buff_printf(10, "Created thread\n"); hasBufferingThreadStarted = true; /* init synchronization prymitives */ pthread_mutex_init(&bufferingMtx, NULL); - + pthread_cond_init(&bufferingExitCond, NULL); pthread_cond_init(&bufferingDataConsumedCond, NULL); pthread_cond_init(&bufferingdDataAddedCond, NULL); } } - + if (!ret) { if (!strcmp("video", type) && -1 == videofd) @@ -281,21 +292,22 @@ int32_t LinuxDvbBuffOpen(Context_t *context, char *type, int outfd) int32_t LinuxDvbBuffClose(Context_t *context __attribute__((unused))) { int32_t ret = 0; - + buff_printf(10, "\n"); videofd = -1; audiofd = -1; - - if (hasBufferingThreadStarted) + + if (hasBufferingThreadStarted) { struct timespec max_wait = {0, 0}; - - /* WakeUp if we are waiting in the write */ + + /* WakeUp if we are waiting in the write */ WriteWakeUp(); - + pthread_mutex_lock(&bufferingMtx); - /* wake up if thread is waiting for data */ + /* wake up if thread is waiting for data */ pthread_cond_signal(&bufferingdDataAddedCond); + /* wait for thread end */ clock_gettime(CLOCK_REALTIME, &max_wait); max_wait.tv_sec += 1; @@ -305,9 +317,9 @@ int32_t LinuxDvbBuffClose(Context_t *context __attribute__((unused))) if (!hasBufferingThreadStarted) { /* destroy synchronization prymitives? - * for a moment, we'll exit linux process, - * so the system will do this for us - */ + * for a moment, we'll exit linux process, + * so the system will do this for us + */ /* pthread_mutex_destroy(&bufferingMtx); pthread_cond_destroy(&bufferingDataConsumedCond); @@ -315,7 +327,7 @@ int32_t LinuxDvbBuffClose(Context_t *context __attribute__((unused))) */ } } - + ret = hasBufferingThreadStarted ? cERR_LINUX_DVB_BUFFERING_ERROR : cERR_LINUX_DVB_BUFFERING_NO_ERROR; buff_printf(10, "exiting with value %d\n", ret); @@ -326,46 +338,50 @@ int32_t LinuxDvbBuffFlush(Context_t *context __attribute__((unused))) { static BufferingNode_t *nodePtr = NULL; buff_printf(40, "ENTER bufferingQueueHead[%p]\n", bufferingQueueHead); - + /* signal if we are waiting for write to DVB decoders */ WriteWakeUp(); pthread_mutex_lock(&bufferingMtx); while (bufferingQueueHead) { - nodePtr = bufferingQueueHead; - bufferingQueueHead = nodePtr->next; - bufferingDataSize -= (nodePtr->dataSize + sizeof(BufferingNode_t)); - free(nodePtr); + nodePtr = bufferingQueueHead; + bufferingQueueHead = nodePtr->next; + bufferingDataSize -= (nodePtr->dataSize + sizeof(BufferingNode_t)); + free(nodePtr); } bufferingQueueHead = NULL; bufferingQueueTail = NULL; buff_printf(40, "bufferingDataSize [%u]\n", bufferingDataSize); assert(bufferingDataSize == 0); bufferingDataSize = 0; - + /* signal that queue is empty */ pthread_cond_signal(&bufferingDataConsumedCond); pthread_mutex_unlock(&bufferingMtx); buff_printf(40, "EXIT\n"); + return 0; } int32_t LinuxDvbBuffResume(Context_t *context __attribute__((unused))) { - /* signal if we are waiting for write to DVB decoders */ + /* signal if we are waiting for write to DVB decoders + * + */ WriteWakeUp(); + return 0; } -ssize_t BufferingWriteV(int fd, const struct iovec *iov, size_t ic) +ssize_t BufferingWriteV(int fd, const struct iovec *iov, size_t ic) { OutputType_t dataType = OUTPUT_UNK; BufferingNode_t *nodePtr = NULL; uint8_t *dataPtr = NULL; uint32_t chunkSize = 0; uint32_t i = 0; - + buff_printf(60, "ENTER\n"); if (fd == videofd) { @@ -382,13 +398,13 @@ ssize_t BufferingWriteV(int fd, const struct iovec *iov, size_t ic) buff_err("Unknown output type\n"); return cERR_LINUX_DVB_BUFFERING_ERROR; } - - for (i=0; inext = nodePtr; bufferingQueueTail = nodePtr; } - + bufferingDataSize += chunkSize; chunkSize -= sizeof(BufferingNode_t); nodePtr->dataSize = chunkSize; nodePtr->dataType = dataType; nodePtr->next = NULL; - + /* signal that we added some data to queue */ pthread_cond_signal(&bufferingdDataAddedCond); break; diff --git a/libeplayer3-arm/output/linuxdvb_mipsel.c b/libeplayer3-arm/output/linuxdvb_mipsel.c index 4335399..f4acac6 100644 --- a/libeplayer3-arm/output/linuxdvb_mipsel.c +++ b/libeplayer3-arm/output/linuxdvb_mipsel.c @@ -50,9 +50,7 @@ /* Makros/Constants */ /* ***************************** */ -// SULGE DEBUG //#define SAM_WITH_DEBUG - #ifdef SAM_WITH_DEBUG #define LINUXDVB_DEBUG static unsigned short debug_level = 20; @@ -64,15 +62,15 @@ static const char FILENAME[] = __FILE__; #ifdef LINUXDVB_DEBUG #define linuxdvb_printf(level, fmt, x...) do { \ -if (debug_level >= level) printf("[%s:%s] " fmt, __FILE__, __FUNCTION__, ## x ); } while (0) +if (debug_level >= level) printf("[%s:%s] " fmt, __FILE__, __FUNCTION__, ## x); } while (0) #else -#define linuxdvb_printf(level, fmt, x...) +#define linuxdvb_printf(x...) #endif #ifndef LINUXDVB_SILENT #define linuxdvb_err(fmt, x...) do { printf("[%s:%s] " fmt, __FILE__, __FUNCTION__, ## x); } while (0) #else -#define linuxdvb_err(fmt, x...) +#define linuxdvb_err(x...) #endif #define cERR_LINUXDVB_NO_ERROR 0 @@ -108,10 +106,11 @@ int32_t LinuxDvbBuffResume(Context_t *context); ssize_t BufferingWriteV(int fd, const struct iovec *iov, size_t ic); int32_t WriteSetBufferingSize(const uint32_t bufferSize); + int LinuxDvbStop(Context_t *context, char *type); /* ***************************** */ -/* Functions */ +/* MISC Functions */ /* ***************************** */ void getLinuxDVBMutex(const char *filename __attribute__((unused)), const char *function __attribute__((unused)), int line __attribute__((unused))) @@ -137,53 +136,67 @@ int LinuxDvbOpen(Context_t *context __attribute__((unused)), char *type) { uint8_t video = !strcmp("video", type); uint8_t audio = !strcmp("audio", type); + linuxdvb_printf(10, "v%d a%d\n", video, audio); + if (video && videofd < 0) { videofd = open(VIDEODEV, O_RDWR | O_CLOEXEC); + if (videofd < 0) { linuxdvb_err("failed to open %s - errno %d, %s\n", VIDEODEV, errno, strerror(errno)); + linuxdvb_err("%s\n",); return cERR_LINUXDVB_ERROR; } + if (ioctl(videofd, VIDEO_CLEAR_BUFFER) == -1) { linuxdvb_err("VIDEO_CLEAR_BUFFER: ERROR %d, %s\n", errno, strerror(errno)); } + if (ioctl(videofd, VIDEO_SELECT_SOURCE, (void *)VIDEO_SOURCE_MEMORY) == -1) { linuxdvb_err("VIDEO_SELECT_SOURCE: ERROR %d, %s\n", errno, strerror(errno)); } + if (ioctl(videofd, VIDEO_FREEZE) == -1) { linuxdvb_err("VIDEO_FREEZE: ERROR %d, %s\n", errno, strerror(errno)); } + if (isBufferedOutput) LinuxDvbBuffOpen(context, type, videofd); } if (audio && audiofd < 0) { audiofd = open(AUDIODEV, O_RDWR | O_CLOEXEC); + if (audiofd < 0) { linuxdvb_err("failed to open %s - errno %d, %s\n", AUDIODEV, errno, strerror(errno)); return cERR_LINUXDVB_ERROR; } + if (ioctl(audiofd, AUDIO_CLEAR_BUFFER) == -1) { linuxdvb_err("AUDIO_CLEAR_BUFFER: ERROR %d, %s\n", errno, strerror(errno)); } + if (ioctl(audiofd, AUDIO_SELECT_SOURCE, AUDIO_SOURCE_MEMORY) == -1) { linuxdvb_err("AUDIO_SELECT_SOURCE: ERROR %d, %s\n", errno, strerror(errno)); } + if (ioctl(audiofd, AUDIO_PAUSE) == -1) { linuxdvb_err("AUDIO_PAUSE: ERROR %d, %s\n", errno, strerror(errno)); } + if (isBufferedOutput) LinuxDvbBuffOpen(context, type, audiofd); } + return cERR_LINUXDVB_NO_ERROR; } @@ -191,15 +204,20 @@ int LinuxDvbClose(Context_t *context, char *type) { uint8_t video = !strcmp("video", type); uint8_t audio = !strcmp("audio", type); + linuxdvb_printf(10, "v%d a%d\n", video, audio); + /* closing stand alone is not allowed, so prevent * user from closing and don't call stop. stop will * set default values for us (speed and so on). */ LinuxDvbStop(context, type); + getLinuxDVBMutex(FILENAME, __FUNCTION__, __LINE__); + if (isBufferedOutput) LinuxDvbBuffClose(context); + if (video && videofd != -1) { close(videofd); @@ -210,6 +228,7 @@ int LinuxDvbClose(Context_t *context, char *type) close(audiofd); audiofd = -1; } + releaseLinuxDVBMutex(FILENAME, __FUNCTION__, __LINE__); return cERR_LINUXDVB_NO_ERROR; } @@ -218,14 +237,19 @@ int LinuxDvbPlay(Context_t *context, char *type) { int ret = cERR_LINUXDVB_NO_ERROR; Writer_t *writer; + uint8_t video = !strcmp("video", type); uint8_t audio = !strcmp("audio", type); + linuxdvb_printf(10, "v%d a%d\n", video, audio); + if (video && videofd != -1) { char *Encoding = NULL; context->manager->video->Command(context, MANAGER_GETENCODING, &Encoding); + linuxdvb_printf(10, "V %s\n", Encoding); + writer = getWriter(Encoding); if (writer == NULL) { @@ -242,15 +266,18 @@ int LinuxDvbPlay(Context_t *context, char *type) } } free(Encoding); + if (0 != ioctl(videofd, VIDEO_PLAY)) { linuxdvb_err("VIDEO_PLAY: ERROR %d, %s\n", errno, strerror(errno)); ret = cERR_LINUXDVB_ERROR; } + if (ioctl(videofd, VIDEO_CONTINUE) == -1) { linuxdvb_err("VIDEO_CONTINUE: ERROR %d, %s\n", errno, strerror(errno)); } + if (ioctl(videofd, VIDEO_CLEAR_BUFFER) == -1) { linuxdvb_err("VIDEO_CLEAR_BUFFER: ERROR %d, %s\n", errno, strerror(errno)); @@ -260,8 +287,11 @@ int LinuxDvbPlay(Context_t *context, char *type) { char *Encoding = NULL; context->manager->audio->Command(context, MANAGER_GETENCODING, &Encoding); + linuxdvb_printf(20, "0 A %s\n", Encoding); + writer = getWriter(Encoding); + if (writer == NULL) { linuxdvb_err("cannot found writer for encoding %s using default\n", Encoding); @@ -276,11 +306,13 @@ int LinuxDvbPlay(Context_t *context, char *type) ret = cERR_LINUXDVB_ERROR; } } + if (ioctl(audiofd, AUDIO_PLAY) < 0) { linuxdvb_err("AUDIO_PLAY: ERROR %d, %s\n", errno, strerror(errno)); ret = cERR_LINUXDVB_ERROR; } + if (ioctl(audiofd, AUDIO_CONTINUE) < 0) { linuxdvb_err("AUDIO_CONTINUE: ERROR %d, %s\n", errno, strerror(errno)); @@ -288,6 +320,7 @@ int LinuxDvbPlay(Context_t *context, char *type) } free(Encoding); } + ret = cERR_LINUXDVB_NO_ERROR; return ret; //return 0; @@ -298,19 +331,24 @@ int LinuxDvbStop(Context_t *context __attribute__((unused)), char *type) int ret = cERR_LINUXDVB_NO_ERROR; unsigned char video = !strcmp("video", type); unsigned char audio = !strcmp("audio", type); + linuxdvb_printf(10, "v%d a%d\n", video, audio); + getLinuxDVBMutex(FILENAME, __FUNCTION__, __LINE__); + if (video && videofd != -1) { if (ioctl(videofd, VIDEO_CLEAR_BUFFER) == -1) { linuxdvb_err("VIDEO_CLEAR_BUFFER: ERROR %d, %s\n", errno, strerror(errno)); } + if (ioctl(videofd, VIDEO_STOP) == -1) { linuxdvb_err("VIDEO_STOP: ERROR %d, %s\n", errno, strerror(errno)); ret = cERR_LINUXDVB_ERROR; } + ioctl(videofd, VIDEO_SLOWMOTION, 0); ioctl(videofd, VIDEO_FAST_FORWARD, 0); ioctl(videofd, VIDEO_SELECT_SOURCE, VIDEO_SOURCE_DEMUX); @@ -321,6 +359,7 @@ int LinuxDvbStop(Context_t *context __attribute__((unused)), char *type) { linuxdvb_err("AUDIO_CLEAR_BUFFER: ERROR %d, %s\n", errno, strerror(errno)); } + if (ioctl(audiofd, AUDIO_STOP) == -1) { linuxdvb_err("AUDIO_STOP: ERROR %d, %s\n", errno, strerror(errno)); @@ -328,7 +367,9 @@ int LinuxDvbStop(Context_t *context __attribute__((unused)), char *type) } ioctl(audiofd, AUDIO_SELECT_SOURCE, AUDIO_SOURCE_DEMUX); } + releaseLinuxDVBMutex(FILENAME, __FUNCTION__, __LINE__); + return ret; } @@ -337,8 +378,11 @@ int LinuxDvbPause(Context_t *context __attribute__((unused)), char *type) int32_t ret = cERR_LINUXDVB_NO_ERROR; uint8_t video = !strcmp("video", type); uint8_t audio = !strcmp("audio", type); + linuxdvb_printf(10, "v%d a%d\n", video, audio); + getLinuxDVBMutex(FILENAME, __FUNCTION__, __LINE__); + if (video && videofd != -1) { if (ioctl(videofd, VIDEO_FREEZE, NULL) == -1) @@ -347,6 +391,7 @@ int LinuxDvbPause(Context_t *context __attribute__((unused)), char *type) ret = cERR_LINUXDVB_ERROR; } } + if (audio && audiofd != -1) { if (ioctl(audiofd, AUDIO_PAUSE, NULL) == -1) @@ -355,7 +400,9 @@ int LinuxDvbPause(Context_t *context __attribute__((unused)), char *type) ret = cERR_LINUXDVB_ERROR; } } + releaseLinuxDVBMutex(FILENAME, __FUNCTION__, __LINE__); + return ret; } @@ -364,19 +411,23 @@ int LinuxDvbContinue(Context_t *context __attribute__((unused)), char *type) int32_t ret = cERR_LINUXDVB_NO_ERROR; uint8_t video = !strcmp("video", type); uint8_t audio = !strcmp("audio", type); + linuxdvb_printf(10, "v%d a%d\n", video, audio); + if (video && videofd != -1) { if (context->playback->isForwarding == 0) { ioctl(videofd, VIDEO_FAST_FORWARD, 0); } + if (ioctl(videofd, VIDEO_CONTINUE, NULL) == -1) { linuxdvb_err("VIDEO_CONTINUE: ERROR %d, %s\n", errno, strerror(errno)); ret = cERR_LINUXDVB_ERROR; } } + if (audio && audiofd != -1) { if (ioctl(audiofd, AUDIO_CONTINUE, NULL) == -1) @@ -385,16 +436,21 @@ int LinuxDvbContinue(Context_t *context __attribute__((unused)), char *type) ret = cERR_LINUXDVB_ERROR; } } + if (isBufferedOutput) LinuxDvbBuffResume(context); + linuxdvb_printf(10, "exiting\n"); + return ret; } int LinuxDvbAudioMute(Context_t *context __attribute__((unused)), char *flag) { int ret = cERR_LINUXDVB_NO_ERROR; + linuxdvb_printf(10, "\n"); + if (audiofd != -1) { if (*flag == '1') @@ -414,7 +470,9 @@ int LinuxDvbAudioMute(Context_t *context __attribute__((unused)), char *flag) } } } + linuxdvb_printf(10, "exiting\n"); + return ret; } @@ -428,8 +486,11 @@ int LinuxDvbFastForward(Context_t *context, char *type) int32_t ret = cERR_LINUXDVB_NO_ERROR; uint8_t video = !strcmp("video", type); uint8_t audio = !strcmp("audio", type); + if (audio) {} + linuxdvb_printf(10, "v%d a%d speed %d\n", video, audio, context->playback->Speed); + if (video && videofd != -1) { getLinuxDVBMutex(FILENAME, __FUNCTION__, __LINE__); @@ -441,6 +502,7 @@ int LinuxDvbFastForward(Context_t *context, char *type) } releaseLinuxDVBMutex(FILENAME, __FUNCTION__, __LINE__); } + linuxdvb_printf(10, "exiting with value %d\n", ret); return ret; } @@ -448,12 +510,16 @@ int LinuxDvbFastForward(Context_t *context, char *type) int LinuxDvbSlowMotion(Context_t *context, char *type) { int32_t ret = cERR_LINUXDVB_NO_ERROR; + uint8_t video = !strcmp("video", type); uint8_t audio = !strcmp("audio", type); + linuxdvb_printf(10, "v%d a%d\n", video, audio); + if ((video && videofd != -1) || (audio && audiofd != -1)) { getLinuxDVBMutex(FILENAME, __FUNCTION__, __LINE__); + if (video && videofd != -1) { if (ioctl(videofd, VIDEO_SLOWMOTION, context->playback->SlowMotion) == -1) @@ -462,9 +528,12 @@ int LinuxDvbSlowMotion(Context_t *context, char *type) ret = cERR_LINUXDVB_ERROR; } } + releaseLinuxDVBMutex(FILENAME, __FUNCTION__, __LINE__); } + linuxdvb_printf(10, "exiting with value %d\n", ret); + return ret; } @@ -480,13 +549,16 @@ int LinuxDvbAVSync(Context_t *context __attribute__((unused)), char *type __attr if (audiofd != -1) { getLinuxDVBMutex(FILENAME, __FUNCTION__, __LINE__); + if (ioctl(audiofd, AUDIO_SET_AV_SYNC, 0) == -1) //context->playback->AVSync) == -1) { linuxdvb_err("AUDIO_SET_AV_SYNC: ERROR %d, %s\n", errno, strerror(errno)); ret = cERR_LINUXDVB_ERROR; } + releaseLinuxDVBMutex(FILENAME, __FUNCTION__, __LINE__); } + return ret; } @@ -495,10 +567,13 @@ int LinuxDvbClear(Context_t *context __attribute__((unused)), char *type) int32_t ret = cERR_LINUXDVB_NO_ERROR; uint8_t video = !strcmp("video", type); uint8_t audio = !strcmp("audio", type); + linuxdvb_printf(10, "LinuxDvbClear v%d a%d\n", video, audio); + if ((video && videofd != -1) || (audio && audiofd != -1)) { getLinuxDVBMutex(FILENAME, __FUNCTION__, __LINE__); + if (video && videofd != -1) { if (ioctl(videofd, VIDEO_CLEAR_BUFFER) == -1) @@ -515,16 +590,21 @@ int LinuxDvbClear(Context_t *context __attribute__((unused)), char *type) ret = cERR_LINUXDVB_ERROR; } } + releaseLinuxDVBMutex(FILENAME, __FUNCTION__, __LINE__); } + linuxdvb_printf(10, "exiting\n"); + return ret; } int LinuxDvbPts(Context_t *context __attribute__((unused)), unsigned long long int *pts) { int32_t ret = cERR_LINUXDVB_ERROR; + linuxdvb_printf(50, "\n"); + // GET_PTS is immutable call, so it can be done in parallel to other requests if (videofd > -1 && !ioctl(videofd, VIDEO_GET_PTS, (void *)&sCURRENT_PTS)) { @@ -534,6 +614,7 @@ int LinuxDvbPts(Context_t *context __attribute__((unused)), unsigned long long i { linuxdvb_err("VIDEO_GET_PTS: ERROR %d, %s\n", errno, strerror(errno)); } + if (ret != cERR_LINUXDVB_NO_ERROR) { if (audiofd > -1 && !ioctl(audiofd, AUDIO_GET_PTS, (void *)&sCURRENT_PTS)) @@ -545,10 +626,12 @@ int LinuxDvbPts(Context_t *context __attribute__((unused)), unsigned long long i linuxdvb_err("AUDIO_GET_PTS: ERROR %d, %s\n", errno, strerror(errno)); } } + if (ret != cERR_LINUXDVB_NO_ERROR) { sCURRENT_PTS = 0; } + *((unsigned long long int *)pts) = (unsigned long long int)sCURRENT_PTS; return ret; } @@ -563,26 +646,34 @@ int LinuxDvbSwitch(Context_t *context, char *type) uint8_t audio = !strcmp("audio", type); uint8_t video = !strcmp("video", type); Writer_t *writer; + linuxdvb_printf(10, "v%d a%d\n", video, audio); + if ((video && videofd != -1) || (audio && audiofd != -1)) { getLinuxDVBMutex(FILENAME, __FUNCTION__, __LINE__); + if (audio && audiofd != -1) { char *Encoding = NULL; if (context && context->manager && context->manager->audio) { context->manager->audio->Command(context, MANAGER_GETENCODING, &Encoding); + linuxdvb_printf(10, "A %s\n", Encoding); + writer = getWriter(Encoding); + if (ioctl(audiofd, AUDIO_STOP, NULL) == -1) { linuxdvb_err("AUDIO_STOP: ERROR %d, %s\n", errno, strerror(errno)); } + if (ioctl(audiofd, AUDIO_CLEAR_BUFFER) == -1) { linuxdvb_err("AUDIO_CLEAR_BUFFER: ERROR %d, %s\n", errno, strerror(errno)); } + if (writer == NULL) { linuxdvb_err("cannot found writer for encoding %s using default\n", Encoding); @@ -595,6 +686,7 @@ int LinuxDvbSwitch(Context_t *context, char *type) linuxdvb_err("AUDIO_SET_BYPASS_MODE: ERROR %d, %s\n", errno, strerror(errno)); } } + if (ioctl(audiofd, AUDIO_PLAY) == -1) { linuxdvb_err("AUDIO_PLAY: ERROR %d, %s\n", errno, strerror(errno)); @@ -606,22 +698,28 @@ int LinuxDvbSwitch(Context_t *context, char *type) linuxdvb_printf(20, "no context for Audio\n"); } } + if (video && videofd != -1) { char *Encoding = NULL; if (context && context->manager && context->manager->video) { context->manager->video->Command(context, MANAGER_GETENCODING, &Encoding); + if (ioctl(videofd, VIDEO_STOP, NULL) == -1) { linuxdvb_err("VIDEO_STOP: ERROR %d, %s\n", errno, strerror(errno)); } + if (ioctl(videofd, VIDEO_CLEAR_BUFFER) == -1) { linuxdvb_err("VIDEO_CLEAR_BUFFER: ERROR %d, %s\n", errno, strerror(errno)); } + linuxdvb_printf(10, "V %s\n", Encoding); + writer = getWriter(Encoding); + if (writer == NULL) { linuxdvb_err("cannot found writer for encoding %s using default\n", Encoding); @@ -634,6 +732,7 @@ int LinuxDvbSwitch(Context_t *context, char *type) linuxdvb_err("VIDEO_SET_STREAMTYPE: ERROR %d, %s\n", errno, strerror(errno)); } } + if (ioctl(videofd, VIDEO_PLAY) == -1) { /* konfetti: fixme: think on this, I think we should @@ -648,42 +747,54 @@ int LinuxDvbSwitch(Context_t *context, char *type) linuxdvb_printf(20, "no context for Video\n"); } } + releaseLinuxDVBMutex(FILENAME, __FUNCTION__, __LINE__); + } + linuxdvb_printf(10, "exiting\n"); + return cERR_LINUXDVB_NO_ERROR; } static int Write(Context_t *context, void *_out) { AudioVideoOut_t *out = (AudioVideoOut_t *) _out; - int32_t ret = cERR_LINUXDVB_NO_ERROR; - int32_t res = 0; - uint8_t video = 0; - uint8_t audio = 0; - Writer_t *writer = NULL; + int32_t ret = cERR_LINUXDVB_NO_ERROR; + int32_t res = 0; + uint8_t video = 0; + uint8_t audio = 0; + Writer_t *writer = NULL; WriterAVCallData_t call; + if (out == NULL) { linuxdvb_err("null pointer passed\n"); return cERR_LINUXDVB_ERROR; } + video = !strcmp("video", out->type); audio = !strcmp("audio", out->type); + linuxdvb_printf(20, "DataLength=%u PrivateLength=%u Pts=%llu FrameRate=%f\n", out->len, out->extralen, out->pts, out->frameRate); linuxdvb_printf(20, "v%d a%d\n", video, audio); + if (video) { char *Encoding = NULL; context->manager->video->Command(context, MANAGER_GETENCODING, &Encoding); + linuxdvb_printf(20, "Encoding = %s\n", Encoding); + writer = getWriter(Encoding); + if (writer == NULL) { linuxdvb_printf(20, "searching default writer ... %s\n", Encoding); writer = getDefaultVideoWriter(); } + if (writer == NULL) { linuxdvb_err("unknown video codec and no default writer %s\n", Encoding); @@ -734,6 +845,7 @@ static int Write(Context_t *context, void *_out) } } } + call.fd = videofd; call.data = out->data; call.len = out->len; @@ -747,11 +859,13 @@ static int Write(Context_t *context, void *_out) call.Height = out->height; call.InfoFlags = out->infoFlags; call.Version = 0; - call.WriteV = isBufferedOutput ? BufferingWriteV : writev_with_retry; + call.WriteV = isBufferedOutput ? BufferingWriteV : writev_with_retry; + if (writer->writeData) { res = writer->writeData(&call); } + if (res < 0) { linuxdvb_err("failed to write data %d - %d\n", res, errno); @@ -759,19 +873,24 @@ static int Write(Context_t *context, void *_out) ret = cERR_LINUXDVB_ERROR; } } + free(Encoding); } else if (audio) { char *Encoding = NULL; context->manager->audio->Command(context, MANAGER_GETENCODING, &Encoding); + linuxdvb_printf(20, "%s::%s Encoding = %s\n", FILENAME, __FUNCTION__, Encoding); + writer = getWriter(Encoding); + if (writer == NULL) { linuxdvb_printf(20, "searching default writer ... %s\n", Encoding); writer = getDefaultAudioWriter(); } + if (writer == NULL) { linuxdvb_err("unknown audio codec %s and no default writer\n", Encoding); @@ -790,11 +909,13 @@ static int Write(Context_t *context, void *_out) call.FrameScale = out->timeScale; call.InfoFlags = out->infoFlags; call.Version = 0; - call.WriteV = isBufferedOutput ? BufferingWriteV : writev_with_retry; + call.WriteV = isBufferedOutput ? BufferingWriteV : writev_with_retry; + if (writer->writeData) { res = writer->writeData(&call); } + if (res < 0) { linuxdvb_err("failed to write data %d - %d\n", res, errno); @@ -802,8 +923,10 @@ static int Write(Context_t *context, void *_out) ret = cERR_LINUXDVB_ERROR; } } + free(Encoding); } + return ret; } @@ -812,8 +935,11 @@ static int reset(Context_t *context) int ret = cERR_LINUXDVB_NO_ERROR; Writer_t *writer; char *Encoding = NULL; + context->manager->video->Command(context, MANAGER_GETENCODING, &Encoding); + writer = getWriter(Encoding); + if (writer == NULL) { linuxdvb_err("unknown video codec %s\n", Encoding); @@ -823,9 +949,13 @@ static int reset(Context_t *context) { writer->reset(); } + free(Encoding); + context->manager->audio->Command(context, MANAGER_GETENCODING, &Encoding); + writer = getWriter(Encoding); + if (writer == NULL) { linuxdvb_err("unknown video codec %s\n", Encoding); @@ -835,16 +965,21 @@ static int reset(Context_t *context) { writer->reset(); } + free(Encoding); + if (isBufferedOutput) LinuxDvbBuffFlush(context); + return ret; } static int Command(Context_t *context, OutputCmd_t command, void *argument) { int ret = cERR_LINUXDVB_NO_ERROR; + linuxdvb_printf(50, "Command %d\n", command); + switch (command) { case OUTPUT_OPEN: @@ -946,7 +1081,7 @@ static int Command(Context_t *context, OutputCmd_t command, void *argument) ret = cERR_LINUXDVB_ERROR; if (!isBufferedOutput) { - uint32_t bufferSize = *((uint32_t*)argument); + uint32_t bufferSize = *((uint32_t *)argument); ret = cERR_LINUXDVB_NO_ERROR; if (bufferSize > 0) { @@ -961,7 +1096,9 @@ static int Command(Context_t *context, OutputCmd_t command, void *argument) ret = cERR_LINUXDVB_ERROR; break; } + linuxdvb_printf(50, "exiting with value %d\n", ret); + return ret; } diff --git a/libeplayer3-arm/output/linuxdvb_sh4.c b/libeplayer3-arm/output/linuxdvb_sh4.c index efbc39c..1eb6d23 100644 --- a/libeplayer3-arm/output/linuxdvb_sh4.c +++ b/libeplayer3-arm/output/linuxdvb_sh4.c @@ -70,6 +70,7 @@ if (debug_level >= level) printf("[%s:%s] " fmt, __FILE__, __FUNCTION__, ## x); #define linuxdvb_err(x...) #endif + #define cERR_LINUXDVB_NO_ERROR 0 #define cERR_LINUXDVB_ERROR -1 @@ -99,84 +100,103 @@ pthread_mutex_t LinuxDVBmutex; int LinuxDvbStop(Context_t *context, char *type); /* ***************************** */ -/* Functions */ +/* MISC Functions */ /* ***************************** */ void getLinuxDVBMutex(const char *filename __attribute__((unused)), const char *function __attribute__((unused)), int line __attribute__((unused))) { + linuxdvb_printf(250, "requesting mutex\n"); + pthread_mutex_lock(&LinuxDVBmutex); + linuxdvb_printf(250, "received mutex\n"); } void releaseLinuxDVBMutex(const char *filename __attribute__((unused)), const char *function __attribute__((unused)), int line __attribute__((unused))) { pthread_mutex_unlock(&LinuxDVBmutex); + linuxdvb_printf(250, "released mutex\n"); + } int LinuxDvbOpen(Context_t *context __attribute__((unused)), char *type) { unsigned char video = !strcmp("video", type); unsigned char audio = !strcmp("audio", type); + linuxdvb_printf(10, "v%d a%d\n", video, audio); + if (video && videofd < 0) { videofd = open(VIDEODEV, O_RDWR); + if (videofd < 0) { linuxdvb_err("failed to open %s - errno %d\n", VIDEODEV, errno); linuxdvb_err("%s\n", strerror(errno)); return cERR_LINUXDVB_ERROR; } + 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_SELECT_SOURCE, (void *)VIDEO_SOURCE_MEMORY) == -1) { linuxdvb_err("ioctl failed with errno %d\n", errno); linuxdvb_err("VIDEO_SELECT_SOURCE: %s\n", strerror(errno)); } + if (ioctl(videofd, VIDEO_SET_STREAMTYPE, (void *)STREAM_TYPE_PROGRAM) == -1) { linuxdvb_err("ioctl failed with errno %d\n", errno); linuxdvb_err("VIDEO_SET_STREAMTYPE: %s\n", strerror(errno)); } + if (ioctl(videofd, VIDEO_SET_SPEED, DVB_SPEED_NORMAL_PLAY) == -1) { linuxdvb_err("ioctl failed with errno %d\n", errno); linuxdvb_err("VIDEO_SET_SPEED: %s\n", strerror(errno)); } + } if (audio && audiofd < 0) { audiofd = open(AUDIODEV, O_RDWR); + if (audiofd < 0) { linuxdvb_err("failed to open %s - errno %d\n", AUDIODEV, errno); linuxdvb_err("%s\n", strerror(errno)); + if (videofd < 0) close(videofd); return cERR_LINUXDVB_ERROR; } + 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_SELECT_SOURCE, (void *)AUDIO_SOURCE_MEMORY) == -1) { linuxdvb_err("ioctl failed with errno %d\n", errno); linuxdvb_err("AUDIO_SELECT_SOURCE: %s\n", strerror(errno)); } + if (ioctl(audiofd, AUDIO_SET_STREAMTYPE, (void *)STREAM_TYPE_PROGRAM) == -1) { linuxdvb_err("ioctl failed with errno %d\n", errno); linuxdvb_err("AUDIO_SET_STREAMTYPE: %s\n", strerror(errno)); } } + return cERR_LINUXDVB_NO_ERROR; } @@ -184,13 +204,17 @@ int LinuxDvbClose(Context_t *context, char *type) { unsigned char video = !strcmp("video", type); unsigned char audio = !strcmp("audio", type); + linuxdvb_printf(10, "v%d a%d\n", video, audio); + /* closing stand alone is not allowed, so prevent * user from closing and dont call stop. stop will * set default values for us (speed and so on). */ LinuxDvbStop(context, type); + getLinuxDVBMutex(FILENAME, __FUNCTION__, __LINE__); + if (video && videofd != -1) { close(videofd); @@ -201,6 +225,7 @@ int LinuxDvbClose(Context_t *context, char *type) close(audiofd); audiofd = -1; } + releaseLinuxDVBMutex(FILENAME, __FUNCTION__, __LINE__); return cERR_LINUXDVB_NO_ERROR; } @@ -209,15 +234,21 @@ int LinuxDvbPlay(Context_t *context, char *type) { int ret = cERR_LINUXDVB_NO_ERROR; Writer_t *writer; + unsigned char video = !strcmp("video", type); unsigned char audio = !strcmp("audio", type); + linuxdvb_printf(10, "v%d a%d\n", video, audio); + if (video && videofd != -1) { char *Encoding = NULL; context->manager->video->Command(context, MANAGER_GETENCODING, &Encoding); + linuxdvb_printf(10, "V %s\n", Encoding); + writer = getWriter(Encoding); + if (writer == NULL) { linuxdvb_err("cannot found writer for encoding %s using default\n", Encoding); @@ -238,6 +269,7 @@ int LinuxDvbPlay(Context_t *context, char *type) ret = cERR_LINUXDVB_ERROR; } } + if (ioctl(videofd, VIDEO_PLAY, NULL) == -1) { linuxdvb_err("ioctl failed with errno %d\n", errno); @@ -250,8 +282,11 @@ int LinuxDvbPlay(Context_t *context, char *type) { char *Encoding = NULL; context->manager->audio->Command(context, MANAGER_GETENCODING, &Encoding); + linuxdvb_printf(20, "0 A %s\n", Encoding); + writer = getWriter(Encoding); + if (writer == NULL) { linuxdvb_err("cannot found writer for encoding %s using default\n", Encoding); @@ -272,6 +307,7 @@ int LinuxDvbPlay(Context_t *context, char *type) ret = -1; } } + if (ioctl(audiofd, AUDIO_PLAY, NULL) == -1) { linuxdvb_err("ioctl failed with errno %d\n", errno); @@ -280,6 +316,7 @@ int LinuxDvbPlay(Context_t *context, char *type) } free(Encoding); } + return ret; } @@ -288,8 +325,11 @@ int LinuxDvbStop(Context_t *context __attribute__((unused)), char *type) int ret = cERR_LINUXDVB_NO_ERROR; unsigned char video = !strcmp("video", type); unsigned char audio = !strcmp("audio", type); + linuxdvb_printf(10, "v%d a%d\n", video, audio); + getLinuxDVBMutex(FILENAME, __FUNCTION__, __LINE__); + if (video && videofd != -1) { if (ioctl(videofd, VIDEO_CLEAR_BUFFER) == -1) @@ -297,6 +337,7 @@ int LinuxDvbStop(Context_t *context __attribute__((unused)), char *type) linuxdvb_err("ioctl failed with errno %d\n", errno); linuxdvb_err("VIDEO_CLEAR_BUFFER: %s\n", strerror(errno)); } + /* set back to normal speed (end trickmodes) */ if (ioctl(videofd, VIDEO_SET_SPEED, DVB_SPEED_NORMAL_PLAY) == -1) { @@ -317,6 +358,7 @@ int LinuxDvbStop(Context_t *context __attribute__((unused)), char *type) linuxdvb_err("ioctl failed with errno %d\n", errno); linuxdvb_err("AUDIO_CLEAR_BUFFER: %s\n", strerror(errno)); } + /* set back to normal speed (end trickmodes) */ if (ioctl(audiofd, AUDIO_SET_SPEED, DVB_SPEED_NORMAL_PLAY) == -1) { @@ -330,7 +372,9 @@ int LinuxDvbStop(Context_t *context __attribute__((unused)), char *type) ret = cERR_LINUXDVB_ERROR; } } + releaseLinuxDVBMutex(FILENAME, __FUNCTION__, __LINE__); + return ret; } @@ -339,8 +383,11 @@ int LinuxDvbPause(Context_t *context __attribute__((unused)), char *type) int ret = cERR_LINUXDVB_NO_ERROR; unsigned char video = !strcmp("video", type); unsigned char audio = !strcmp("audio", type); + linuxdvb_printf(10, "v%d a%d\n", video, audio); + getLinuxDVBMutex(FILENAME, __FUNCTION__, __LINE__); + if (video && videofd != -1) { if (ioctl(videofd, VIDEO_FREEZE, NULL) == -1) @@ -359,7 +406,9 @@ int LinuxDvbPause(Context_t *context __attribute__((unused)), char *type) ret = cERR_LINUXDVB_ERROR; } } + releaseLinuxDVBMutex(FILENAME, __FUNCTION__, __LINE__); + return ret; } @@ -368,7 +417,9 @@ int LinuxDvbContinue(Context_t *context __attribute__((unused)), char *type) int ret = cERR_LINUXDVB_NO_ERROR; unsigned char video = !strcmp("video", type); unsigned char audio = !strcmp("audio", type); + linuxdvb_printf(10, "v%d a%d\n", video, audio); + if (video && videofd != -1) { if (ioctl(videofd, VIDEO_CONTINUE, NULL) == -1) @@ -387,7 +438,10 @@ int LinuxDvbContinue(Context_t *context __attribute__((unused)), char *type) ret = cERR_LINUXDVB_ERROR; } } + linuxdvb_printf(10, "exiting\n"); + + return ret; } @@ -395,20 +449,26 @@ int LinuxDvbReverseDiscontinuity(Context_t *context __attribute__((unused)), int { int ret = cERR_LINUXDVB_NO_ERROR; int dis_type = VIDEO_DISCONTINUITY_CONTINUOUS_REVERSE | *surplus; + linuxdvb_printf(50, "\n"); + if (ioctl(videofd, VIDEO_DISCONTINUITY, (void *) dis_type) == -1) { linuxdvb_err("ioctl failed with errno %d\n", errno); linuxdvb_err("VIDEO_DISCONTINUITY: %s\n", strerror(errno)); } + linuxdvb_printf(50, "exiting\n"); + return ret; } int LinuxDvbAudioMute(Context_t *context __attribute__((unused)), char *flag) { int ret = cERR_LINUXDVB_NO_ERROR; + linuxdvb_printf(10, "\n"); + if (audiofd != -1) { if (*flag == '1') @@ -436,18 +496,24 @@ int LinuxDvbAudioMute(Context_t *context __attribute__((unused)), char *flag) } } } + linuxdvb_printf(10, "exiting\n"); + return ret; } + int LinuxDvbFlush(Context_t *context __attribute__((unused)), char *type) { unsigned char video = !strcmp("video", type); unsigned char audio = !strcmp("audio", type); + linuxdvb_printf(10, "v%d a%d\n", video, audio); + if ((video && videofd != -1) || (audio && audiofd != -1)) { getLinuxDVBMutex(FILENAME, __FUNCTION__, __LINE__); + if (video && videofd != -1) { if (ioctl(videofd, VIDEO_FLUSH, NULL) == -1) @@ -456,6 +522,7 @@ int LinuxDvbFlush(Context_t *context __attribute__((unused)), char *type) linuxdvb_err("VIDEO_FLUSH: %s\n", strerror(errno)); } } + if (audio && audiofd != -1) { if (ioctl(audiofd, AUDIO_FLUSH, NULL) == -1) @@ -464,9 +531,12 @@ int LinuxDvbFlush(Context_t *context __attribute__((unused)), char *type) linuxdvb_err("AUDIO_FLUSH: %s\n", strerror(errno)); } } + releaseLinuxDVBMutex(FILENAME, __FUNCTION__, __LINE__); } + linuxdvb_printf(10, "exiting\n"); + return cERR_LINUXDVB_NO_ERROR; } @@ -474,22 +544,31 @@ int LinuxDvbFlush(Context_t *context __attribute__((unused)), char *type) int LinuxDvbFastForward(Context_t *context, char *type) { int ret = cERR_LINUXDVB_NO_ERROR; + unsigned char video = !strcmp("video", type); unsigned char audio = !strcmp("audio", type); + linuxdvb_printf(10, "v%d a%d speed %d\n", video, audio, context->playback->Speed); + if (video && videofd != -1) { + getLinuxDVBMutex(FILENAME, __FUNCTION__, __LINE__); + /* konfetti comment: speed is a value given in skipped frames */ + if (ioctl(videofd, VIDEO_FAST_FORWARD, context->playback->Speed) == -1) { linuxdvb_err("ioctl failed with errno %d\n", errno); linuxdvb_err("VIDEO_FAST_FORWARD: %s\n", strerror(errno)); ret = cERR_LINUXDVB_ERROR; } + releaseLinuxDVBMutex(FILENAME, __FUNCTION__, __LINE__); } + linuxdvb_printf(10, "exiting with value %d\n", ret); + return ret; } #else @@ -508,38 +587,54 @@ int LinuxDvbFastForward(Context_t *context, char *type) int speedIndex; unsigned char video = !strcmp("video", type); unsigned char audio = !strcmp("audio", type); + linuxdvb_printf(10, "v%d a%d\n", video, audio); + if (video && videofd != -1) { + getLinuxDVBMutex(FILENAME, __FUNCTION__, __LINE__); + speedIndex = context->playback->Speed % (sizeof(SpeedList) / sizeof(int)); + linuxdvb_printf(1, "speedIndex %d\n", speedIndex); + if (ioctl(videofd, VIDEO_SET_SPEED, SpeedList[speedIndex]) == -1) { linuxdvb_err("ioctl failed with errno %d\n", errno); linuxdvb_err("VIDEO_SET_SPEED: %s\n", strerror(errno)); ret = cERR_LINUXDVB_ERROR; } + releaseLinuxDVBMutex(FILENAME, __FUNCTION__, __LINE__); } + if (audio && audiofd != -1) { + getLinuxDVBMutex(FILENAME, __FUNCTION__, __LINE__); + speedIndex = context->playback->Speed % (sizeof(SpeedList) / sizeof(int)); + linuxdvb_printf(1, "speedIndex %d\n", speedIndex); + if (ioctl(audiofd, AUDIO_SET_SPEED, SpeedList[speedIndex]) == -1) { linuxdvb_err("ioctl failed with errno %d\n", errno); linuxdvb_err("AUDIO_SET_SPEED: %s\n", strerror(errno)); ret = cERR_LINUXDVB_ERROR; } + releaseLinuxDVBMutex(FILENAME, __FUNCTION__, __LINE__); } + linuxdvb_printf(10, "exiting with value %d\n", ret); + return ret; } #endif + int LinuxDvbReverse(Context_t *context __attribute__((unused)), char *type __attribute__((unused))) { int ret = cERR_LINUXDVB_NO_ERROR; @@ -549,12 +644,16 @@ int LinuxDvbReverse(Context_t *context __attribute__((unused)), char *type __att int LinuxDvbSlowMotion(Context_t *context, char *type) { int ret = cERR_LINUXDVB_NO_ERROR; + unsigned char video = !strcmp("video", type); unsigned char audio = !strcmp("audio", type); + linuxdvb_printf(10, "v%d a%d\n", video, audio); + if ((video && videofd != -1) || (audio && audiofd != -1)) { getLinuxDVBMutex(FILENAME, __FUNCTION__, __LINE__); + if (video && videofd != -1) { if (ioctl(videofd, VIDEO_SLOWMOTION, context->playback->SlowMotion) == -1) @@ -564,9 +663,12 @@ int LinuxDvbSlowMotion(Context_t *context, char *type) ret = cERR_LINUXDVB_ERROR; } } + releaseLinuxDVBMutex(FILENAME, __FUNCTION__, __LINE__); } + linuxdvb_printf(10, "exiting with value %d\n", ret); + return ret; } @@ -582,14 +684,17 @@ int LinuxDvbAVSync(Context_t *context, char *type __attribute__((unused))) if (audiofd != -1) { getLinuxDVBMutex(FILENAME, __FUNCTION__, __LINE__); + if (ioctl(audiofd, AUDIO_SET_AV_SYNC, context->playback->AVSync) == -1) { linuxdvb_err("ioctl failed with errno %d\n", errno); linuxdvb_err("AUDIO_SET_AV_SYNC: %s\n", strerror(errno)); ret = cERR_LINUXDVB_ERROR; } + releaseLinuxDVBMutex(FILENAME, __FUNCTION__, __LINE__); } + return ret; } @@ -598,10 +703,13 @@ int LinuxDvbClear(Context_t *context __attribute__((unused)), char *type) int32_t ret = cERR_LINUXDVB_NO_ERROR; uint8_t video = !strcmp("video", type); uint8_t audio = !strcmp("audio", type); + linuxdvb_printf(10, ">>>>>>>>>>LinuxDvbClear v%d a%d\n", video, audio); + if ((video && videofd != -1) || (audio && audiofd != -1)) { getLinuxDVBMutex(FILENAME, __FUNCTION__, __LINE__); + if (video && videofd != -1) { if (ioctl(videofd, VIDEO_CLEAR_BUFFER) == -1) @@ -620,18 +728,24 @@ int LinuxDvbClear(Context_t *context __attribute__((unused)), char *type) ret = cERR_LINUXDVB_ERROR; } } + releaseLinuxDVBMutex(FILENAME, __FUNCTION__, __LINE__); } + linuxdvb_printf(10, "exiting\n"); + return ret; } int LinuxDvbPts(Context_t *context __attribute__((unused)), unsigned long long int *pts) { int ret = cERR_LINUXDVB_ERROR; + linuxdvb_printf(50, "\n"); + // pts is a non writting requests and can be done in parallel to other requests //getLinuxDVBMutex(FILENAME, __FUNCTION__,__LINE__); + if (videofd > -1 && !ioctl(videofd, VIDEO_GET_PTS, (void *)&sCURRENT_PTS)) { ret = cERR_LINUXDVB_NO_ERROR; @@ -640,6 +754,7 @@ int LinuxDvbPts(Context_t *context __attribute__((unused)), unsigned long long i { linuxdvb_err("VIDEO_GET_PTS: %d (%s)\n", errno, strerror(errno)); } + if (ret != cERR_LINUXDVB_NO_ERROR) { if (audiofd > -1 && !ioctl(audiofd, AUDIO_GET_PTS, (void *)&sCURRENT_PTS)) @@ -651,12 +766,16 @@ int LinuxDvbPts(Context_t *context __attribute__((unused)), unsigned long long i linuxdvb_err("AUDIO_GET_PTS: %d (%s)\n", errno, strerror(errno)); } } + if (ret != cERR_LINUXDVB_NO_ERROR) { sCURRENT_PTS = 0; } + *((unsigned long long int *)pts) = (unsigned long long int)sCURRENT_PTS; + //releaseLinuxDVBMutex(FILENAME, __FUNCTION__,__LINE__); + return ret; } @@ -664,8 +783,11 @@ int LinuxDvbGetFrameCount(Context_t *context __attribute__((unused)), unsigned l { int ret = cERR_LINUXDVB_NO_ERROR; dvb_play_info_t playInfo; + linuxdvb_printf(50, "\n"); + getLinuxDVBMutex(FILENAME, __FUNCTION__, __LINE__); + if (videofd != -1) { if (ioctl(videofd, VIDEO_GET_PLAY_INFO, (void *)&playInfo) == -1) @@ -690,9 +812,12 @@ int LinuxDvbGetFrameCount(Context_t *context __attribute__((unused)), unsigned l { ret = cERR_LINUXDVB_ERROR; } + if (ret == cERR_LINUXDVB_NO_ERROR) *((unsigned long long int *)frameCount) = playInfo.frame_count; + releaseLinuxDVBMutex(FILENAME, __FUNCTION__, __LINE__); + return ret; } @@ -701,28 +826,38 @@ int LinuxDvbSwitch(Context_t *context, char *type) unsigned char audio = !strcmp("audio", type); unsigned char video = !strcmp("video", type); Writer_t *writer; + linuxdvb_printf(10, "v%d a%d\n", video, audio); + if ((video && videofd != -1) || (audio && audiofd != -1)) { getLinuxDVBMutex(FILENAME, __FUNCTION__, __LINE__); + if (audio && audiofd != -1) { char *Encoding = NULL; if (context && context->manager && context->manager->audio) { context->manager->audio->Command(context, MANAGER_GETENCODING, &Encoding); + linuxdvb_printf(10, "A %s\n", Encoding); + writer = getWriter(Encoding); + if (ioctl(audiofd, AUDIO_STOP, NULL) == -1) { linuxdvb_err("ioctl failed with errno %d\n", errno); linuxdvb_err("AUDIO_STOP: %s\n", strerror(errno)); + } + 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 (writer == NULL) { linuxdvb_err("cannot found writer for encoding %s using default\n", Encoding); @@ -741,6 +876,7 @@ int LinuxDvbSwitch(Context_t *context, char *type) linuxdvb_err("AUDIO_SET_ENCODING: %s\n", strerror(errno)); } } + if (ioctl(audiofd, AUDIO_PLAY, NULL) == -1) { linuxdvb_err("ioctl failed with errno %d\n", errno); @@ -753,24 +889,30 @@ int LinuxDvbSwitch(Context_t *context, char *type) linuxdvb_printf(20, "no context for Audio\n"); } } + if (video && videofd != -1) { char *Encoding = NULL; if (context && context->manager && context->manager->video) { context->manager->video->Command(context, MANAGER_GETENCODING, &Encoding); + if (ioctl(videofd, VIDEO_STOP, NULL) == -1) { linuxdvb_err("ioctl failed with errno %d\n", errno); linuxdvb_err("VIDEO_STOP: %s\n", strerror(errno)); } + 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)); } + linuxdvb_printf(10, "V %s\n", Encoding); + writer = getWriter(Encoding); + if (writer == NULL) { linuxdvb_err("cannot found writer for encoding %s using default\n", Encoding); @@ -789,6 +931,7 @@ int LinuxDvbSwitch(Context_t *context, char *type) linuxdvb_err("VIDEO_SET_ENCODING: %s\n", strerror(errno)); } } + if (ioctl(videofd, VIDEO_PLAY, NULL) == -1) { /* konfetti: fixme: think on this, I think we should @@ -804,9 +947,13 @@ int LinuxDvbSwitch(Context_t *context, char *type) linuxdvb_printf(20, "no context for Video\n"); } } + releaseLinuxDVBMutex(FILENAME, __FUNCTION__, __LINE__); + } + linuxdvb_printf(10, "exiting\n"); + return cERR_LINUXDVB_NO_ERROR; } @@ -820,27 +967,35 @@ static int Write(void *_context, void *_out) unsigned char audio = 0; Writer_t *writer; WriterAVCallData_t call; + if (out == NULL) { linuxdvb_err("null pointer passed\n"); return cERR_LINUXDVB_ERROR; } + video = !strcmp("video", out->type); audio = !strcmp("audio", out->type); + linuxdvb_printf(20, "DataLength=%u PrivateLength=%u Pts=%llu FrameRate=%f\n", out->len, out->extralen, out->pts, out->frameRate); linuxdvb_printf(20, "v%d a%d\n", video, audio); + if (video) { char *Encoding = NULL; context->manager->video->Command(context, MANAGER_GETENCODING, &Encoding); + linuxdvb_printf(20, "Encoding = %s\n", Encoding); + writer = getWriter(Encoding); + if (writer == NULL) { linuxdvb_printf(20, "searching default writer ... %s\n", Encoding); writer = getDefaultVideoWriter(); } + if (writer == NULL) { linuxdvb_err("unknown video codec and no default writer %s\n", Encoding); @@ -891,6 +1046,7 @@ static int Write(void *_context, void *_out) } } } + call.fd = videofd; call.data = out->data; call.len = out->len; @@ -904,10 +1060,12 @@ static int Write(void *_context, void *_out) call.Height = out->height; call.InfoFlags = out->infoFlags; call.Version = 0; // is unsingned char + if (writer->writeData) { res = writer->writeData(&call); } + if (res < 0) { linuxdvb_err("failed to write data %d - %d\n", res, errno); @@ -915,19 +1073,24 @@ static int Write(void *_context, void *_out) ret = cERR_LINUXDVB_ERROR; } } + free(Encoding); } else if (audio) { char *Encoding = NULL; context->manager->audio->Command(context, MANAGER_GETENCODING, &Encoding); + linuxdvb_printf(20, "%s::%s Encoding = %s\n", FILENAME, __FUNCTION__, Encoding); + writer = getWriter(Encoding); + if (writer == NULL) { linuxdvb_printf(20, "searching default writer ... %s\n", Encoding); writer = getDefaultAudioWriter(); } + if (writer == NULL) { linuxdvb_err("unknown audio codec %s and no default writer\n", Encoding); @@ -946,10 +1109,12 @@ static int Write(void *_context, void *_out) call.FrameScale = out->timeScale; call.InfoFlags = out->infoFlags; call.Version = 0; /* -1; unsigned char cannot be negative */ + if (writer->writeData) { res = writer->writeData(&call); } + if (res < 0) { linuxdvb_err("failed to write data %d - %d\n", res, errno); @@ -957,8 +1122,10 @@ static int Write(void *_context, void *_out) ret = cERR_LINUXDVB_ERROR; } } + free(Encoding); } + return ret; } @@ -967,8 +1134,11 @@ static int reset(Context_t *context) int ret = cERR_LINUXDVB_NO_ERROR; Writer_t *writer; char *Encoding = NULL; + context->manager->video->Command(context, MANAGER_GETENCODING, &Encoding); + writer = getWriter(Encoding); + if (writer == NULL) { linuxdvb_err("unknown video codec %s\n", Encoding); @@ -978,9 +1148,13 @@ static int reset(Context_t *context) { writer->reset(); } + free(Encoding); + context->manager->audio->Command(context, MANAGER_GETENCODING, &Encoding); + writer = getWriter(Encoding); + if (writer == NULL) { linuxdvb_err("unknown video codec %s\n", Encoding); @@ -990,7 +1164,9 @@ static int reset(Context_t *context) { writer->reset(); } + free(Encoding); + return ret; } @@ -998,7 +1174,9 @@ static int Command(void *_context, OutputCmd_t command, void *argument) { Context_t *context = (Context_t *) _context; int ret = cERR_LINUXDVB_NO_ERROR; + linuxdvb_printf(50, "Command %d\n", command); + switch (command) { case OUTPUT_OPEN: @@ -1110,7 +1288,9 @@ static int Command(void *_context, OutputCmd_t command, void *argument) ret = cERR_LINUXDVB_ERROR; break; } + linuxdvb_printf(50, "exiting with value %d\n", ret); + return ret; } diff --git a/libeplayer3-arm/output/output.c b/libeplayer3-arm/output/output.c index 8c1580f..d63f30c 100644 --- a/libeplayer3-arm/output/output.c +++ b/libeplayer3-arm/output/output.c @@ -77,14 +77,16 @@ static Output_t *AvailableOutput[] = /* ***************************** */ /* ***************************** */ -/* Functions */ +/* MISC Functions */ /* ***************************** */ static void printOutputCapabilities() { int i, j; + output_printf(10, "%s::%s\n", __FILE__, __FUNCTION__); output_printf(10, "Capabilities:\n"); + for (i = 0; AvailableOutput[i] != NULL; i++) { output_printf(10, "\t%s : ", AvailableOutput[i]->Name); @@ -103,7 +105,9 @@ static void printOutputCapabilities() static void OutputAdd(Context_t *context, char *port) { int i, j; + output_printf(10, "%s::%s\n", __FILE__, __FUNCTION__); + for (i = 0; AvailableOutput[i] != NULL; i++) { for (j = 0; AvailableOutput[i]->Capabilities[j] != NULL; j++) @@ -133,6 +137,7 @@ static void OutputAdd(Context_t *context, char *port) static void OutputDel(Context_t *context, char *port) { output_printf(10, "%s::%s\n", __FILE__, __FUNCTION__); + if (!strcmp("audio", port)) { context->output->audio = NULL; @@ -150,7 +155,9 @@ static void OutputDel(Context_t *context, char *port) static int Command(Context_t *context, OutputCmd_t command, void *argument) { int ret = cERR_OUTPUT_NO_ERROR; + output_printf(10, "%s::%s Command %d\n", __FILE__, __FUNCTION__, command); + switch (command) { case OUTPUT_OPEN: @@ -562,7 +569,9 @@ static int Command(Context_t *context, OutputCmd_t command, void *argument) ret = cERR_OUTPUT_INTERNAL_ERROR; break; } + output_printf(10, "%s::%s exiting with value %d\n", __FILE__, __FUNCTION__, ret); + return ret; } diff --git a/libeplayer3-arm/output/output_subtitle.c b/libeplayer3-arm/output/output_subtitle.c index 726d230..16fc2bb 100644 --- a/libeplayer3-arm/output/output_subtitle.c +++ b/libeplayer3-arm/output/output_subtitle.c @@ -82,6 +82,7 @@ Number, Style, Name,, MarginL, MarginR, MarginV, Effect,, Text /* Types */ /* ***************************** */ + /* ***************************** */ /* Variables */ /* ***************************** */ @@ -94,19 +95,22 @@ static int isSubtitleOpened = 0; /* ***************************** */ /* ***************************** */ -/* Functions */ +/* MISC Functions */ /* ***************************** */ static void getMutex(int line __attribute__((unused))) { subtitle_printf(100, "%d requesting mutex\n", line); + pthread_mutex_lock(&mutex); + subtitle_printf(100, "%d received mutex\n", line); } static void releaseMutex(int line __attribute__((unused))) { pthread_mutex_unlock(&mutex); + subtitle_printf(100, "%d released mutex\n", line); } @@ -176,6 +180,7 @@ static char *json_string_escape(char *str) *ptr1++ = *ptr2; break; } + ++ptr2; } *ptr1 = '\0'; @@ -193,25 +198,32 @@ static int Write(Context_t *context, void *data) char *Encoding = NULL; SubtitleOut_t *out = NULL; int32_t curtrackid = -1; + subtitle_printf(10, "\n"); + if (data == NULL) { subtitle_err("null pointer passed\n"); return cERR_SUBTITLE_ERROR; } + out = (SubtitleOut_t *) data; + context->manager->subtitle->Command(context, MANAGER_GET, &curtrackid); if (curtrackid != (int32_t)out->trackId) { Flush(); } context->manager->subtitle->Command(context, MANAGER_GETENCODING, &Encoding); + if (Encoding == NULL) { subtitle_err("encoding unknown\n"); return cERR_SUBTITLE_ERROR; } + subtitle_printf(20, "Encoding:%s Text:%s Len:%d\n", Encoding, (const char *) out->data, out->len); + if (!strncmp("S_TEXT/SUBRIP", Encoding, 13)) { fprintf(stderr, "{\"s_a\":{\"id\":%d,\"s\":%lld,\"e\":%lld,\"t\":\"%s\"}}\n", out->trackId, out->pts / 90, out->pts / 90 + out->durationMS, json_string_escape((char *)out->data)); @@ -225,6 +237,7 @@ static int Write(Context_t *context, void *data) subtitle_err("unknown encoding %s\n", Encoding); return cERR_SUBTITLE_ERROR; } + subtitle_printf(10, "<\n"); return cERR_SUBTITLE_NO_ERROR; } @@ -232,15 +245,21 @@ static int Write(Context_t *context, void *data) static int32_t subtitle_Open(Context_t *context __attribute__((unused))) { //uint32_t i = 0 ; + subtitle_printf(10, "\n"); + if (isSubtitleOpened == 1) { subtitle_err("already opened! ignoring\n"); return cERR_SUBTITLE_ERROR; } + getMutex(__LINE__); + isSubtitleOpened = 1; + releaseMutex(__LINE__); + subtitle_printf(10, "<\n"); return cERR_SUBTITLE_NO_ERROR; } @@ -248,18 +267,26 @@ static int32_t subtitle_Open(Context_t *context __attribute__((unused))) static int32_t subtitle_Close(Context_t *context __attribute__((unused))) { //uint32_t i = 0 ; + subtitle_printf(10, "\n"); + getMutex(__LINE__); + isSubtitleOpened = 0; + releaseMutex(__LINE__); + subtitle_printf(10, "<\n"); + return cERR_SUBTITLE_NO_ERROR; } static int Command(Context_t *context, OutputCmd_t command, void *argument __attribute__((unused))) { int ret = cERR_SUBTITLE_NO_ERROR; + subtitle_printf(50, "%d\n", command); + switch (command) { case OUTPUT_OPEN: @@ -312,10 +339,12 @@ static int Command(Context_t *context, OutputCmd_t command, void *argument __att ret = cERR_SUBTITLE_ERROR; break; } + subtitle_printf(50, "exiting with value %d\n", ret); return ret; } + static char *SubtitleCapabilitis[] = { "subtitle", NULL }; Output_t SubtitleOutput = diff --git a/libeplayer3-arm/output/writer/common/misc.c b/libeplayer3-arm/output/writer/common/misc.c index c9c18af..71c5ec1 100644 --- a/libeplayer3-arm/output/writer/common/misc.c +++ b/libeplayer3-arm/output/writer/common/misc.c @@ -69,12 +69,15 @@ void PutBits(BitPacker_t *ld, unsigned int code, unsigned int length) { unsigned int bit_buf; unsigned int bit_left; + bit_buf = ld->BitBuffer; bit_left = ld->Remaining; + #ifdef DEBUG_PUTBITS if (ld->debug) dprintf("code = %d, length = %d, bit_buf = 0x%x, bit_left = %d\n", code, length, bit_buf, bit_left); #endif /* DEBUG_PUTBITS */ + if (length < bit_left) { /* fits into current buffer */ @@ -96,10 +99,12 @@ void PutBits(BitPacker_t *ld, unsigned int code, unsigned int length) bit_left = 32 - length; bit_buf = code; } + #ifdef DEBUG_PUTBITS if (ld->debug) dprintf("bit_left = %d, bit_buf = 0x%x\n", bit_left, bit_buf); #endif /* DEBUG_PUTBITS */ + /* writeback */ ld->BitBuffer = bit_buf; ld->Remaining = bit_left; diff --git a/libeplayer3-arm/output/writer/common/pes.c b/libeplayer3-arm/output/writer/common/pes.c index fea8dc3..e4788c5 100644 --- a/libeplayer3-arm/output/writer/common/pes.c +++ b/libeplayer3-arm/output/writer/common/pes.c @@ -57,6 +57,7 @@ /* Types */ /* ***************************** */ + /* ***************************** */ /* Varaibles */ /* ***************************** */ @@ -73,25 +74,32 @@ int32_t InsertVideoPrivateDataHeader(uint8_t *data, int32_t payload_size) { BitPacker_t ld2 = {data, 0, 32}; int32_t i = 0; + PutBits(&ld2, PES_PRIVATE_DATA_FLAG, 8); PutBits(&ld2, payload_size & 0xff, 8); PutBits(&ld2, (payload_size >> 8) & 0xff, 8); PutBits(&ld2, (payload_size >> 16) & 0xff, 8); + for (i = 4; i < (PES_PRIVATE_DATA_LENGTH + 1); i++) { PutBits(&ld2, 0, 8); } + FlushBits(&ld2); + return PES_PRIVATE_DATA_LENGTH + 1; + } int32_t InsertPesHeader(uint8_t *data, int32_t size, uint8_t stream_id, uint64_t pts, int32_t pic_start_code) { BitPacker_t ld2 = {data, 0, 32}; + if (size > (MAX_PES_PACKET_SIZE - 13)) { size = -1; // unbounded } + PutBits(&ld2, 0x0, 8); PutBits(&ld2, 0x0, 8); PutBits(&ld2, 0x1, 8); // Start Code @@ -113,6 +121,7 @@ int32_t InsertPesHeader(uint8_t *data, int32_t size, uint8_t stream_id, uint64_t PutBits(&ld2, 0x0, 1); // Copyright PutBits(&ld2, 0x0, 1); // Original or Copy //7 = 6+1 + if (pts != INVALID_PTS_VALUE) { PutBits(&ld2, 0x2, 2); @@ -121,6 +130,7 @@ int32_t InsertPesHeader(uint8_t *data, int32_t size, uint8_t stream_id, uint64_t { PutBits(&ld2, 0x0, 2); // PTS_DTS flag } + PutBits(&ld2, 0x0, 1); // ESCR_flag PutBits(&ld2, 0x0, 1); // ES_rate_flag PutBits(&ld2, 0x0, 1); // DSM_trick_mode_flag @@ -128,6 +138,7 @@ int32_t InsertPesHeader(uint8_t *data, int32_t size, uint8_t stream_id, uint64_t PutBits(&ld2, 0x0, 1); // PES_CRC_flag PutBits(&ld2, 0x0, 1); // PES_extension_flag //8 = 7+1 + if (pts != INVALID_PTS_VALUE) { PutBits(&ld2, 0x5, 8); @@ -137,6 +148,7 @@ int32_t InsertPesHeader(uint8_t *data, int32_t size, uint8_t stream_id, uint64_t PutBits(&ld2, 0x0, 8); // PES_header_data_length } //9 = 8+1 + if (pts != INVALID_PTS_VALUE) { PutBits(&ld2, 0x2, 4); @@ -148,6 +160,7 @@ int32_t InsertPesHeader(uint8_t *data, int32_t size, uint8_t stream_id, uint64_t PutBits(&ld2, 0x1, 1); } //14 = 9+5 + if (pic_start_code) { PutBits(&ld2, 0x0, 8); @@ -157,6 +170,8 @@ int32_t InsertPesHeader(uint8_t *data, int32_t size, uint8_t stream_id, uint64_t PutBits(&ld2, (pic_start_code >> 8) & 0xff, 8); // For any extra information (like in mpeg4p2, the pic_start_code) //14 + 4 = 18 } + FlushBits(&ld2); + return (ld2.Ptr - data); } diff --git a/libeplayer3-arm/output/writer/mipsel/aac.c b/libeplayer3-arm/output/writer/mipsel/aac.c index 90b48c7..4ec234b 100644 --- a/libeplayer3-arm/output/writer/mipsel/aac.c +++ b/libeplayer3-arm/output/writer/mipsel/aac.c @@ -143,7 +143,7 @@ LATMContext *pLATMCtx = NULL; /* ***************************** */ /* ***************************** */ -/* Functions */ +/* MISC Functions */ /* ***************************** */ static int reset() @@ -159,16 +159,19 @@ static int reset() static int _writeData(WriterAVCallData_t *call, int type) { aac_printf(10, "\n _writeData type[%d]\n", type); + if (call == NULL) { aac_err("call data is NULL...\n"); return 0; } + if ((call->data == NULL) || (call->len < 8)) { aac_err("parsing Data with missing AAC header. ignoring...\n"); return 0; } + /* simple validation */ if (0 == type) // check ADTS header { @@ -195,9 +198,13 @@ static int _writeData(WriterAVCallData_t *call, int type) return 0; } } + unsigned char PesHeader[PES_MAX_HEADER_SIZE]; + aac_printf(10, "AudioPts %lld\n", call->Pts); + unsigned int HeaderLength = InsertPesHeader(PesHeader, call->len, MPEG_AUDIO_PES_START_CODE, call->Pts, 0); + struct iovec iov[2]; iov[0].iov_base = PesHeader; iov[0].iov_len = HeaderLength; @@ -209,31 +216,37 @@ static int _writeData(WriterAVCallData_t *call, int type) static int writeDataADTS(WriterAVCallData_t *call) { aac_printf(10, "\n"); + if (call == NULL) { aac_err("call data is NULL...\n"); return 0; } + if ((call->data == NULL) || (call->len <= 0)) { aac_err("parsing NULL Data. ignoring...\n"); return 0; } + if (call->fd < 0) { aac_err("file pointer < 0. ignoring ...\n"); return 0; } + if ((call->private_data && 0 == strncmp("ADTS", (const char *)call->private_data, call->private_size)) || HasADTSHeader(call->data, call->len)) { //printf("%hhx %hhx %hhx %hhx %hhx %hhx %hhx %hhx\n", call->data[0], call->data[1], call->data[2], call->data[3], call->data[4], call->data[5], call->data[6], call->data[7]); return _writeData(call, 0); } + uint32_t PacketLength = call->len + AAC_HEADER_LENGTH; uint8_t PesHeader[PES_MAX_HEADER_SIZE + AAC_HEADER_LENGTH]; uint32_t headerSize = InsertPesHeader(PesHeader, PacketLength, MPEG_AUDIO_PES_START_CODE, call->Pts, 0); uint8_t *pExtraData = &PesHeader[headerSize]; + aac_printf(10, "AudioPts %lld\n", call->Pts); if (call->private_data == NULL) { @@ -244,6 +257,7 @@ static int writeDataADTS(WriterAVCallData_t *call) { memcpy(pExtraData, call->private_data, AAC_HEADER_LENGTH); } + pExtraData[3] &= 0xC0; /* frame size over last 2 bits */ pExtraData[3] |= (PacketLength & 0x1800) >> 11; @@ -256,33 +270,41 @@ static int writeDataADTS(WriterAVCallData_t *call) /* buffer fullness(0x7FF for VBR) continued over 6 first bits + 2 zeros for * number of raw data blocks */ pExtraData[6] = 0xFC; + //PesHeader[6] = 0x81; + struct iovec iov[2]; iov[0].iov_base = PesHeader; iov[0].iov_len = headerSize + AAC_HEADER_LENGTH; iov[1].iov_base = call->data; iov[1].iov_len = call->len; + return call->WriteV(call->fd, iov, 2); } static int writeDataLATM(WriterAVCallData_t *call) { aac_printf(10, "\n"); + if (call == NULL) { aac_err("call data is NULL...\n"); return 0; } + if ((call->data == NULL) || (call->len <= 0)) { aac_err("parsing NULL Data. ignoring...\n"); return 0; } + if (call->private_data && 0 == strncmp("LATM", (const char *)call->private_data, call->private_size)) { return _writeData(call, 1); } + aac_printf(10, "AudioPts %lld\n", call->Pts); + if (!pLATMCtx) { pLATMCtx = malloc(sizeof(LATMContext)); @@ -290,11 +312,13 @@ static int writeDataLATM(WriterAVCallData_t *call) pLATMCtx->mod = 14; pLATMCtx->counter = 0; } + if (!pLATMCtx) { aac_err("parsing NULL pLATMCtx. ignoring...\n"); return 0; } + unsigned char PesHeader[PES_MAX_HEADER_SIZE]; int ret = latmenc_decode_extradata(pLATMCtx, call->private_data, call->private_size); if (ret) @@ -310,14 +334,19 @@ static int writeDataLATM(WriterAVCallData_t *call) aac_err("latm_write_packet failed. ignoring...\n"); return 0; } + unsigned int HeaderLength = InsertPesHeader(PesHeader, pLATMCtx->len + 3, MPEG_AUDIO_PES_START_CODE, call->Pts, 0); + struct iovec iov[3]; iov[0].iov_base = PesHeader; iov[0].iov_len = HeaderLength; + iov[1].iov_base = pLATMCtx->loas_header; iov[1].iov_len = 3; + iov[2].iov_base = pLATMCtx->buffer; iov[2].iov_len = pLATMCtx->len; + return call->WriteV(call->fd, iov, 3); } diff --git a/libeplayer3-arm/output/writer/mipsel/ac3.c b/libeplayer3-arm/output/writer/mipsel/ac3.c index 37ee989..12ade9a 100644 --- a/libeplayer3-arm/output/writer/mipsel/ac3.c +++ b/libeplayer3-arm/output/writer/mipsel/ac3.c @@ -98,34 +98,45 @@ static int reset() static int writeData(WriterAVCallData_t *call) { ac3_printf(10, "\n"); + unsigned char PesHeader[PES_MAX_HEADER_SIZE]; + if (call == NULL) { ac3_err("call data is NULL...\n"); return 0; } + ac3_printf(10, "AudioPts %lld\n", call->Pts); + if ((call->data == NULL) || (call->len <= 0)) { ac3_err("parsing NULL Data. ignoring...\n"); return 0; } + if (call->fd < 0) { ac3_err("file pointer < 0. ignoring ...\n"); return 0; } + struct iovec iov[3]; + iov[0].iov_base = PesHeader; iov[0].iov_len = InsertPesHeader(PesHeader, call->len, MPEG_AUDIO_PES_START_CODE, call->Pts, 0); //+ sizeof(AC3_SYNC_HEADER) + //PesHeader[6] = 0x81; //PesHeader[7] = 0x80; //PesHeader[8] = 0x09; + //iov[1].iov_base = AC3_SYNC_HEADER; //iov[1].iov_len = sizeof(AC3_SYNC_HEADER); iov[1].iov_base = call->data; iov[1].iov_len = call->len; + ac3_printf(40, "PES HEADER LEN %d\n", iov[0].iov_len); + return call->WriteV(call->fd, iov, 2); } diff --git a/libeplayer3-arm/output/writer/mipsel/amr.c b/libeplayer3-arm/output/writer/mipsel/amr.c index d509ea5..98cc1a4 100644 --- a/libeplayer3-arm/output/writer/mipsel/amr.c +++ b/libeplayer3-arm/output/writer/mipsel/amr.c @@ -99,23 +99,29 @@ static int reset() static int writeData(WriterAVCallData_t *call) { unsigned char PesHeader[PES_MAX_HEADER_SIZE + 4 + 9]; + amr_printf(10, "\n"); + if (call == NULL) { amr_err("call data is NULL...\n"); return 0; } + amr_printf(10, "AudioPts %lld\n", call->Pts); + if ((call->data == NULL) || (call->len <= 0)) { amr_err("parsing NULL Data. ignoring...\n"); return 0; } + if (call->fd < 0) { amr_err("file pointer < 0. ignoring ...\n"); return 0; } + uint8_t hasCodecData = 1; if (NULL != call->private_data && call->private_size >= 17) { @@ -128,11 +134,13 @@ static int writeData(WriterAVCallData_t *call) payload_len += 9; } payload_len += 4; + uint32_t headerSize = InsertPesHeader(PesHeader, payload_len, MPEG_AUDIO_PES_START_CODE, call->Pts, 0); PesHeader[headerSize++] = (payload_len >> 24) & 0xff; PesHeader[headerSize++] = (payload_len >> 16) & 0xff; PesHeader[headerSize++] = (payload_len >> 8) & 0xff; PesHeader[headerSize++] = payload_len & 0xff; + if (hasCodecData) { uint8_t tmp[] = {0x45, 0x4d, 0x50, 0x20, 0x00, 0x00, 0x80, 0x00, 0x01}; @@ -140,12 +148,15 @@ static int writeData(WriterAVCallData_t *call) //memcpy(&PesHeader[headerSize], call->private_data + 8, 9); //memset(&PesHeader[headerSize], 0, 9); } + struct iovec iov[2]; iov[0].iov_base = PesHeader; iov[0].iov_len = headerSize; iov[1].iov_base = call->data; iov[1].iov_len = call->len; + int len = call->WriteV(call->fd, iov, 2); + amr_printf(10, "amr_Write-< len=%d\n", len); return len; } diff --git a/libeplayer3-arm/output/writer/mipsel/divx3.c b/libeplayer3-arm/output/writer/mipsel/divx3.c index de7ebab..d4de31f 100644 --- a/libeplayer3-arm/output/writer/mipsel/divx3.c +++ b/libeplayer3-arm/output/writer/mipsel/divx3.c @@ -118,25 +118,32 @@ static int writeData(WriterAVCallData_t *call) unsigned char PesHeader[PES_MAX_HEADER_SIZE + 4]; // unsigned char Version = 5; // unsigned int FakeStartCode = (Version << 8) | PES_VERSION_FAKE_START_CODE; + divx_printf(10, "\n"); + if (call == NULL) { divx_err("call data is NULL...\n"); return 0; } + if ((call->data == NULL) || (call->len <= 0)) { divx_err("parsing NULL Data. ignoring...\n"); return 0; } + if (call->fd < 0) { divx_err("file pointer < 0. ignoring ...\n"); return 0; } + divx_printf(10, "AudioPts %lld\n", call->Pts); + struct iovec iov[8]; int ic = 0; + if (initialHeader) { initialHeader = 0; @@ -151,11 +158,14 @@ static int writeData(WriterAVCallData_t *call) data[2] = B_GET_BITS(height, 9, 2); data[3] = B_SET_BITS("height [1.0]", B_GET_BITS(height, 1, 0), 7, 6) | B_SET_BITS("'100000'", 0x20, 5, 0); + iov[ic].iov_base = brcm_divx311_sequence_header; iov[ic++].iov_len = sizeof(brcm_divx311_sequence_header); } + iov[ic].iov_base = PesHeader; uint32_t headerSize = 0; + if (memcmp(call->data, "\x00\x00\x01\xb6", 4)) { headerSize = InsertPesHeader(PesHeader, call->len + 4, MPEG_VIDEO_PES_START_CODE, call->Pts, 0); @@ -167,10 +177,14 @@ static int writeData(WriterAVCallData_t *call) headerSize = InsertPesHeader(PesHeader, call->len, MPEG_VIDEO_PES_START_CODE, call->Pts, 0); } iov[ic++].iov_len = headerSize; + iov[ic].iov_base = call->data; iov[ic++].iov_len = call->len; - int len = call->WriteV(call->fd, iov, ic); + + int len = call->WriteV(call->fd, iov, ic); + divx_printf(10, "xvid_Write < len=%d\n", len); + return len; } diff --git a/libeplayer3-arm/output/writer/mipsel/dts.c b/libeplayer3-arm/output/writer/mipsel/dts.c index beb8e28..34548ba 100644 --- a/libeplayer3-arm/output/writer/mipsel/dts.c +++ b/libeplayer3-arm/output/writer/mipsel/dts.c @@ -103,25 +103,32 @@ static int32_t reset() static int writeData(WriterAVCallData_t *call) { uint8_t PesHeader[PES_AUDIO_HEADER_SIZE]; + dts_printf(10, "\n"); + if (call == NULL) { dts_err("call data is NULL...\n"); return 0; } + dts_printf(10, "AudioPts %lld\n", call->Pts); + if ((call->data == NULL) || (call->len <= 0)) { dts_err("parsing NULL Data. ignoring...\n"); return 0; } + if (call->fd < 0) { dts_err("file pointer < 0. ignoring ...\n"); return 0; } + uint8_t *Data = call->data; int32_t Size = call->len; + #ifdef CHECK_FOR_DTS_HD int32_t pos = 0; while ((pos + 4) <= Size) @@ -135,6 +142,7 @@ static int writeData(WriterAVCallData_t *call) ++pos; } #endif + // #define DO_BYTESWAP #ifdef DO_BYTESWAP /* 16-bit byte swap all data before injecting it */ @@ -145,11 +153,13 @@ static int writeData(WriterAVCallData_t *call) Data[i + 1] = Tmp; } #endif + struct iovec iov[2]; iov[0].iov_base = PesHeader; iov[0].iov_len = InsertPesHeader(PesHeader, Size, MPEG_AUDIO_PES_START_CODE, call->Pts, 0); iov[1].iov_base = Data; iov[1].iov_len = Size; + int32_t len = call->WriteV(call->fd, iov, 2); dts_printf(10, "< len %d\n", len); return len; diff --git a/libeplayer3-arm/output/writer/mipsel/h263.c b/libeplayer3-arm/output/writer/mipsel/h263.c index 39c4ed2..1d8b0e5 100644 --- a/libeplayer3-arm/output/writer/mipsel/h263.c +++ b/libeplayer3-arm/output/writer/mipsel/h263.c @@ -95,37 +95,46 @@ static int writeData(WriterAVCallData_t *call) { uint8_t PesHeader[PES_MAX_HEADER_SIZE]; int32_t len = 0; + h263_printf(10, "\n"); + if (call == NULL) { h263_err("call data is NULL...\n"); return 0; } + h263_printf(10, "VideoPts %lld\n", call->Pts); + if ((call->data == NULL) || (call->len <= 0)) { h263_err("NULL Data. ignoring...\n"); return 0; } + if (call->fd < 0) { h263_err("file pointer < 0. ignoring ...\n"); return 0; } + int32_t HeaderLength = InsertPesHeader(PesHeader, call->len, MPEG_VIDEO_PES_START_CODE, call->Pts, 0); int32_t PrivateHeaderLength = InsertVideoPrivateDataHeader(&PesHeader[HeaderLength], call->len); int32_t PesLength = PesHeader[PES_LENGTH_BYTE_0] + (PesHeader[PES_LENGTH_BYTE_1] << 8) + PrivateHeaderLength; + PesHeader[PES_LENGTH_BYTE_0] = PesLength & 0xff; PesHeader[PES_LENGTH_BYTE_1] = (PesLength >> 8) & 0xff; PesHeader[PES_HEADER_DATA_LENGTH_BYTE] += PrivateHeaderLength; PesHeader[PES_FLAGS_BYTE] |= PES_EXTENSION_DATA_PRESENT; HeaderLength += PrivateHeaderLength; + struct iovec iov[2]; iov[0].iov_base = PesHeader; iov[0].iov_len = HeaderLength; iov[1].iov_base = call->data; iov[1].iov_len = call->len; len = call->WriteV(call->fd, iov, 2); + h263_printf(10, "< len %d\n", len); return len; } diff --git a/libeplayer3-arm/output/writer/mipsel/h264.c b/libeplayer3-arm/output/writer/mipsel/h264.c index 4dbf2b6..8fe4be9 100644 --- a/libeplayer3-arm/output/writer/mipsel/h264.c +++ b/libeplayer3-arm/output/writer/mipsel/h264.c @@ -103,34 +103,45 @@ static int sps_pps_in_stream = 0; static int32_t UpdateExtraData(uint8_t **ppExtraData, uint32_t *pExtraDataSize, uint8_t *pData, uint32_t dataSize) { uint8_t *aExtraData = *ppExtraData; + if (aExtraData[0] != 1 || !pData) { // Not AVCC or nothing to update with. return -1; } + int32_t nalsize = (aExtraData[4] & 3) + 1; + uint8_t sps[256]; uint8_t spsIdx = 0; + uint8_t numSps = 0; + uint8_t pps[256]; uint8_t ppsIdx = 0; + uint8_t numPps = 0; + if (nalsize != 4) { return -1; } + // Find SPS and PPS NALUs in AVCC data uint8_t *d = pData; while (d + 4 < pData + dataSize) { uint32_t nalLen = ReadUint32(d); + uint8_t nalType = d[4] & 0x1f; if (nalType == 7) { /* SPS */ + // 16 bits size sps[spsIdx++] = (uint8_t)(0xFF & (nalLen >> 8)); sps[spsIdx++] = (uint8_t)(0xFF & nalLen); + if (spsIdx + nalLen >= sizeof(sps)) { h264_err("SPS no free space to copy...\n"); @@ -138,15 +149,19 @@ static int32_t UpdateExtraData(uint8_t **ppExtraData, uint32_t *pExtraDataSize, } memcpy(&(sps[spsIdx]), d + 4, nalLen); spsIdx += nalLen; + numSps += 1; + h264_printf(10, "SPS len[%u]...\n", nalLen); } else if (nalType == 8) { /* PPS */ + // 16 bits size pps[ppsIdx++] = (uint8_t)(0xFF & (nalLen >> 8)); pps[ppsIdx++] = (uint8_t)(0xFF & nalLen); + if (ppsIdx + nalLen >= sizeof(sps)) { h264_err("PPS not free space to copy...\n"); @@ -154,7 +169,9 @@ static int32_t UpdateExtraData(uint8_t **ppExtraData, uint32_t *pExtraDataSize, } memcpy(&(pps[ppsIdx]), d + 4, nalLen); ppsIdx += nalLen; + numPps += 1; + h264_printf(10, "PPS len[%u]...\n", nalLen); } d += 4 + nalLen; @@ -167,18 +184,21 @@ static int32_t UpdateExtraData(uint8_t **ppExtraData, uint32_t *pExtraDataSize, aExtraData[idx++] = sps[4]; // profile compat aExtraData[idx++] = sps[5]; // level aExtraData[idx++] = 0xff; // nal size - 1 + aExtraData[idx++] = 0xe0 | numSps; if (numSps) { memcpy(&(aExtraData[idx]), sps, spsIdx); idx += spsIdx; } + aExtraData[idx++] = numPps; if (numPps) { memcpy(&(aExtraData[idx]), pps, ppsIdx); idx += ppsIdx; } + h264_printf(10, "aExtraData len[%u]...\n", idx); *pExtraDataSize = idx; return 0; @@ -192,6 +212,7 @@ static int32_t PreparCodecData(unsigned char *data, unsigned int cd_len, unsigne { unsigned char tmp[2048]; unsigned int tmp_len = 0; + unsigned int cd_pos = 0; h264_printf(10, "H264 have codec data..!\n"); if (cd_len > 7 && data[0] == 1) @@ -238,9 +259,11 @@ static int32_t PreparCodecData(unsigned char *data, unsigned int cd_len, unsigne tmp_len += 4; memcpy(tmp + tmp_len, data + cd_pos, len); tmp_len += len; + CodecData = malloc(tmp_len); memcpy(CodecData, tmp, tmp_len); CodecDataLen = tmp_len; + *NalLength = (data[4] & 0x03) + 1; ret = 0; } @@ -297,28 +320,34 @@ static int writeData(WriterAVCallData_t *call) int ic = 0; struct iovec iov[IOVEC_SIZE]; h264_printf(20, "\n"); + if (call == NULL) { h264_err("call data is NULL...\n"); return 0; } + TimeDelta = call->FrameRate; TimeScale = call->FrameScale; /* avoid compiler warnings */ if (TimeDelta) {} if (TimeScale) {} VideoPts = call->Pts; + h264_printf(20, "VideoPts %lld - %d %d\n", call->Pts, TimeDelta, TimeScale); + if ((call->data == NULL) || (call->len <= 0)) { h264_err("NULL Data. ignoring...\n"); return 0; } + if (call->fd < 0) { h264_err("file pointer < 0. ignoring ...\n"); return 0; } + /* AnnexA */ if (!avc3 && ((1 < call->private_size && 0 == call->private_data[0]) || ((call->len > 3) && ((call->data[0] == 0x00 && call->data[1] == 0x00 && call->data[2] == 0x00 && call->data[3] == 0x01) || @@ -329,6 +358,7 @@ static int writeData(WriterAVCallData_t *call) uint32_t PacketLength = 0; uint32_t FakeStartCode = (call->Version << 8) | PES_VERSION_FAKE_START_CODE; iov[ic++].iov_base = PesHeader; + while (InsertPrivData && i < 36 && (call->len - i) > 5) { if ((call->data[i] == 0x00 && call->data[i + 1] == 0x00 && call->data[i + 2] == 0x00 && call->data[i + 3] == 0x01 && (call->data[i + 4] == 0x67 || call->data[i + 4] == 0x68))) @@ -338,6 +368,7 @@ static int writeData(WriterAVCallData_t *call) } i += 1; } + if (InsertPrivData && call->private_size > 0 /*&& initialHeader*/) // some rtsp streams can update codec data at runtime { initialHeader = 0; @@ -345,10 +376,13 @@ static int writeData(WriterAVCallData_t *call) iov[ic++].iov_len = call->private_size; PacketLength += call->private_size; } + iov[ic].iov_base = call->data; iov[ic++].iov_len = call->len; PacketLength += call->len; + iov[0].iov_len = InsertPesHeader(PesHeader, -1, MPEG_VIDEO_PES_START_CODE, VideoPts, FakeStartCode); + return call->WriteV(call->fd, iov, ic); } else if (!call->private_data || call->private_size < 7 || 1 != call->private_data[0]) @@ -356,9 +390,12 @@ static int writeData(WriterAVCallData_t *call) h264_err("No valid private data available! [%d]\n", (int)call->private_size); return 0; } + uint32_t PacketLength = 0; + ic = 0; iov[ic++].iov_base = PesHeader; + //if (initialHeader) { if (CodecData) @@ -366,19 +403,23 @@ static int writeData(WriterAVCallData_t *call) free(CodecData); CodecData = NULL; } + uint8_t *private_data = call->private_data; uint32_t private_size = call->private_size; + if (PreparCodecData(private_data, private_size, &NalLengthBytes)) { UpdateExtraData(&private_data, &private_size, call->data, call->len); PreparCodecData(private_data, private_size, &NalLengthBytes); } + if (private_data != call->private_data) { avc3 = 1; free(private_data); private_data = NULL; } + if (CodecData != NULL) { iov[ic].iov_base = CodecData; @@ -387,6 +428,7 @@ static int writeData(WriterAVCallData_t *call) initialHeader = 0; } } + if (CodecData != NULL) { uint32_t pos = 0; @@ -397,6 +439,7 @@ static int writeData(WriterAVCallData_t *call) h264_err(">> Drop data due to ic overflow\n"); break; } + uint32_t pack_len = 0; uint32_t i = 0; for (i = 0; i < NalLengthBytes; i++, pos++) @@ -404,21 +447,28 @@ static int writeData(WriterAVCallData_t *call) pack_len <<= 8; pack_len += call->data[pos]; } + if ((pos + pack_len) > call->len) { pack_len = call->len - pos; } + iov[ic].iov_base = Head; iov[ic++].iov_len = sizeof(Head); PacketLength += sizeof(Head); + iov[ic].iov_base = call->data + pos; iov[ic++].iov_len = pack_len; PacketLength += pack_len; + pos += pack_len; + } while ((pos + NalLengthBytes) < call->len); + h264_printf(10, "<<<< PacketLength [%d]\n", PacketLength); iov[0].iov_len = InsertPesHeader(PesHeader, -1, MPEG_VIDEO_PES_START_CODE, VideoPts, 0); + len = call->WriteV(call->fd, iov, ic); PacketLength += iov[0].iov_len; if (PacketLength != len) @@ -426,6 +476,7 @@ static int writeData(WriterAVCallData_t *call) h264_err("<<<< not all data have been written [%d/%d]\n", len, PacketLength); } } + h264_printf(10, "< len %d\n", len); return len; } diff --git a/libeplayer3-arm/output/writer/mipsel/h265.c b/libeplayer3-arm/output/writer/mipsel/h265.c index ad59853..1e61411 100644 --- a/libeplayer3-arm/output/writer/mipsel/h265.c +++ b/libeplayer3-arm/output/writer/mipsel/h265.c @@ -105,7 +105,9 @@ static int32_t PreparCodecData(unsigned char *data, unsigned int cd_len, unsigne { unsigned char tmp[2048]; unsigned int tmp_len = 0; + h264_printf(10, "H265 have codec data..!"); + if (cd_len > 3 && (data[0] || data[1] || data[2] > 1)) { if (cd_len > 22) @@ -115,6 +117,7 @@ static int32_t PreparCodecData(unsigned char *data, unsigned int cd_len, unsigne { h264_printf(10, "Unsupported extra data version %d, decoding may fail", (int)data[0]); } + *NalLength = (data[21] & 3) + 1; int num_param_sets = data[22]; uint32_t pos = 23; @@ -150,6 +153,7 @@ static int32_t PreparCodecData(unsigned char *data, unsigned int cd_len, unsigne pos += nal_size; } } + CodecData = malloc(tmp_len); memcpy(CodecData, tmp, tmp_len); CodecDataLen = tmp_len; @@ -160,6 +164,7 @@ static int32_t PreparCodecData(unsigned char *data, unsigned int cd_len, unsigne { *NalLength = 0; } + return ret; } @@ -179,33 +184,40 @@ static int writeData(WriterAVCallData_t *call) int ic = 0; struct iovec iov[IOVEC_SIZE]; h264_printf(20, "\n"); + if (call == NULL) { h264_err("call data is NULL...\n"); return 0; } + TimeDelta = call->FrameRate; TimeScale = call->FrameScale; /* avoid compiler warnings */ if (TimeDelta) {} if (TimeScale) {} VideoPts = call->Pts; + h264_printf(20, "VideoPts %lld - %d %d\n", call->Pts, TimeDelta, TimeScale); + if ((call->data == NULL) || (call->len <= 0)) { h264_err("NULL Data. ignoring...\n"); return 0; } + if (call->fd < 0) { h264_err("file pointer < 0. ignoring ...\n"); return 0; } + if (call->InfoFlags & 0x1) // TS container { h264_printf(10, "H265 simple inject method!\n"); uint32_t PacketLength = 0; uint32_t FakeStartCode = (call->Version << 8) | PES_VERSION_FAKE_START_CODE; + iov[ic++].iov_base = PesHeader; initialHeader = 0; if (initialHeader) @@ -215,17 +227,24 @@ static int writeData(WriterAVCallData_t *call) iov[ic++].iov_len = call->private_size; PacketLength += call->private_size; } + iov[ic].iov_base = ""; iov[ic++].iov_len = 1; + iov[ic].iov_base = call->data; iov[ic++].iov_len = call->len; PacketLength += call->len; + iov[0].iov_len = InsertPesHeader(PesHeader, -1, MPEG_VIDEO_PES_START_CODE, VideoPts, FakeStartCode); + return call->WriteV(call->fd, iov, ic); } + uint32_t PacketLength = 0; + ic = 0; iov[ic++].iov_base = PesHeader; + if (initialHeader) { if (CodecData) @@ -233,9 +252,12 @@ static int writeData(WriterAVCallData_t *call) free(CodecData); CodecData = NULL; } + uint8_t *private_data = call->private_data; uint32_t private_size = call->private_size; + PreparCodecData(private_data, private_size, &NalLengthBytes); + if (CodecData != NULL) { iov[ic].iov_base = CodecData; @@ -244,6 +266,7 @@ static int writeData(WriterAVCallData_t *call) initialHeader = 0; } } + if (CodecData != NULL) { uint32_t pos = 0; @@ -254,6 +277,7 @@ static int writeData(WriterAVCallData_t *call) h264_err(">> Drop data due to ic overflow\n"); break; } + uint32_t pack_len = 0; uint32_t i = 0; for (i = 0; i < NalLengthBytes; i++, pos++) @@ -261,21 +285,28 @@ static int writeData(WriterAVCallData_t *call) pack_len <<= 8; pack_len += call->data[pos]; } + if ((pos + pack_len) > call->len) { pack_len = call->len - pos; } + iov[ic].iov_base = Head; iov[ic++].iov_len = sizeof(Head); PacketLength += sizeof(Head); + iov[ic].iov_base = call->data + pos; iov[ic++].iov_len = pack_len; PacketLength += pack_len; + pos += pack_len; + } while ((pos + NalLengthBytes) < call->len); + h264_printf(10, "<<<< PacketLength [%d]\n", PacketLength); iov[0].iov_len = InsertPesHeader(PesHeader, -1, MPEG_VIDEO_PES_START_CODE, VideoPts, 0); + len = call->WriteV(call->fd, iov, ic); PacketLength += iov[0].iov_len; if (PacketLength != len) @@ -283,6 +314,7 @@ static int writeData(WriterAVCallData_t *call) h264_err("<<<< not all data have been written [%d/%d]\n", len, PacketLength); } } + h264_printf(10, "< len %d\n", len); return len; } diff --git a/libeplayer3-arm/output/writer/mipsel/lpcm.c b/libeplayer3-arm/output/writer/mipsel/lpcm.c index f03fc5d..cf099a2 100644 --- a/libeplayer3-arm/output/writer/mipsel/lpcm.c +++ b/libeplayer3-arm/output/writer/mipsel/lpcm.c @@ -59,7 +59,6 @@ /* ***************************** */ //#define SAM_WITH_DEBUG - #ifdef SAM_WITH_DEBUG #define LPCM_DEBUG #else @@ -135,23 +134,29 @@ static int32_t reset() static int writeData(WriterAVCallData_t *call) { lpcm_printf(10, "\n"); + if (!call) { lpcm_err("call data is NULL...\n"); return 0; } + lpcm_printf(10, "AudioPts %lld\n", call->Pts); + if (!call->data || (call->len <= 0)) { lpcm_err("parsing NULL Data. ignoring...\n"); return 0; } + if (call->fd < 0) { lpcm_err("file pointer < 0. ignoring ...\n"); return 0; } + pcmPrivateData_t *pcmPrivateData = (pcmPrivateData_t *)call->private_data; + int32_t i_rate = (int32_t)pcmPrivateData->sample_rate; int32_t i_channels = (int32_t)pcmPrivateData->channels; int32_t i_nb_samples = call->len / (i_channels * 2); @@ -161,6 +166,7 @@ static int writeData(WriterAVCallData_t *call) lpcm_err("Error DVD LPCM supports a maximum of eight channels i_channels[%d]\n", i_channels); return 0; } + if (pcmPrivateData->bResampling || NULL == p_buffer) { lpcm_printf(1, "i_rate: [%d]\n", i_rate); @@ -183,6 +189,7 @@ static int writeData(WriterAVCallData_t *call) lpcm_err("Error DVD LPCM sample_rate not supported [%d]\n", i_rate); return 0; } + /* In DVD LCPM, a frame is always 150 PTS ticks. */ i_frame_samples = i_rate * 150 / 90000; i_frame_size = i_frame_samples * i_channels * 2 + LLPCM_VOB_HEADER_LEN; @@ -191,6 +198,7 @@ static int writeData(WriterAVCallData_t *call) free(p_buffer); } p_buffer = malloc(i_frame_samples * i_channels * 16); + if (NULL != p_frame_buffer) { free(p_frame_buffer); @@ -200,9 +208,11 @@ static int writeData(WriterAVCallData_t *call) i_frame_num = 0; i_bitspersample = 16; } + const int i_num_frames = (i_buffer_used + i_nb_samples) / i_frame_samples; const int i_leftover_samples = (i_buffer_used + i_nb_samples) % i_frame_samples; const int i_start_offset = -i_buffer_used; + int32_t i_bytes_consumed = 0; int32_t i = 0; for (i = 0; i < i_num_frames; ++i) @@ -214,9 +224,11 @@ static int writeData(WriterAVCallData_t *call) frame[3] = (i_frame_num + i) & 0x1f; /* no emphasis, no mute */ frame[4] = (i_freq_code << 4) | (i_channels - 1); frame[5] = 0x80; /* neutral dynamic range */ + const int i_consume_samples = i_frame_samples - i_buffer_used; const int i_kept_bytes = i_buffer_used * i_channels * 2; const int i_consume_bytes = i_consume_samples * i_channels * 2; + #ifdef WORDS_BIGENDIAN memcpy(frame + 6, p_buffer, i_kept_bytes); memcpy(frame + 6 + i_kept_bytes, call->data + i_bytes_consumed, i_consume_bytes); @@ -224,15 +236,20 @@ static int writeData(WriterAVCallData_t *call) swab(p_buffer, frame + 6, i_kept_bytes); swab(call->data + i_bytes_consumed, frame + 6 + i_kept_bytes, i_consume_bytes); #endif + i_frame_num++; i_buffer_used = 0; i_bytes_consumed += i_consume_bytes; + /* We need to find i_length by means of next_pts due to possible roundoff errors. */ uint64_t this_pts = call->Pts + (i * i_frame_samples + i_start_offset) * 90000 / i_rate; + uint32_t pes_header_size = 0; pes_header_size = InsertPesHeader(PesHeader, i_frame_size + 1, MPEG_AUDIO_PES_START_CODE, this_pts, 0); + PesHeader[pes_header_size] = 0xa0; pes_header_size += 1; + struct iovec iov[2]; iov[0].iov_base = PesHeader; iov[0].iov_len = pes_header_size; @@ -240,8 +257,10 @@ static int writeData(WriterAVCallData_t *call) iov[1].iov_len = i_frame_size; i_ret_size += call->WriteV(call->fd, iov, 2); } + memcpy(p_buffer, call->data + i_bytes_consumed, i_leftover_samples * i_channels * 2); i_buffer_used = i_leftover_samples; + return i_ret_size; } diff --git a/libeplayer3-arm/output/writer/mipsel/mp3.c b/libeplayer3-arm/output/writer/mipsel/mp3.c index 3271f98..9eb9f5c 100644 --- a/libeplayer3-arm/output/writer/mipsel/mp3.c +++ b/libeplayer3-arm/output/writer/mipsel/mp3.c @@ -94,24 +94,31 @@ static int reset() static int writeData(WriterAVCallData_t *call) { unsigned char PesHeader[PES_MAX_HEADER_SIZE + 22]; + mp3_printf(10, "\n"); + if (call == NULL) { mp3_err("call data is NULL...\n"); return 0; } + mp3_printf(10, "AudioPts %lld\n", call->Pts); + if ((call->data == NULL) || (call->len <= 0)) { mp3_err("parsing NULL Data. ignoring...\n"); return 0; } + if (call->fd < 0) { mp3_err("file pointer < 0. ignoring ...\n"); return 0; } + call->private_size = 0; + uint32_t headerSize = InsertPesHeader(PesHeader, call->len + call->private_size, MPEG_AUDIO_PES_START_CODE, call->Pts, 0); if (call->private_size > 0) { @@ -123,7 +130,9 @@ static int writeData(WriterAVCallData_t *call) iov[0].iov_len = headerSize; iov[1].iov_base = call->data; iov[1].iov_len = call->len; + int len = call->WriteV(call->fd, iov, 2); + mp3_printf(10, "mp3_Write-< len=%d\n", len); return len; } diff --git a/libeplayer3-arm/output/writer/mipsel/mpeg2.c b/libeplayer3-arm/output/writer/mipsel/mpeg2.c index 2e53f70..aecc701 100644 --- a/libeplayer3-arm/output/writer/mipsel/mpeg2.c +++ b/libeplayer3-arm/output/writer/mipsel/mpeg2.c @@ -95,36 +95,47 @@ static int reset() static int writeData(WriterAVCallData_t *call) { unsigned char PesHeader[PES_MAX_HEADER_SIZE]; + int len = 0; unsigned int Position = 0; + mpeg2_printf(10, "\n"); + if (call == NULL) { mpeg2_err("call data is NULL...\n"); return 0; } + mpeg2_printf(10, "VideoPts %lld\n", call->Pts); + if ((call->data == NULL) || (call->len <= 0)) { mpeg2_err("parsing NULL Data. ignoring...\n"); return 0; } + if (call->fd < 0) { mpeg2_err("file pointer < 0. ignoring ...\n"); return 0; } + while (Position < call->len) { int PacketLength = (call->len - Position) <= MAX_PES_PACKET_SIZE ? (call->len - Position) : MAX_PES_PACKET_SIZE; + int Remaining = call->len - Position - PacketLength; + mpeg2_printf(20, "PacketLength=%d, Remaining=%d, Position=%d\n", PacketLength, Remaining, Position); + struct iovec iov[2]; iov[0].iov_base = PesHeader; iov[0].iov_len = InsertPesHeader(PesHeader, PacketLength, 0xe0, call->Pts, 0); iov[1].iov_base = call->data + Position; iov[1].iov_len = PacketLength; + ssize_t l = call->WriteV(call->fd, iov, 2); if (l < 0) { @@ -132,9 +143,11 @@ static int writeData(WriterAVCallData_t *call) break; } len += l; + Position += PacketLength; call->Pts = INVALID_PTS_VALUE; } + mpeg2_printf(10, "< len %d\n", len); return len; } diff --git a/libeplayer3-arm/output/writer/mipsel/mpeg4.c b/libeplayer3-arm/output/writer/mipsel/mpeg4.c index 23cb154..0086992 100644 --- a/libeplayer3-arm/output/writer/mipsel/mpeg4.c +++ b/libeplayer3-arm/output/writer/mipsel/mpeg4.c @@ -103,32 +103,40 @@ static int reset() static int writeData(WriterAVCallData_t *call) { unsigned char PesHeader[PES_MAX_HEADER_SIZE]; + mpeg4_printf(10, "\n"); + if (call == NULL) { mpeg4_err("call data is NULL...\n"); return 0; } + if ((call->data == NULL) || (call->len <= 0)) { mpeg4_err("parsing NULL Data. ignoring...\n"); return 0; } + if (call->fd < 0) { mpeg4_err("file pointer < 0. ignoring ...\n"); return 0; } + mpeg4_printf(10, "VideoPts %lld\n", call->Pts); + unsigned int PacketLength = call->len; if (initialHeader && call->private_size && call->private_data != NULL) { PacketLength += call->private_size; } + struct iovec iov[3]; int ic = 0; iov[ic].iov_base = PesHeader; iov[ic++].iov_len = InsertPesHeader(PesHeader, PacketLength, MPEG_VIDEO_PES_START_CODE, call->Pts, 0); + if (initialHeader && call->private_size && call->private_data != NULL) { initialHeader = 0; @@ -137,8 +145,11 @@ static int writeData(WriterAVCallData_t *call) } iov[ic].iov_base = call->data; iov[ic++].iov_len = call->len; + int len = call->WriteV(call->fd, iov, ic); + mpeg4_printf(10, "xvid_Write < len=%d\n", len); + return len; } diff --git a/libeplayer3-arm/output/writer/mipsel/pcm.c b/libeplayer3-arm/output/writer/mipsel/pcm.c index 8246100..f50ab64 100644 --- a/libeplayer3-arm/output/writer/mipsel/pcm.c +++ b/libeplayer3-arm/output/writer/mipsel/pcm.c @@ -56,8 +56,6 @@ /* Makros/Constants */ /* ***************************** */ -//#define SAM_WITH_DEBUG - #ifdef SAM_WITH_DEBUG #define PCM_DEBUG #else @@ -113,26 +111,32 @@ static int32_t reset() static int writeData(WriterAVCallData_t *call) { pcm_printf(10, "\n"); + if (!call) { pcm_err("call data is NULL...\n"); return 0; } + pcm_printf(10, "AudioPts %lld\n", call->Pts); + if (!call->data || (call->len <= 0)) { pcm_err("parsing NULL Data. ignoring...\n"); return 0; } + if (call->fd < 0) { pcm_err("file pointer < 0. ignoring ...\n"); return 0; } + static uint8_t PesHeader[PES_MAX_HEADER_SIZE + 22]; pcmPrivateData_t *pcmPrivateData = (pcmPrivateData_t *)call->private_data; uint8_t *buffer = call->data; uint32_t size = call->len; + if (pcmPrivateData->bResampling || NULL == fixed_buffer) { if (0) @@ -143,14 +147,18 @@ static int writeData(WriterAVCallData_t *call) printf("ioctl %d", ioctl(call->fd, AUDIO_PLAY)); printf("ioctl %d", ioctl(call->fd, AUDIO_CONTINUE)); } + int32_t format = 0x01; + int32_t width = 0; int32_t depth = 0; int32_t rate = (uint64_t)pcmPrivateData->sample_rate; int32_t channels = (uint8_t) pcmPrivateData->channels; int32_t block_align = 0; int32_t byterate = 0; + uint32_t codecID = (uint32_t)pcmPrivateData->ffmpeg_codec_id; + //uint8_t dataPrecision = 0; uint8_t LE = 0; switch (codecID) @@ -183,7 +191,9 @@ static int writeData(WriterAVCallData_t *call) default: break; } + uint8_t *data = codec_data; + byterate = channels * rate * width / 8; block_align = channels * width / 8; memset(data, 0, sizeof(codec_data)); @@ -209,10 +219,12 @@ static int writeData(WriterAVCallData_t *call) /* word size */ *(data++) = depth & 0xff; *(data++) = (depth >> 8) & 0xff; + uint32_t nfixed_buffersize = rate * 30 / 1000; nfixed_buffersize *= channels * depth / 8; fixed_buffertimestamp = call->Pts; fixed_bufferduration = 90000 * nfixed_buffersize / byterate; + if (fixed_buffersize != nfixed_buffersize || NULL == fixed_buffer) { fixed_buffersize = nfixed_buffersize; @@ -227,6 +239,7 @@ static int writeData(WriterAVCallData_t *call) if (LE) {} //printf("PCM fixed_buffersize [%u] [%s]\n", fixed_buffersize, LE ? "LE":"BE"); } + while (size > 0) { uint32_t cpSize = (fixed_buffersize - fixed_bufferfilled); @@ -236,10 +249,12 @@ static int writeData(WriterAVCallData_t *call) fixed_bufferfilled += size; return size; } + memcpy(fixed_buffer + fixed_bufferfilled, buffer, cpSize); fixed_bufferfilled = 0; buffer += cpSize; size -= cpSize; + uint32_t addHeaderSize = 0; if (IsDreambox()) { @@ -253,13 +268,17 @@ static int writeData(WriterAVCallData_t *call) PesHeader[headerSize++] = 0x4D; // M PesHeader[headerSize++] = 0x41; // A } + PesHeader[headerSize++] = (fixed_buffersize >> 24) & 0xff; PesHeader[headerSize++] = (fixed_buffersize >> 16) & 0xff; PesHeader[headerSize++] = (fixed_buffersize >> 8) & 0xff; PesHeader[headerSize++] = fixed_buffersize & 0xff; + memcpy(PesHeader + headerSize, codec_data, sizeof(codec_data)); headerSize += sizeof(codec_data); + PesHeader[6] |= 1; + struct iovec iov[2]; iov[0].iov_base = PesHeader; iov[0].iov_len = headerSize; @@ -267,10 +286,13 @@ static int writeData(WriterAVCallData_t *call) iov[1].iov_len = fixed_buffersize; call->WriteV(call->fd, iov, 2); fixed_buffertimestamp += fixed_bufferduration; - int g_fd_dump = open("/hdd/lpcm/ffmpeg.pes", O_CREAT | O_RDWR | O_APPEND, S_IRUSR | S_IWUSR); + + int g_fd_dump = open("/hdd/lpcm/ffmpeg.pes", O_CREAT | + O_RDWR | O_APPEND, S_IRUSR | S_IWUSR); call->WriteV(g_fd_dump, iov, 2); close(g_fd_dump); } + return size; } diff --git a/libeplayer3-arm/output/writer/mipsel/vc1.c b/libeplayer3-arm/output/writer/mipsel/vc1.c index d291e2a..0cdb63b 100644 --- a/libeplayer3-arm/output/writer/mipsel/vc1.c +++ b/libeplayer3-arm/output/writer/mipsel/vc1.c @@ -79,6 +79,7 @@ if (debug_level >= level) printf("[%s:%s] " fmt, __FILE__, __FUNCTION__, ## x); #define vc1_err(fmt, x...) #endif + /* ***************************** */ /* Types */ /* ***************************** */ @@ -110,28 +111,35 @@ static int reset() static int writeData(WriterAVCallData_t *call) { //int len = 0; + vc1_printf(10, "\n"); + if (call == NULL) { vc1_err("call data is NULL...\n"); return 0; } + if ((call->data == NULL) || (call->len <= 0)) { vc1_err("parsing NULL Data. ignoring...\n"); return 0; } + if (call->fd < 0) { vc1_err("file pointer < 0. ignoring ...\n"); return 0; } + vc1_printf(10, "VideoPts %lld\n", call->Pts); vc1_printf(10, "Got Private Size %d\n", call->private_size); + unsigned char PesHeader[PES_MAX_HEADER_SIZE + sizeof(Vc1FrameStartCode)]; int32_t ic = 0; struct iovec iov[5]; unsigned int PacketLength = 0; + iov[ic++].iov_base = PesHeader; if (initialHeader) { @@ -152,6 +160,7 @@ static int writeData(WriterAVCallData_t *call) PacketLength += videocodecdata.length; } } + uint8_t needFrameStartCode = 0; if (sizeof(Vc1FrameStartCode) >= call->len || memcmp(call->data, Vc1FrameStartCode, sizeof(Vc1FrameStartCode)) != 0) @@ -159,22 +168,28 @@ static int writeData(WriterAVCallData_t *call) needFrameStartCode = 1; PacketLength += sizeof(Vc1FrameStartCode); } + iov[ic].iov_base = call->data; iov[ic++].iov_len = call->len; PacketLength += call->len; + iov[0].iov_len = InsertPesHeader(PesHeader, PacketLength, MPEG_VIDEO_PES_START_CODE, call->Pts, 0); + /* some mipsel receiver(s) like et4x00 needs to have Copy(0)/Original(1) flag set to Original */ PesHeader[6] |= 1; + if (needFrameStartCode) { memcpy(PesHeader + iov[0].iov_len, Vc1FrameStartCode, sizeof(Vc1FrameStartCode)); iov[0].iov_len += sizeof(Vc1FrameStartCode); } + if (videocodecdata.data) { free(videocodecdata.data); videocodecdata.data = NULL; } + return call->WriteV(call->fd, iov, ic); } diff --git a/libeplayer3-arm/output/writer/mipsel/vp.c b/libeplayer3-arm/output/writer/mipsel/vp.c index 0c61c8c..a9f75aa 100644 --- a/libeplayer3-arm/output/writer/mipsel/vp.c +++ b/libeplayer3-arm/output/writer/mipsel/vp.c @@ -54,7 +54,6 @@ /* ***************************** */ //#define SAM_WITH_DEBUG - #ifdef SAM_WITH_DEBUG #define VP_DEBUG #else @@ -77,6 +76,7 @@ if (debug_level >= level) printf("[%s:%s] " fmt, __FILE__, __FUNCTION__, ## x); #define vp_err(fmt, x...) #endif + /* ***************************** */ /* Types */ /* ***************************** */ @@ -101,25 +101,31 @@ static int reset() static int writeData(WriterAVCallData_t *call, int is_vp6) { vp_printf(10, "\n"); + if (call == NULL) { vp_err("call data is NULL...\n"); return 0; } + if ((call->data == NULL) || (call->len <= 0)) { vp_err("parsing NULL Data. ignoring...\n"); return 0; } + if (call->fd < 0) { vp_err("file pointer < 0. ignoring ...\n"); return 0; } + vp_printf(10, "VideoPts %lld\n", call->Pts); vp_printf(10, "Got Private Size %d\n", call->private_size); + unsigned char PesHeader[PES_MAX_HEADER_SIZE]; struct iovec iov[2]; + iov[0].iov_base = PesHeader; uint32_t pes_header_len = InsertPesHeader(PesHeader, call->len, MPEG_VIDEO_PES_START_CODE, call->Pts, 0); uint32_t len = call->len + 4 + 6; @@ -138,6 +144,7 @@ static int writeData(WriterAVCallData_t *call, int is_vp6) iov[0].iov_len = pes_header_len; iov[1].iov_base = call->data; iov[1].iov_len = call->len; + return call->WriteV(call->fd, iov, 2); } diff --git a/libeplayer3-arm/output/writer/mipsel/wma.c b/libeplayer3-arm/output/writer/mipsel/wma.c index cea0459..15d6b2d 100644 --- a/libeplayer3-arm/output/writer/mipsel/wma.c +++ b/libeplayer3-arm/output/writer/mipsel/wma.c @@ -53,8 +53,6 @@ /* Makros/Constants */ /* ***************************** */ -//#define SAM_WITH_DEBUG - #ifdef SAM_WITH_DEBUG #define WMA_DEBUG #else @@ -106,28 +104,36 @@ static int reset() static int writeData(WriterAVCallData_t *call) { //int len = 0; + wma_printf(10, "\n"); + if (call == NULL) { wma_err("call data is NULL...\n"); return 0; } + wma_printf(10, "AudioPts %lld\n", call->Pts); + if ((call->data == NULL) || (call->len <= 0)) { wma_err("parsing NULL Data. ignoring...\n"); return 0; } + if (call->fd < 0) { wma_err("file pointer < 0. ignoring ...\n"); return 0; } + uint32_t packetLength = 4 + call->private_size + call->len; + if (IsDreambox()) { packetLength += 4; } + if ((packetLength + PES_MAX_HEADER_SIZE) > MaxPesHeader) { if (PesHeader) @@ -137,6 +143,7 @@ static int writeData(WriterAVCallData_t *call) MaxPesHeader = packetLength + PES_MAX_HEADER_SIZE; PesHeader = malloc(MaxPesHeader); } + uint32_t headerSize = InsertPesHeader(PesHeader, packetLength, MPEG_AUDIO_PES_START_CODE, call->Pts, 0); if (IsDreambox()) { @@ -145,14 +152,18 @@ static int writeData(WriterAVCallData_t *call) PesHeader[headerSize++] = 0x4D; // M PesHeader[headerSize++] = 0x41; // A } + size_t payload_len = call->len; PesHeader[headerSize++] = (payload_len >> 24) & 0xff; PesHeader[headerSize++] = (payload_len >> 16) & 0xff; PesHeader[headerSize++] = (payload_len >> 8) & 0xff; PesHeader[headerSize++] = payload_len & 0xff; + memcpy(PesHeader + headerSize, call->private_data, call->private_size); headerSize += call->private_size; + PesHeader[6] |= 1; + struct iovec iov[2]; iov[0].iov_base = PesHeader; iov[0].iov_len = headerSize; diff --git a/libeplayer3-arm/output/writer/mipsel/wmv.c b/libeplayer3-arm/output/writer/mipsel/wmv.c index 225697b..13934c7 100644 --- a/libeplayer3-arm/output/writer/mipsel/wmv.c +++ b/libeplayer3-arm/output/writer/mipsel/wmv.c @@ -108,27 +108,33 @@ static int reset() static int writeData(WriterAVCallData_t *call) { wmv_printf(10, "\n"); + if (call == NULL) { wmv_err("call data is NULL...\n"); return 0; } + if ((call->data == NULL) || (call->len <= 0)) { wmv_err("parsing NULL Data. ignoring...\n"); return 0; } + if (call->fd < 0) { wmv_err("file pointer < 0. ignoring ...\n"); return 0; } + wmv_printf(10, "VideoPts %lld\n", call->Pts); wmv_printf(10, "Got Private Size %d\n", call->private_size); + unsigned char PesHeader[PES_MAX_HEADER_SIZE + sizeof(Vc1FrameStartCode)]; int32_t ic = 0; struct iovec iov[5]; unsigned int PacketLength = 0; + iov[ic++].iov_base = PesHeader; if (initialHeader) { @@ -138,8 +144,10 @@ static int writeData(WriterAVCallData_t *call) free(videocodecdata.data); videocodecdata.data = NULL; } + unsigned int codec_size = call->private_size; if (codec_size > 4) codec_size = 4; + videocodecdata.length = 33; uint8_t *data = videocodecdata.data = malloc(videocodecdata.length); memset(videocodecdata.data, 0, videocodecdata.length); @@ -158,6 +166,7 @@ static int writeData(WriterAVCallData_t *call) PacketLength += videocodecdata.length; } } + uint8_t needFrameStartCode = 0; if (sizeof(Vc1FrameStartCode) >= call->len || memcmp(call->data, Vc1FrameStartCode, sizeof(Vc1FrameStartCode)) != 0) @@ -165,22 +174,28 @@ static int writeData(WriterAVCallData_t *call) needFrameStartCode = 1; PacketLength += sizeof(Vc1FrameStartCode); } + iov[ic].iov_base = call->data; iov[ic++].iov_len = call->len; PacketLength += call->len; + iov[0].iov_len = InsertPesHeader(PesHeader, PacketLength, MPEG_VIDEO_PES_START_CODE, call->Pts, 0); + /* some mipsel receiver(s) like et4x00 needs to have Copy(0)/Original(1) flag set to Original */ PesHeader[6] |= 1; + if (needFrameStartCode) { memcpy(PesHeader + iov[0].iov_len, Vc1FrameStartCode, sizeof(Vc1FrameStartCode)); iov[0].iov_len += sizeof(Vc1FrameStartCode); } + if (videocodecdata.data) { free(videocodecdata.data); videocodecdata.data = NULL; } + return call->WriteV(call->fd, iov, ic); } diff --git a/libeplayer3-arm/output/writer/mipsel/writer.c b/libeplayer3-arm/output/writer/mipsel/writer.c index 829e4db..209c75c 100644 --- a/libeplayer3-arm/output/writer/mipsel/writer.c +++ b/libeplayer3-arm/output/writer/mipsel/writer.c @@ -111,7 +111,7 @@ ssize_t WriteWithRetry(Context_t *context, int pipefd, int fd, const void *buf, { fd_set rfds; fd_set wfds; - + ssize_t ret; int retval = -1; int maxFd = pipefd > fd ? pipefd : fd; @@ -125,36 +125,36 @@ ssize_t WriteWithRetry(Context_t *context, int pipefd, int fd, const void *buf, FD_SET(pipefd, &rfds); FD_SET(fd, &wfds); - /* When we PAUSE LINUX DVB outputs buffers then audio/video buffers - * will be filled to full unfortunately, in such case after resume + /* When we PAUSE LINUX DVB outputs buffers then audio/video buffers + * will be filled to full unfortunately, in such case after resume * select never return with fd set - bug in DVB drivers? * So, there will be to workarounds: * 1. write to pipe pipe at resume to exit select immediately - * 2. even if fd is not set exit from select after 0,1s + * 2. even if fd is not set exit from select after 0,1s * (it seems that second workaround is not needed) */ //tv.tv_sec = 0; //tv.tv_usec = 100000; // 100ms - + retval = select(maxFd + 1, &rfds, &wfds, NULL, NULL); //&tv); if (retval < 0) { break; } - + //if (retval == 0) //{ // //printf("RETURN FROM SELECT DUE TO TIMEOUT TIMEOUT\n"); // continue; //} - + if(FD_ISSET(pipefd, &rfds)) { FlusPipe(pipefd); //printf("RETURN FROM SELECT DUE TO pipefd SET\n"); continue; } - + if(FD_ISSET(fd, &wfds)) { ret = write(fd, buf, size); @@ -173,7 +173,7 @@ ssize_t WriteWithRetry(Context_t *context, int pipefd, int fd, const void *buf, { break; } - + return ret; } else if (ret == 0) @@ -186,7 +186,7 @@ ssize_t WriteWithRetry(Context_t *context, int pipefd, int fd, const void *buf, FlusPipe(pipefd); continue; } - + size -= ret; buf += ret; } @@ -219,12 +219,15 @@ ssize_t write_with_retry(int fd, const void *buf, size_t size) break; } } + if (ret < 0) { return ret; } + size -= ret; buf += ret; + if (size > 0) { if (usleep(1000)) @@ -255,6 +258,7 @@ ssize_t writev_with_retry(int fd, const struct iovec *iov, size_t ic) Writer_t *getWriter(char *encoding) { int i; + for (i = 0; AvailableWriter[i] != NULL; i++) { if (strcmp(AvailableWriter[i]->caps->textEncoding, encoding) == 0) @@ -263,13 +267,16 @@ Writer_t *getWriter(char *encoding) return AvailableWriter[i]; } } + writer_printf(1, "%s: no writer found for \"%s\"\n", __func__, encoding); + return NULL; } Writer_t *getDefaultVideoWriter() { int i; + for (i = 0; AvailableWriter[i] != NULL; i++) { if (strcmp(AvailableWriter[i]->caps->textEncoding, "V_MPEG2") == 0) @@ -278,13 +285,16 @@ Writer_t *getDefaultVideoWriter() return AvailableWriter[i]; } } + writer_printf(1, "%s: no writer found\n", __func__); + return NULL; } Writer_t *getDefaultAudioWriter() { int i; + for (i = 0; AvailableWriter[i] != NULL; i++) { if (strcmp(AvailableWriter[i]->caps->textEncoding, "A_MP3") == 0) @@ -293,6 +303,8 @@ Writer_t *getDefaultAudioWriter() return AvailableWriter[i]; } } + writer_printf(1, "%s: no writer found\n", __func__); + return NULL; } diff --git a/libeplayer3-arm/output/writer/sh4/aac.c b/libeplayer3-arm/output/writer/sh4/aac.c index e70336c..28b06b8 100644 --- a/libeplayer3-arm/output/writer/sh4/aac.c +++ b/libeplayer3-arm/output/writer/sh4/aac.c @@ -43,6 +43,7 @@ #include #include "ffmpeg/latmenc.h" + #include "common.h" #include "output.h" #include "debug.h" @@ -157,17 +158,21 @@ static int reset() static int _writeData(void *_call, int type) { WriterAVCallData_t *call = (WriterAVCallData_t *) _call; + aac_printf(10, "\n _writeData type[%d]\n", type); + if (call == NULL) { aac_err("call data is NULL...\n"); return 0; } + if ((call->data == NULL) || (call->len < 8)) { aac_err("parsing Data with missing AAC header. ignoring...\n"); return 0; } + /* simple validation */ if (0 == type) // check ADTS header { @@ -194,9 +199,13 @@ static int _writeData(void *_call, int type) return 0; } } + unsigned char PesHeader[PES_MAX_HEADER_SIZE]; + aac_printf(10, "AudioPts %lld\n", call->Pts); + unsigned int HeaderLength = InsertPesHeader(PesHeader, call->len, MPEG_AUDIO_PES_START_CODE, call->Pts, 0); + struct iovec iov[2]; iov[0].iov_base = PesHeader; iov[0].iov_len = HeaderLength; @@ -208,31 +217,38 @@ static int _writeData(void *_call, int type) static int writeDataADTS(void *_call) { WriterAVCallData_t *call = (WriterAVCallData_t *) _call; + aac_printf(10, "\n"); + if (call == NULL) { aac_err("call data is NULL...\n"); return 0; } + if ((call->data == NULL) || (call->len <= 0)) { aac_err("parsing NULL Data. ignoring...\n"); return 0; } + if (call->fd < 0) { aac_err("file pointer < 0. ignoring ...\n"); return 0; } + if ((call->private_data && 0 == strncmp("ADTS", call->private_data, call->private_size)) || HasADTSHeader(call->data, call->len)) { return _writeData(_call, 0); } + uint32_t PacketLength = call->len + AAC_HEADER_LENGTH; uint8_t PesHeader[PES_MAX_HEADER_SIZE + AAC_HEADER_LENGTH]; uint32_t headerSize = InsertPesHeader(PesHeader, PacketLength, MPEG_AUDIO_PES_START_CODE, call->Pts, 0); uint8_t *pExtraData = &PesHeader[headerSize]; + aac_printf(10, "AudioPts %lld\n", call->Pts); if (call->private_data == NULL) { @@ -243,6 +259,7 @@ static int writeDataADTS(void *_call) { memcpy(pExtraData, call->private_data, AAC_HEADER_LENGTH); } + pExtraData[3] &= 0xC0; /* frame size over last 2 bits */ pExtraData[3] |= (PacketLength & 0x1800) >> 11; @@ -255,33 +272,41 @@ static int writeDataADTS(void *_call) /* buffer fullness(0x7FF for VBR) continued over 6 first bits + 2 zeros for * number of raw data blocks */ pExtraData[6] = 0xFC; + struct iovec iov[2]; iov[0].iov_base = PesHeader; iov[0].iov_len = headerSize + AAC_HEADER_LENGTH; iov[1].iov_base = call->data; iov[1].iov_len = call->len; + return writev(call->fd, iov, 2); } static int writeDataLATM(void *_call) { WriterAVCallData_t *call = (WriterAVCallData_t *) _call; + aac_printf(10, "\n"); + if (call == NULL) { aac_err("call data is NULL...\n"); return 0; } + if ((call->data == NULL) || (call->len <= 0)) { aac_err("parsing NULL Data. ignoring...\n"); return 0; } + if (call->private_data && 0 == strncmp("LATM", call->private_data, call->private_size)) { return _writeData(_call, 1); } + aac_printf(10, "AudioPts %lld\n", call->Pts); + if (!pLATMCtx) { pLATMCtx = malloc(sizeof(LATMContext)); @@ -289,11 +314,13 @@ static int writeDataLATM(void *_call) pLATMCtx->mod = 14; pLATMCtx->counter = 0; } + if (!pLATMCtx) { aac_err("parsing NULL pLATMCtx. ignoring...\n"); return 0; } + unsigned char PesHeader[PES_MAX_HEADER_SIZE]; int ret = latmenc_decode_extradata(pLATMCtx, call->private_data, call->private_size); if (ret) @@ -309,14 +336,19 @@ static int writeDataLATM(void *_call) aac_err("latm_write_packet failed. ignoring...\n"); return 0; } + unsigned int HeaderLength = InsertPesHeader(PesHeader, pLATMCtx->len + 3, MPEG_AUDIO_PES_START_CODE, call->Pts, 0); + struct iovec iov[3]; iov[0].iov_base = PesHeader; iov[0].iov_len = HeaderLength; + iov[1].iov_base = pLATMCtx->loas_header; iov[1].iov_len = 3; + iov[2].iov_base = pLATMCtx->buffer; iov[2].iov_len = pLATMCtx->len; + return writev(call->fd, iov, 3); } diff --git a/libeplayer3-arm/output/writer/sh4/ac3.c b/libeplayer3-arm/output/writer/sh4/ac3.c index cf50f6b..3ff3df0 100644 --- a/libeplayer3-arm/output/writer/sh4/ac3.c +++ b/libeplayer3-arm/output/writer/sh4/ac3.c @@ -98,29 +98,38 @@ static int reset() static int writeData(void *_call) { WriterAVCallData_t *call = (WriterAVCallData_t *) _call; + ac3_printf(10, "\n"); + unsigned char PesHeader[PES_MAX_HEADER_SIZE]; + if (call == NULL) { ac3_err("call data is NULL...\n"); return 0; } + ac3_printf(10, "AudioPts %lld\n", call->Pts); + if ((call->data == NULL) || (call->len <= 0)) { ac3_err("parsing NULL Data. ignoring...\n"); return 0; } + if (call->fd < 0) { ac3_err("file pointer < 0. ignoring ...\n"); return 0; } + struct iovec iov[2]; + iov[0].iov_base = PesHeader; iov[0].iov_len = InsertPesHeader(PesHeader, call->len, PRIVATE_STREAM_1_PES_START_CODE, call->Pts, 0); iov[1].iov_base = call->data; iov[1].iov_len = call->len; + return writev(call->fd, iov, 2); } diff --git a/libeplayer3-arm/output/writer/sh4/divx.c b/libeplayer3-arm/output/writer/sh4/divx.c index 904b7af..e18538d 100644 --- a/libeplayer3-arm/output/writer/sh4/divx.c +++ b/libeplayer3-arm/output/writer/sh4/divx.c @@ -101,6 +101,7 @@ static uint8_t updateCodecData(uint8_t *data, int32_t size) { static uint8_t *oldData = NULL; static int32_t oldSize = 0; + uint8_t update = 0; if (data != NULL && size > 0) { @@ -121,6 +122,7 @@ static uint8_t updateCodecData(uint8_t *data, int32_t size) } } } + if (update) { if (oldData != NULL) @@ -131,43 +133,56 @@ static uint8_t updateCodecData(uint8_t *data, int32_t size) memcpy(oldData, data, size); oldSize = size; } + return update; } static int writeData(void *_call) { WriterAVCallData_t *call = (WriterAVCallData_t *) _call; + unsigned char PesHeader[PES_MAX_HEADER_SIZE]; + divx_printf(10, "\n"); + if (call == NULL) { divx_err("call data is NULL...\n"); return 0; } + if ((call->data == NULL) || (call->len <= 0)) { divx_err("parsing NULL Data. ignoring...\n"); return 0; } + if (call->fd < 0) { divx_err("file pointer < 0. ignoring ...\n"); return 0; } + divx_printf(10, "VideoPts %lld\n", call->Pts); + struct iovec iov[4]; int ic = 0; iov[ic].iov_base = PesHeader; iov[ic++].iov_len = InsertPesHeader(PesHeader, call->len, MPEG_VIDEO_PES_START_CODE, call->Pts, 0); + if (updateCodecData(call->private_data, call->private_size)) { iov[ic].iov_base = call->private_data; iov[ic++].iov_len = call->private_size; } + iov[ic].iov_base = call->data; iov[ic++].iov_len = call->len; + int len = writev(call->fd, iov, ic); + divx_printf(10, "xvid_Write < len=%d\n", len); + return len; } diff --git a/libeplayer3-arm/output/writer/sh4/divx2.c b/libeplayer3-arm/output/writer/sh4/divx2.c index a658416..c7b8654 100644 --- a/libeplayer3-arm/output/writer/sh4/divx2.c +++ b/libeplayer3-arm/output/writer/sh4/divx2.c @@ -101,6 +101,7 @@ static uint8_t updateCodecData(uint8_t *data, int32_t size) { static uint8_t *oldData = NULL; static int32_t oldSize = 0; + uint8_t update = 0; if (data != NULL && size > 0) { @@ -121,6 +122,7 @@ static uint8_t updateCodecData(uint8_t *data, int32_t size) } } } + if (update) { if (oldData != NULL) @@ -131,12 +133,14 @@ static uint8_t updateCodecData(uint8_t *data, int32_t size) memcpy(oldData, data, size); oldSize = size; } + return update; } static int writeData(void *_call) { WriterAVCallData_t *call = (WriterAVCallData_t *) _call; + unsigned char PesHeader[PES_MAX_HEADER_SIZE]; unsigned char FakeHeaders[64]; // 64bytes should be enough to make the fake headers unsigned int FakeHeaderLength; @@ -144,26 +148,34 @@ static int writeData(void *_call) unsigned int FakeStartCode = (Version << 8) | PES_VERSION_FAKE_START_CODE; unsigned int usecPerFrame = 41708; /* Hellmaster1024: default value */ BitPacker_t ld = {FakeHeaders, 0, 32}; + divx_printf(10, "\n"); + if (call == NULL) { divx_err("call data is NULL...\n"); return 0; } + if ((call->data == NULL) || (call->len <= 0)) { divx_err("parsing NULL Data. ignoring...\n"); return 0; } + if (call->fd < 0) { divx_err("file pointer < 0. ignoring ...\n"); return 0; } + divx_printf(10, "AudioPts %lld\n", call->Pts); + usecPerFrame = 1000000000 / call->FrameRate; divx_printf(10, "Microsecends per frame = %d\n", usecPerFrame); + memset(FakeHeaders, 0, sizeof(FakeHeaders)); + /* Create info record for frame parser */ /* divx4 & 5 VOS @@ -177,23 +189,30 @@ static int writeData(void *_call) PutBits(&ld, usecPerFrame, 32); // microseconds per frame FlushBits(&ld); + FakeHeaderLength = (ld.Ptr - (FakeHeaders)); + struct iovec iov[4]; int ic = 0; iov[ic].iov_base = PesHeader; iov[ic++].iov_len = InsertPesHeader(PesHeader, call->len, MPEG_VIDEO_PES_START_CODE, call->Pts, FakeStartCode); iov[ic].iov_base = FakeHeaders; iov[ic++].iov_len = FakeHeaderLength; + if (initialHeader) { iov[ic].iov_base = call->private_data; iov[ic++].iov_len = call->private_size; initialHeader = 0; } + iov[ic].iov_base = call->data; iov[ic++].iov_len = call->len; + int len = writev(call->fd, iov, ic); + divx_printf(10, "xvid_Write < len=%d\n", len); + return len; } diff --git a/libeplayer3-arm/output/writer/sh4/dts.c b/libeplayer3-arm/output/writer/sh4/dts.c index 25bd117..fb2a21f 100644 --- a/libeplayer3-arm/output/writer/sh4/dts.c +++ b/libeplayer3-arm/output/writer/sh4/dts.c @@ -102,26 +102,34 @@ static int reset() static int32_t writeData(void *_call) { WriterAVCallData_t *call = (WriterAVCallData_t *) _call; + uint8_t PesHeader[PES_AUDIO_HEADER_SIZE]; + dts_printf(10, "\n"); + if (call == NULL) { dts_err("call data is NULL...\n"); return 0; } + dts_printf(10, "AudioPts %lld\n", call->Pts); + if ((call->data == NULL) || (call->len <= 0)) { dts_err("parsing NULL Data. ignoring...\n"); return 0; } + if (call->fd < 0) { dts_err("file pointer < 0. ignoring ...\n"); return 0; } + uint8_t *Data = call->data; int32_t Size = call->len; + #ifdef CHECK_FOR_DTS_HD int32_t pos = 0; while ((pos + 4) <= Size) @@ -135,6 +143,7 @@ static int32_t writeData(void *_call) ++pos; } #endif + // #define DO_BYTESWAP #ifdef DO_BYTESWAP /* 16-bit byte swap all data before injecting it */ @@ -145,11 +154,13 @@ static int32_t writeData(void *_call) Data[i + 1] = Tmp; } #endif + struct iovec iov[2]; iov[0].iov_base = PesHeader; iov[0].iov_len = InsertPesHeader(PesHeader, Size, MPEG_AUDIO_PES_START_CODE, call->Pts, 0); iov[1].iov_base = Data; iov[1].iov_len = Size; + int32_t len = writev(call->fd, iov, 2); dts_printf(10, "< len %d\n", len); return len; diff --git a/libeplayer3-arm/output/writer/sh4/h263.c b/libeplayer3-arm/output/writer/sh4/h263.c index 86430df..466d720 100644 --- a/libeplayer3-arm/output/writer/sh4/h263.c +++ b/libeplayer3-arm/output/writer/sh4/h263.c @@ -97,39 +97,52 @@ static int reset() static int writeData(void *_call) { WriterAVCallData_t *call = (WriterAVCallData_t *) _call; + unsigned char PesHeader[PES_MAX_HEADER_SIZE]; int len = 0; + h263_printf(10, "\n"); + if (call == NULL) { h263_err("call data is NULL...\n"); return 0; } + h263_printf(10, "VideoPts %lld\n", call->Pts); + if ((call->data == NULL) || (call->len <= 0)) { h263_err("NULL Data. ignoring...\n"); return 0; } + if (call->fd < 0) { h263_err("file pointer < 0. ignoring ...\n"); return 0; } + int HeaderLength = InsertPesHeader(PesHeader, call->len, H263_VIDEO_PES_START_CODE, call->Pts, 0); + int PrivateHeaderLength = InsertVideoPrivateDataHeader(&PesHeader[HeaderLength], call->len); + int PesLength = PesHeader[PES_LENGTH_BYTE_0] + (PesHeader[PES_LENGTH_BYTE_1] << 8) + PrivateHeaderLength; + PesHeader[PES_LENGTH_BYTE_0] = PesLength & 0xff; PesHeader[PES_LENGTH_BYTE_1] = (PesLength >> 8) & 0xff; PesHeader[PES_HEADER_DATA_LENGTH_BYTE] += PrivateHeaderLength; PesHeader[PES_FLAGS_BYTE] |= PES_EXTENSION_DATA_PRESENT; + HeaderLength += PrivateHeaderLength; + struct iovec iov[2]; iov[0].iov_base = PesHeader; iov[0].iov_len = HeaderLength; iov[1].iov_base = call->data; iov[1].iov_len = call->len; len = writev(call->fd, iov, 2); + h263_printf(10, "< len %d\n", len); return len; } diff --git a/libeplayer3-arm/output/writer/sh4/h264.c b/libeplayer3-arm/output/writer/sh4/h264.c index 482b219..39a6afa 100644 --- a/libeplayer3-arm/output/writer/sh4/h264.c +++ b/libeplayer3-arm/output/writer/sh4/h264.c @@ -113,34 +113,45 @@ static int avc3 = 0; static int32_t UpdateExtraData(uint8_t **ppExtraData, uint32_t *pExtraDataSize, uint8_t *pData, uint32_t dataSize) { uint8_t *aExtraData = *ppExtraData; + if (aExtraData[0] != 1 || !pData) { // Not AVCC or nothing to update with. return -1; } + int32_t nalsize = (aExtraData[4] & 3) + 1; + uint8_t sps[256]; uint8_t spsIdx = 0; + uint8_t numSps = 0; + uint8_t pps[256]; uint8_t ppsIdx = 0; + uint8_t numPps = 0; + if (nalsize != 4) { return -1; } + // Find SPS and PPS NALUs in AVCC data uint8_t *d = pData; while (d + 4 < pData + dataSize) { uint32_t nalLen = ReadUint32(d); + uint8_t nalType = d[4] & 0x1f; if (nalType == 7) { /* SPS */ + // 16 bits size sps[spsIdx++] = (uint8_t)(0xFF & (nalLen >> 8)); sps[spsIdx++] = (uint8_t)(0xFF & nalLen); + if (spsIdx + nalLen >= sizeof(sps)) { h264_err("SPS no free space to copy...\n"); @@ -148,15 +159,19 @@ static int32_t UpdateExtraData(uint8_t **ppExtraData, uint32_t *pExtraDataSize, } memcpy(&(sps[spsIdx]), d + 4, nalLen); spsIdx += nalLen; + numSps += 1; + h264_printf(10, "SPS len[%u]...\n", nalLen); } else if (nalType == 8) { /* PPS */ + // 16 bits size pps[ppsIdx++] = (uint8_t)(0xFF & (nalLen >> 8)); pps[ppsIdx++] = (uint8_t)(0xFF & nalLen); + if (ppsIdx + nalLen >= sizeof(sps)) { h264_err("PPS not free space to copy...\n"); @@ -164,7 +179,9 @@ static int32_t UpdateExtraData(uint8_t **ppExtraData, uint32_t *pExtraDataSize, } memcpy(&(pps[ppsIdx]), d + 4, nalLen); ppsIdx += nalLen; + numPps += 1; + h264_printf(10, "PPS len[%u]...\n", nalLen); } d += 4 + nalLen; @@ -177,18 +194,21 @@ static int32_t UpdateExtraData(uint8_t **ppExtraData, uint32_t *pExtraDataSize, aExtraData[idx++] = sps[4]; // profile compat aExtraData[idx++] = sps[5]; // level aExtraData[idx++] = 0xff; // nal size - 1 + aExtraData[idx++] = 0xe0 | numSps; if (numSps) { memcpy(&(aExtraData[idx]), sps, spsIdx); idx += spsIdx; } + aExtraData[idx++] = numPps; if (numPps) { memcpy(&(aExtraData[idx]), pps, ppsIdx); idx += ppsIdx; } + h264_printf(10, "aExtraData len[%u]...\n", idx); *pExtraDataSize = idx; return 0; @@ -204,6 +224,7 @@ static int32_t reset() static int32_t writeData(void *_call) { WriterAVCallData_t *call = (WriterAVCallData_t *) _call; + uint8_t PesHeader[PES_MAX_HEADER_SIZE]; uint64_t VideoPts; uint32_t TimeDelta; @@ -212,25 +233,31 @@ static int32_t writeData(void *_call) int32_t ic = 0; struct iovec iov[128]; h264_printf(10, "\n"); + if (call == NULL) { h264_err("call data is NULL...\n"); return 0; } + TimeDelta = call->FrameRate; TimeScale = call->FrameScale; VideoPts = call->Pts; + h264_printf(10, "VideoPts %lld - %d %d\n", call->Pts, TimeDelta, TimeScale); + if ((call->data == NULL) || (call->len <= 0)) { h264_err("NULL Data. ignoring...\n"); return 0; } + if (call->fd < 0) { h264_err("file pointer < 0. ignoring ...\n"); return 0; } + /* AnnexA */ if (!avc3 && ((1 < call->private_size && 0 == call->private_data[0]) || (call->len > 3) && ((call->data[0] == 0x00 && call->data[1] == 0x00 && call->data[2] == 0x00 && call->data[3] == 0x01) || @@ -238,6 +265,7 @@ static int32_t writeData(void *_call) { uint32_t PacketLength = 0; uint32_t FakeStartCode = /*(call->Version << 8) | */PES_VERSION_FAKE_START_CODE; + iov[ic++].iov_base = PesHeader; initialHeader = 0; if (initialHeader) @@ -247,16 +275,20 @@ static int32_t writeData(void *_call) iov[ic++].iov_len = call->private_size; PacketLength += call->private_size; } + iov[ic].iov_base = ""; iov[ic++].iov_len = 1; + iov[ic].iov_base = call->data; iov[ic++].iov_len = call->len; PacketLength += call->len; + /*Hellmaster1024: some packets will only be accepted by the player if we send one byte more than data is available. The content of this byte does not matter. It will be ignored by the player */ iov[ic].iov_base = "\0"; iov[ic++].iov_len = 1; + iov[0].iov_len = InsertPesHeader(PesHeader, -1, MPEG_VIDEO_PES_START_CODE, VideoPts, FakeStartCode); int ret = writev(call->fd, iov, ic); return ret; @@ -266,6 +298,7 @@ static int32_t writeData(void *_call) h264_err("No valid private data available!\n"); return 0; } + if (initialHeader) { uint8_t *private_data = call->private_data; @@ -276,8 +309,11 @@ static int32_t writeData(void *_call) unsigned int ParamOffset; unsigned int InitialHeaderLength = 0; unsigned int ParametersLength; + ParametersLength = 0; + unsigned char HeaderData[19]; + if (private_size <= sizeof(avcC_t)) { UpdateExtraData(&private_data, &private_size, call->data, call->len); @@ -287,6 +323,7 @@ static int32_t writeData(void *_call) avcCHeader = (avcC_t *)private_data; } } + HeaderData[ParametersLength++] = 0x00; // Start code HeaderData[ParametersLength++] = 0x00; HeaderData[ParametersLength++] = 0x01; @@ -294,14 +331,17 @@ static int32_t writeData(void *_call) // Container message version - changes when/if we vary the format of the message HeaderData[ParametersLength++] = CONTAINER_PARAMETERS_VERSION; HeaderData[ParametersLength++] = 0xff; // Field separator + if (TimeDelta == 0xffffffff) TimeDelta = (TimeScale > 1000) ? 1001 : 1; + HeaderData[ParametersLength++] = (TimeScale >> 24) & 0xff; // Output the timescale HeaderData[ParametersLength++] = (TimeScale >> 16) & 0xff; HeaderData[ParametersLength++] = 0xff; HeaderData[ParametersLength++] = (TimeScale >> 8) & 0xff; HeaderData[ParametersLength++] = TimeScale & 0xff; HeaderData[ParametersLength++] = 0xff; + HeaderData[ParametersLength++] = (TimeDelta >> 24) & 0xff; // Output frame period HeaderData[ParametersLength++] = (TimeDelta >> 16) & 0xff; HeaderData[ParametersLength++] = 0xff; @@ -309,7 +349,9 @@ static int32_t writeData(void *_call) HeaderData[ParametersLength++] = TimeDelta & 0xff; HeaderData[ParametersLength++] = 0xff; HeaderData[ParametersLength++] = 0x80; // Rsbp trailing bits + assert(ParametersLength <= sizeof(HeaderData)); + ic = 0; iov[ic].iov_base = PesHeader; iov[ic++].iov_len = InsertPesHeader(PesHeader, ParametersLength, MPEG_VIDEO_PES_START_CODE, INVALID_PTS_VALUE, 0); @@ -320,8 +362,10 @@ static int32_t writeData(void *_call) { return len; } + NalLengthBytes = (avcCHeader->NalLengthMinusOne & 0x03) + 1; ParamSets = avcCHeader->NumParamSets & 0x1f; + h264_printf(20, "avcC contents:\n"); h264_printf(20, " version: %d\n", avcCHeader->Version); h264_printf(20, " profile: %d\n", avcCHeader->Profile); @@ -329,13 +373,16 @@ static int32_t writeData(void *_call) h264_printf(20, " level: %d\n", avcCHeader->Level); h264_printf(20, " nal length bytes: %d\n", NalLengthBytes); h264_printf(20, " number of sequence param sets: %d\n", ParamSets); + ParamOffset = 0; ic = 0; iov[ic++].iov_base = PesHeader; for (i = 0; i < ParamSets; i++) { unsigned int PsLength = (avcCHeader->Params[ParamOffset] << 8) + avcCHeader->Params[ParamOffset + 1]; + h264_printf(20, " sps %d has length %d\n", i, PsLength); + iov[ic].iov_base = (char *)Head; iov[ic++].iov_len = sizeof(Head); InitialHeaderLength += sizeof(Head); @@ -344,13 +391,18 @@ static int32_t writeData(void *_call) InitialHeaderLength += PsLength; ParamOffset += PsLength + 2; } + ParamSets = avcCHeader->Params[ParamOffset]; + h264_printf(20, " number of picture param sets: %d\n", ParamSets); + ParamOffset++; for (i = 0; i < ParamSets; i++) { unsigned int PsLength = (avcCHeader->Params[ParamOffset] << 8) + avcCHeader->Params[ParamOffset + 1]; + h264_printf(20, " pps %d has length %d\n", i, PsLength); + iov[ic].iov_base = (char *) Head; iov[ic++].iov_len = sizeof(Head); InitialHeaderLength += sizeof(Head); @@ -359,27 +411,34 @@ static int32_t writeData(void *_call) InitialHeaderLength += PsLength; ParamOffset += PsLength + 2; } + iov[0].iov_len = InsertPesHeader(PesHeader, InitialHeaderLength, MPEG_VIDEO_PES_START_CODE, INVALID_PTS_VALUE, 0); ssize_t l = writev(call->fd, iov, ic); + if (private_data != call->private_data) { free(private_data); } + if (l < 0) { return l; } + len += l; initialHeader = 0; } + unsigned int SampleSize = call->len; unsigned int NalStart = 0; unsigned int VideoPosition = 0; + do { unsigned int NalLength; unsigned char NalData[4]; int NalPresent = 1; + memcpy(NalData, call->data + VideoPosition, NalLengthBytes); VideoPosition += NalLengthBytes; NalStart += NalLengthBytes; @@ -398,11 +457,14 @@ static int32_t writeData(void *_call) NalLength = (NalData[0] << 24) | (NalData[1] << 16) | (NalData[2] << 8) | (NalData[3]); break; } + h264_printf(20, "NalStart = %u + NalLength = %u > SampleSize = %u\n", NalStart, NalLength, SampleSize); + if (NalStart + NalLength > SampleSize) { h264_printf(20, "nal length past end of buffer - size %u frame offset %u left %u\n", NalLength, NalStart, SampleSize - NalStart); + NalStart = SampleSize; } else @@ -410,30 +472,37 @@ static int32_t writeData(void *_call) NalStart += NalLength; ic = 0; iov[ic++].iov_base = PesHeader; + if (NalPresent) { NalPresent = 0; iov[ic].iov_base = (char *)Head; iov[ic++].iov_len = sizeof(Head); } + iov[ic].iov_base = call->data + VideoPosition; iov[ic++].iov_len = NalLength; VideoPosition += NalLength; + h264_printf(20, " pts=%llu\n", VideoPts); + iov[0].iov_len = InsertPesHeader(PesHeader, NalLength, MPEG_VIDEO_PES_START_CODE, VideoPts, 0); ssize_t l = writev(call->fd, iov, ic); if (l < 0) return l; len += l; + VideoPts = INVALID_PTS_VALUE; } } while (NalStart < SampleSize); + if (len < 0) { h264_err("error writing data errno = %d\n", errno); h264_err("%s\n", strerror(errno)); } + h264_printf(10, "< len %d\n", len); return len; } diff --git a/libeplayer3-arm/output/writer/sh4/mp3.c b/libeplayer3-arm/output/writer/sh4/mp3.c index f66bb41..7ed7d02 100644 --- a/libeplayer3-arm/output/writer/sh4/mp3.c +++ b/libeplayer3-arm/output/writer/sh4/mp3.c @@ -97,30 +97,39 @@ static int reset() static int writeData(void *_call) { WriterAVCallData_t *call = (WriterAVCallData_t *) _call; + unsigned char PesHeader[PES_MAX_HEADER_SIZE]; + mp3_printf(10, "\n"); + if (call == NULL) { mp3_err("call data is NULL...\n"); return 0; } + mp3_printf(10, "AudioPts %lld\n", call->Pts); + if ((call->data == NULL) || (call->len <= 0)) { mp3_err("parsing NULL Data. ignoring...\n"); return 0; } + if (call->fd < 0) { mp3_err("file pointer < 0. ignoring ...\n"); return 0; } + struct iovec iov[2]; iov[0].iov_base = PesHeader; iov[0].iov_len = InsertPesHeader(PesHeader, call->len, MPEG_AUDIO_PES_START_CODE, call->Pts, 0); iov[1].iov_base = call->data; iov[1].iov_len = call->len; + int len = writev(call->fd, iov, 2); + mp3_printf(10, "mp3_Write-< len=%d\n", len); return len; } diff --git a/libeplayer3-arm/output/writer/sh4/mpeg2.c b/libeplayer3-arm/output/writer/sh4/mpeg2.c index 2fd8ad6..cb1f928 100644 --- a/libeplayer3-arm/output/writer/sh4/mpeg2.c +++ b/libeplayer3-arm/output/writer/sh4/mpeg2.c @@ -97,37 +97,49 @@ static int reset() static int writeData(void *_call) { WriterAVCallData_t *call = (WriterAVCallData_t *) _call; + unsigned char PesHeader[PES_MAX_HEADER_SIZE]; + int len = 0; unsigned int Position = 0; + mpeg2_printf(10, "\n"); + if (call == NULL) { mpeg2_err("call data is NULL...\n"); return 0; } + mpeg2_printf(10, "VideoPts %lld\n", call->Pts); + if ((call->data == NULL) || (call->len <= 0)) { mpeg2_err("parsing NULL Data. ignoring...\n"); return 0; } + if (call->fd < 0) { mpeg2_err("file pointer < 0. ignoring ...\n"); return 0; } + while (Position < call->len) { int32_t PacketLength = (call->len - Position) <= MAX_PES_PACKET_SIZE ? (call->len - Position) : MAX_PES_PACKET_SIZE; + int32_t Remaining = call->len - Position - PacketLength; + mpeg2_printf(20, "PacketLength=%d, Remaining=%d, Position=%d\n", PacketLength, Remaining, Position); + struct iovec iov[2]; iov[0].iov_base = PesHeader; iov[0].iov_len = InsertPesHeader(PesHeader, PacketLength, 0xe0, call->Pts, 0); iov[1].iov_base = call->data + Position; iov[1].iov_len = PacketLength; + ssize_t l = writev(call->fd, iov, 2); if (l < 0) { @@ -135,9 +147,11 @@ static int writeData(void *_call) break; } len += l; + Position += PacketLength; call->Pts = INVALID_PTS_VALUE; } + mpeg2_printf(10, "< len %d\n", len); return len; } diff --git a/libeplayer3-arm/output/writer/sh4/pcm.c b/libeplayer3-arm/output/writer/sh4/pcm.c index 5b752dd..4a7103f 100644 --- a/libeplayer3-arm/output/writer/sh4/pcm.c +++ b/libeplayer3-arm/output/writer/sh4/pcm.c @@ -124,10 +124,13 @@ static int32_t prepareClipPlay(int32_t uNoOfChannels, int32_t uSampleRate, int32 uBitsPerSample/*Format->wBitsPerSample*/, (uBitsPerSample/*Format->wBitsPerSample*/ / 8) ); + SubFrameLen = 0; SubFramesPerPES = 0; breakBufferFillSize = 0; + memcpy(lpcm_prv, clpcm_prv, sizeof(lpcm_prv)); + //figure out size of subframe //and set up sample rate switch (uSampleRate) @@ -158,14 +161,18 @@ static int32_t prepareClipPlay(int32_t uNoOfChannels, int32_t uSampleRate, int32 default: break; } + SubFrameLen *= uNoOfChannels; SubFrameLen *= (uBitsPerSample / 8); + //rewrite PES size to have as many complete subframes per PES as we can // FIXME: PES header size was hardcoded to 18 in previous code. Actual size returned by InsertPesHeader is 14. SubFramesPerPES = ((2048 - 18) - sizeof(lpcm_prv)) / SubFrameLen; SubFrameLen *= SubFramesPerPES; + //set number of channels lpcm_prv[10] = uNoOfChannels - 1; + switch (uBitsPerSample) { case 24: @@ -176,6 +183,7 @@ static int32_t prepareClipPlay(int32_t uNoOfChannels, int32_t uSampleRate, int32 printf("inappropriate bits per sample (%d) - must be 16 or 24\n", uBitsPerSample); return 1; } + return 0; } @@ -188,25 +196,33 @@ static int32_t reset() static int32_t writeData(void *_call) { WriterAVCallData_t *call = (WriterAVCallData_t *) _call; + unsigned char PesHeader[PES_MAX_HEADER_SIZE]; + pcm_printf(10, "\n"); + if (!call) { pcm_err("call data is NULL...\n"); return 0; } + pcm_printf(10, "AudioPts %lld\n", call->Pts); + if (!call->data || (call->len <= 0)) { pcm_err("parsing NULL Data. ignoring...\n"); return 0; } + if (call->fd < 0) { pcm_err("file pointer < 0. ignoring ...\n"); return 0; } + pcmPrivateData_t *pcmPrivateData = (pcmPrivateData_t *)call->private_data; + if (initialHeader) { uint32_t codecID = (uint32_t)pcmPrivateData->ffmpeg_codec_id; @@ -240,11 +256,14 @@ static int32_t writeData(void *_call) initialHeader = 0; prepareClipPlay(pcmPrivateData->channels, pcmPrivateData->sample_rate, pcmPrivateData->bits_per_coded_sample, LE); } + uint8_t *buffer = call->data; uint32_t size = call->len; + uint32_t n; uint8_t *injectBuffer = malloc(SubFrameLen); uint32_t pos; + for (pos = 0; pos < size;) { //printf("PCM %s - Position=%d\n", __FUNCTION__, pos); @@ -255,6 +274,7 @@ static int32_t writeData(void *_call) //printf("PCM %s - Unplayed=%d\n", __FUNCTION__, breakBufferFillSize); break; } + //get first PES's worth if (breakBufferFillSize > 0) { @@ -268,12 +288,15 @@ static int32_t writeData(void *_call) memcpy(injectBuffer, &buffer[pos], sizeof(uint8_t)*SubFrameLen); pos += SubFrameLen; } + struct iovec iov[3]; iov[0].iov_base = PesHeader; iov[1].iov_base = lpcm_prv; iov[1].iov_len = sizeof(lpcm_prv); + iov[2].iov_base = injectBuffer; iov[2].iov_len = SubFrameLen; + //write the PCM data if (16 == pcmPrivateData->bits_per_coded_sample) { @@ -305,8 +328,10 @@ static int32_t writeData(void *_call) p[ 8] = t; } } + //increment err... subframe count? lpcm_prv[1] = ((lpcm_prv[1] + SubFramesPerPES) & 0x1F); + iov[0].iov_len = InsertPesHeader(PesHeader, iov[1].iov_len + iov[2].iov_len, PCM_PES_START_CODE, call->Pts, 0); int32_t len = writev(call->fd, iov, 3); if (len < 0) @@ -315,6 +340,7 @@ static int32_t writeData(void *_call) } } free(injectBuffer); + return size; } diff --git a/libeplayer3-arm/output/writer/sh4/pes.c b/libeplayer3-arm/output/writer/sh4/pes.c index 8df20a8..12a7bd6 100644 --- a/libeplayer3-arm/output/writer/sh4/pes.c +++ b/libeplayer3-arm/output/writer/sh4/pes.c @@ -70,23 +70,30 @@ int InsertVideoPrivateDataHeader(unsigned char *data, int payload_size) { BitPacker_t ld2 = {data, 0, 32}; int i; + PutBits(&ld2, PES_PRIVATE_DATA_FLAG, 8); PutBits(&ld2, payload_size & 0xff, 8); PutBits(&ld2, (payload_size >> 8) & 0xff, 8); PutBits(&ld2, (payload_size >> 16) & 0xff, 8); + for (i = 4; i < (PES_PRIVATE_DATA_LENGTH + 1); i++) PutBits(&ld2, 0, 8); + FlushBits(&ld2); + return PES_PRIVATE_DATA_LENGTH + 1; + } int InsertPesHeader(unsigned char *data, int size, unsigned char stream_id, unsigned long long int pts, int pic_start_code) { BitPacker_t ld2 = {data, 0, 32}; + if (size > (MAX_PES_PACKET_SIZE - 13)) { size = -1; // unbounded } + PutBits(&ld2, 0x0, 8); PutBits(&ld2, 0x0, 8); PutBits(&ld2, 0x1, 8); // Start Code @@ -108,6 +115,7 @@ int InsertPesHeader(unsigned char *data, int size, unsigned char stream_id, unsi PutBits(&ld2, 0x0, 1); // Copyright PutBits(&ld2, 0x0, 1); // Original or Copy //7 = 6+1 + if (pts != INVALID_PTS_VALUE) { PutBits(&ld2, 0x2, 2); @@ -116,6 +124,7 @@ int InsertPesHeader(unsigned char *data, int size, unsigned char stream_id, unsi { PutBits(&ld2, 0x0, 2); // PTS_DTS flag } + PutBits(&ld2, 0x0, 1); // ESCR_flag PutBits(&ld2, 0x0, 1); // ES_rate_flag PutBits(&ld2, 0x0, 1); // DSM_trick_mode_flag @@ -123,11 +132,13 @@ int InsertPesHeader(unsigned char *data, int size, unsigned char stream_id, unsi PutBits(&ld2, 0x0, 1); // PES_CRC_flag PutBits(&ld2, 0x0, 1); // PES_extension_flag //8 = 7+1 + if (pts != INVALID_PTS_VALUE) PutBits(&ld2, 0x5, 8); else PutBits(&ld2, 0x0, 8); // PES_header_data_length //9 = 8+1 + if (pts != INVALID_PTS_VALUE) { PutBits(&ld2, 0x2, 4); @@ -139,6 +150,7 @@ int InsertPesHeader(unsigned char *data, int size, unsigned char stream_id, unsi PutBits(&ld2, 0x1, 1); } //14 = 9+5 + if (pic_start_code) { PutBits(&ld2, 0x0, 8); @@ -148,6 +160,8 @@ int InsertPesHeader(unsigned char *data, int size, unsigned char stream_id, unsi PutBits(&ld2, (pic_start_code >> 8) & 0xff, 8); // For any extra information (like in mpeg4p2, the pic_start_code) //14 + 4 = 18 } + FlushBits(&ld2); + return (ld2.Ptr - data); } diff --git a/libeplayer3-arm/output/writer/sh4/vc1.c b/libeplayer3-arm/output/writer/sh4/vc1.c index baa8129..4865e9f 100644 --- a/libeplayer3-arm/output/writer/sh4/vc1.c +++ b/libeplayer3-arm/output/writer/sh4/vc1.c @@ -127,25 +127,31 @@ static int reset() static int writeData(void *_call) { WriterAVCallData_t *call = (WriterAVCallData_t *) _call; + int len = 0; vc1_printf(10, "\n"); + if (call == NULL) { vc1_err("call data is NULL...\n"); return 0; } + if ((call->data == NULL) || (call->len <= 0)) { vc1_err("parsing NULL Data. ignoring...\n"); return 0; } + if (call->fd < 0) { vc1_err("file pointer < 0. ignoring ...\n"); return 0; } + vc1_printf(10, "VideoPts %lld\n", call->Pts); vc1_printf(10, "Got Private Size %d\n", call->private_size); + if (initialHeader) { unsigned char PesHeader[PES_MAX_HEADER_SIZE]; @@ -153,18 +159,25 @@ static int writeData(void *_call) unsigned char *PesPtr; unsigned int crazyFramerate = 0; struct iovec iov[2]; + vc1_printf(10, "Framerate: %u\n", call->FrameRate); vc1_printf(10, "biWidth: %d\n", call->Width); vc1_printf(10, "biHeight: %d\n", call->Height); + crazyFramerate = ((10000000.0 / call->FrameRate) * 1000.0); vc1_printf(10, "crazyFramerate: %u\n", crazyFramerate); + memset(PesPayload, 0, sizeof(PesPayload)); + PesPtr = PesPayload; + memcpy(PesPtr, SequenceLayerStartCode, sizeof(SequenceLayerStartCode)); PesPtr += sizeof(SequenceLayerStartCode); + memcpy(PesPtr, Metadata, sizeof(Metadata)); PesPtr += METADATA_STRUCT_C_START; PesPtr += WMV3_PRIVATE_DATA_LENGTH; + /* Metadata Header Struct A */ *PesPtr++ = (call->Height >> 0) & 0xff; *PesPtr++ = (call->Height >> 8) & 0xff; @@ -174,43 +187,56 @@ static int writeData(void *_call) *PesPtr++ = (call->Width >> 8) & 0xff; *PesPtr++ = (call->Width >> 16) & 0xff; *PesPtr++ = call->Width >> 24; + PesPtr += 12; /* Skip flag word and Struct B first 8 bytes */ + *PesPtr++ = (crazyFramerate >> 0) & 0xff; *PesPtr++ = (crazyFramerate >> 8) & 0xff; *PesPtr++ = (crazyFramerate >> 16) & 0xff; *PesPtr++ = crazyFramerate >> 24; + iov[0].iov_base = PesHeader; iov[1].iov_base = PesPayload; iov[1].iov_len = PesPtr - PesPayload; iov[0].iov_len = InsertPesHeader(PesHeader, iov[1].iov_len, VC1_VIDEO_PES_START_CODE, INVALID_PTS_VALUE, 0); len = writev(call->fd, iov, 2); + /* For VC1 the codec private data is a standard vc1 sequence header so we just copy it to the output */ iov[0].iov_base = PesHeader; iov[1].iov_base = call->private_data; iov[1].iov_len = call->private_size; iov[0].iov_len = InsertPesHeader(PesHeader, iov[1].iov_len, VC1_VIDEO_PES_START_CODE, INVALID_PTS_VALUE, 0); len = writev(call->fd, iov, 2); + initialHeader = 0; } + if (call->len > 0 && call->data) { uint32_t Position = 0; uint8_t insertSampleHeader = 1; + while (Position < call->len) { int32_t PacketLength = (call->len - Position) <= MAX_PES_PACKET_SIZE ? (call->len - Position) : MAX_PES_PACKET_SIZE; + int32_t Remaining = call->len - Position - PacketLength; + vc1_printf(20, "PacketLength=%d, Remaining=%d, Position=%d\n", PacketLength, Remaining, Position); + uint8_t PesHeader[PES_MAX_HEADER_SIZE]; int32_t HeaderLength = InsertPesHeader(PesHeader, PacketLength, VC1_VIDEO_PES_START_CODE, call->Pts, 0); + if (insertSampleHeader) { const uint8_t Vc1FrameStartCode[] = {0, 0, 1, VC1_FRAME_START_CODE}; + if (!FrameHeaderSeen && (call->len > 3) && (memcmp(call->data, Vc1FrameStartCode, 4) == 0)) { FrameHeaderSeen = 1; } + if (!FrameHeaderSeen) { memcpy(&PesHeader[HeaderLength], Vc1FrameStartCode, sizeof(Vc1FrameStartCode)); @@ -218,11 +244,13 @@ static int writeData(void *_call) } insertSampleHeader = 0; } + struct iovec iov[2]; iov[0].iov_base = PesHeader; iov[0].iov_len = HeaderLength; iov[1].iov_base = call->data + Position; iov[1].iov_len = PacketLength; + ssize_t l = writev(call->fd, iov, 2); if (l < 0) { @@ -230,10 +258,12 @@ static int writeData(void *_call) break; } len += l; + Position += PacketLength; call->Pts = INVALID_PTS_VALUE; } } + vc1_printf(10, "< %d\n", len); return len; } diff --git a/libeplayer3-arm/output/writer/sh4/vorbis.c b/libeplayer3-arm/output/writer/sh4/vorbis.c index 0b09940..3ed1cb2 100644 --- a/libeplayer3-arm/output/writer/sh4/vorbis.c +++ b/libeplayer3-arm/output/writer/sh4/vorbis.c @@ -50,8 +50,6 @@ /* Makros/Constants */ /* ***************************** */ -//#define SAM_WITH_DEBUG - #ifdef SAM_WITH_DEBUG #define VORBIS_DEBUG #else @@ -98,30 +96,42 @@ static int reset() static int writeData(void *_call) { WriterAVCallData_t *call = (WriterAVCallData_t *) _call; + unsigned char PesHeader[PES_MAX_HEADER_SIZE]; + vorbis_printf(10, "\n"); + if (call == NULL) { vorbis_err("call data is NULL...\n"); return 0; } + vorbis_printf(10, "AudioPts %lld\n", call->Pts); + if ((call->data == NULL) || (call->len <= 0)) { vorbis_err("parsing NULL Data. ignoring...\n"); return 0; } + if (call->fd < 0) { vorbis_err("file pointer < 0. ignoring ...\n"); return 0; } + int HeaderLength = InsertPesHeader(PesHeader, call->len, MPEG_AUDIO_PES_START_CODE, call->Pts, 0); + unsigned char *PacketStart = malloc(call->len + HeaderLength); + memcpy(PacketStart, PesHeader, HeaderLength); memcpy(PacketStart + HeaderLength, call->data, call->len); + int len = write(call->fd, PacketStart, call->len + HeaderLength); + free(PacketStart); + vorbis_printf(10, "vorbis_Write-< len=%d\n", len); return len; } diff --git a/libeplayer3-arm/output/writer/sh4/wma.c b/libeplayer3-arm/output/writer/sh4/wma.c index 39a42a9..4b92ac5 100644 --- a/libeplayer3-arm/output/writer/sh4/wma.c +++ b/libeplayer3-arm/output/writer/sh4/wma.c @@ -51,8 +51,6 @@ /* Makros/Constants */ /* ***************************** */ -//#define SAM_WITH_DEBUG - #ifdef SAM_WITH_DEBUG #define WMA_DEBUG #else @@ -102,32 +100,41 @@ static int reset() static int writeData(void *_call) { WriterAVCallData_t *call = (WriterAVCallData_t *) _call; + int len = 0; + wma_printf(10, "\n"); + if (call == NULL) { wma_err("call data is NULL...\n"); return 0; } + wma_printf(10, "AudioPts %lld\n", call->Pts); + if ((call->data == NULL) || (call->len <= 0)) { wma_err("parsing NULL Data. ignoring...\n"); return 0; } + if (call->fd < 0) { wma_err("file pointer < 0. ignoring ...\n"); return 0; } + if (initialHeader) { unsigned char PesHeader[PES_MAX_HEADER_SIZE]; + if ((call->private_size <= 0) || (call->private_data == NULL)) { wma_err("private NULL.\n"); return -1; } + struct iovec iov[2]; iov[0].iov_base = PesHeader; iov[0].iov_len = InsertPesHeader(PesHeader, call->private_size, MPEG_AUDIO_PES_START_CODE, 0, 0); @@ -136,6 +143,7 @@ static int writeData(void *_call) len = writev(call->fd, iov, 2); initialHeader = 0; } + if (len > -1 && call->len > 0 && call->data) { unsigned char PesHeader[PES_MAX_HEADER_SIZE]; @@ -144,10 +152,13 @@ static int writeData(void *_call) iov[0].iov_len = InsertPesHeader(PesHeader, call->len, MPEG_AUDIO_PES_START_CODE, call->Pts, 0); iov[1].iov_base = call->data; iov[1].iov_len = call->len; + ssize_t l = writev(call->fd, iov, 2); len = (l > -1) ? len + l : l; } + wma_printf(10, "wma < %d\n", len); + return len; } diff --git a/libeplayer3-arm/output/writer/sh4/wmv.c b/libeplayer3-arm/output/writer/sh4/wmv.c index cc61134..9a644d9 100644 --- a/libeplayer3-arm/output/writer/sh4/wmv.c +++ b/libeplayer3-arm/output/writer/sh4/wmv.c @@ -128,31 +128,40 @@ static int reset() static int writeData(void *_call) { WriterAVCallData_t *call = (WriterAVCallData_t *) _call; + awmv_t private_data; int len = 0; + wmv_printf(10, "\n"); + if (call == NULL) { wmv_err("call data is NULL...\n"); return 0; } + if ((call->data == NULL) || (call->len <= 0)) { wmv_err("parsing NULL Data. ignoring...\n"); return 0; } + if (call->fd < 0) { wmv_err("file pointer < 0. ignoring ...\n"); return 0; } + wmv_printf(10, "VideoPts %lld\n", call->Pts); wmv_printf(10, "Got Private Size %d\n", call->private_size); + memcpy(private_data.privateData, call->private_data, call->private_size > WMV3_PRIVATE_DATA_LENGTH ? WMV3_PRIVATE_DATA_LENGTH : call->private_size); + private_data.width = call->Width; private_data.height = call->Height; private_data.framerate = call->FrameRate; + #define PES_MIN_HEADER_SIZE 9 if (initialHeader) { @@ -160,16 +169,22 @@ static int writeData(void *_call) unsigned char *PesPtr; unsigned int MetadataLength; unsigned int crazyFramerate = 0; + wmv_printf(10, "Framerate: %u\n", private_data.framerate); wmv_printf(10, "biWidth: %d\n", private_data.width); wmv_printf(10, "biHeight: %d\n", private_data.height); + crazyFramerate = ((10000000.0 / private_data.framerate) * 1000.0); wmv_printf(10, "crazyFramerate: %u\n", crazyFramerate); + PesPtr = &PesPacket[PES_MIN_HEADER_SIZE]; + memcpy(PesPtr, Metadata, sizeof(Metadata)); PesPtr += METADATA_STRUCT_C_START; + memcpy(PesPtr, private_data.privateData, WMV3_PRIVATE_DATA_LENGTH); PesPtr += WMV3_PRIVATE_DATA_LENGTH; + /* Metadata Header Struct A */ *PesPtr++ = (private_data.height >> 0) & 0xff; *PesPtr++ = (private_data.height >> 8) & 0xff; @@ -179,16 +194,23 @@ static int writeData(void *_call) *PesPtr++ = (private_data.width >> 8) & 0xff; *PesPtr++ = (private_data.width >> 16) & 0xff; *PesPtr++ = private_data.width >> 24; + PesPtr += 12; /* Skip flag word and Struct B first 8 bytes */ + *PesPtr++ = (crazyFramerate >> 0) & 0xff; *PesPtr++ = (crazyFramerate >> 8) & 0xff; *PesPtr++ = (crazyFramerate >> 16) & 0xff; *PesPtr++ = crazyFramerate >> 24; + MetadataLength = PesPtr - &PesPacket[PES_MIN_HEADER_SIZE]; + int HeaderLength = InsertPesHeader(PesPacket, MetadataLength, VC1_VIDEO_PES_START_CODE, INVALID_PTS_VALUE, 0); + len = write(call->fd, PesPacket, HeaderLength + MetadataLength); + initialHeader = 0; } + if (call->len > 0 && call->data) { unsigned int Position = 0; @@ -197,12 +219,16 @@ static int writeData(void *_call) { int PacketLength = (call->len - Position) <= MAX_PES_PACKET_SIZE ? (call->len - Position) : MAX_PES_PACKET_SIZE; + int Remaining = call->len - Position - PacketLength; + wmv_printf(20, "PacketLength=%d, Remaining=%d, Position=%d\n", PacketLength, Remaining, Position); + unsigned char PesHeader[PES_MAX_HEADER_SIZE]; memset(PesHeader, '0', PES_MAX_HEADER_SIZE); int HeaderLength = InsertPesHeader(PesHeader, PacketLength, VC1_VIDEO_PES_START_CODE, call->Pts, 0); unsigned char *PacketStart; + if (insertSampleHeader) { unsigned int PesLength; @@ -215,18 +241,23 @@ static int writeData(void *_call) PesHeader[PES_LENGTH_BYTE_1] = (PesLength >> 8) & 0xff; PesHeader[PES_HEADER_DATA_LENGTH_BYTE] += PrivateHeaderLength; PesHeader[PES_FLAGS_BYTE] |= PES_EXTENSION_DATA_PRESENT; + HeaderLength += PrivateHeaderLength; insertSampleHeader = 0; } + PacketStart = malloc(call->len + HeaderLength); memcpy(PacketStart, PesHeader, HeaderLength); memcpy(PacketStart + HeaderLength, call->data + Position, PacketLength); + len = write(call->fd, PacketStart, PacketLength + HeaderLength); free(PacketStart); + Position += PacketLength; call->Pts = INVALID_PTS_VALUE; } } + wmv_printf(10, "< %d\n", len); return len; } diff --git a/libeplayer3-arm/output/writer/sh4/writer.c b/libeplayer3-arm/output/writer/sh4/writer.c index a9d8548..1ac9cf2 100644 --- a/libeplayer3-arm/output/writer/sh4/writer.c +++ b/libeplayer3-arm/output/writer/sh4/writer.c @@ -100,6 +100,7 @@ static Writer_t *AvailableWriter[] = Writer_t *getWriter(char *encoding) { int i; + for (i = 0; AvailableWriter[i] != NULL; i++) { if (strcmp(AvailableWriter[i]->caps->textEncoding, encoding) == 0) @@ -108,13 +109,16 @@ Writer_t *getWriter(char *encoding) return AvailableWriter[i]; } } + writer_printf(1, "%s: no writer found for \"%s\"\n", __func__, encoding); + return NULL; } Writer_t *getDefaultVideoWriter() { int i; + for (i = 0; AvailableWriter[i] != NULL; i++) { if (strcmp(AvailableWriter[i]->caps->textEncoding, "V_MPEG2") == 0) @@ -123,13 +127,16 @@ Writer_t *getDefaultVideoWriter() return AvailableWriter[i]; } } + writer_printf(1, "%s: no writer found\n", __func__); + return NULL; } Writer_t *getDefaultAudioWriter() { int i; + for (i = 0; AvailableWriter[i] != NULL; i++) { if (strcmp(AvailableWriter[i]->caps->textEncoding, "A_MP3") == 0) @@ -138,6 +145,8 @@ Writer_t *getDefaultAudioWriter() return AvailableWriter[i]; } } + writer_printf(1, "%s: no writer found\n", __func__); + return NULL; } diff --git a/libeplayer3-arm/playback/playback.c b/libeplayer3-arm/playback/playback.c index bac6adb..6ed983e 100644 --- a/libeplayer3-arm/playback/playback.c +++ b/libeplayer3-arm/playback/playback.c @@ -114,7 +114,7 @@ bool PlaybackDieNowRegisterCallback(PlaybackDieNowCallback callback) ret = true; break; } - + if (playbackDieNowCallbacks[i] == NULL) { playbackDieNowCallbacks[i] = callback; @@ -135,6 +135,7 @@ static void SupervisorThread(Context_t *context) { hasThreadStarted = 1; playback_printf(10, ">\n"); + while (context && context->playback && context->playback->isPlaying && !context->playback->abortRequested) { usleep(100000); @@ -158,19 +159,26 @@ static int PlaybackOpen(Context_t *context, PlayFiles_t *pFiles) { PlaybackStop(context); } + char *uri = pFiles->szFirstFile; + playback_printf(10, "URI=%s\n", uri); + if (context->playback->isPlaying) { // shouldn't happen playback_err("playback already running\n"); return cERR_PLAYBACK_ERROR; } + char *extension = NULL; + context->playback->uri = strdup(uri); + context->playback->isFile = 0; context->playback->isHttp = 0; context->playback->noprobe = 0; + if (!strncmp("file://", uri, 7) || !strncmp("myts://", uri, 7)) { context->playback->isFile = 1; @@ -183,6 +191,7 @@ static int PlaybackOpen(Context_t *context, PlayFiles_t *pFiles) { context->playback->noprobe = 0; } + extension = getExtension(context->playback->uri + 7); if (!extension) { @@ -207,6 +216,7 @@ static int PlaybackOpen(Context_t *context, PlayFiles_t *pFiles) free(context->playback->uri); context->playback->uri = tUri; } + if (strstr(uri, ":10000") || strstr(uri, ":31339/id=")) { context->playback->noprobe = 1; @@ -217,6 +227,7 @@ static int PlaybackOpen(Context_t *context, PlayFiles_t *pFiles) playback_err("Unknown stream (%s)\n", uri); return cERR_PLAYBACK_ERROR; } + pFiles->szFirstFile = context->playback->uri; if ((context->container->Command(context, CONTAINER_ADD, extension) < 0) || (!context->container->selectedContainer) || @@ -225,20 +236,26 @@ static int PlaybackOpen(Context_t *context, PlayFiles_t *pFiles) playback_err("CONTAINER_ADD failed\n"); return cERR_PLAYBACK_ERROR; } + playback_printf(10, "exiting with value 0\n"); + return cERR_PLAYBACK_NO_ERROR; } static int PlaybackClose(Context_t *context) { int ret = cERR_PLAYBACK_NO_ERROR; + playback_printf(10, "\n"); + if (context->container->Command(context, CONTAINER_DEL, NULL) < 0) { playback_err("container delete failed\n"); } + context->manager->audio->Command(context, MANAGER_DEL, NULL); context->manager->video->Command(context, MANAGER_DEL, NULL); + context->playback->isPaused = 0; context->playback->isPlaying = 0; context->playback->isForwarding = 0; @@ -250,8 +267,10 @@ static int PlaybackClose(Context_t *context) free(context->playback->uri); context->playback->uri = NULL; } + PlaybackDieNow(2); playback_printf(10, "exiting with value %d\n", ret); + return ret; } @@ -259,13 +278,17 @@ static int PlaybackPlay(Context_t *context) { pthread_attr_t attr; int ret = cERR_PLAYBACK_NO_ERROR; + playback_printf(10, "\n"); + if (!context->playback->isPlaying) { context->playback->AVSync = 1; context->output->Command(context, OUTPUT_AVSYNC, NULL); + context->playback->isCreationPhase = 1; // allows the created thread to go into wait mode ret = context->output->Command(context, OUTPUT_PLAY, NULL); + if (ret != 0) { playback_err("OUTPUT_PLAY failed!\n"); @@ -287,6 +310,7 @@ static int PlaybackPlay(Context_t *context) context->playback->BackWard = 0; context->playback->SlowMotion = 0; context->playback->Speed = 1; + if (hasThreadStarted == 0) { int error; @@ -302,13 +326,17 @@ static int PlaybackPlay(Context_t *context) playback_printf(10, "Created thread\n"); } } + playback_printf(10, "clearing isCreationPhase!\n"); + context->playback->isCreationPhase = 0; // allow thread to go into next state + ret = context->container->selectedContainer->Command(context, CONTAINER_PLAY, NULL); if (ret != 0) { playback_err("CONTAINER_PLAY failed!\n"); } + } } else @@ -316,19 +344,25 @@ static int PlaybackPlay(Context_t *context) playback_err("playback already running\n"); ret = cERR_PLAYBACK_ERROR; } + playback_printf(10, "exiting with value %d\n", ret); + return ret; } static int PlaybackPause(Context_t *context) { int ret = cERR_PLAYBACK_NO_ERROR; + playback_printf(10, "\n"); + if (context->playback->isPlaying && !context->playback->isPaused) { if (context->playback->SlowMotion) context->output->Command(context, OUTPUT_CLEAR, NULL); + context->output->Command(context, OUTPUT_PAUSE, NULL); + context->playback->isPaused = 1; //context->playback->isPlaying = 1; context->playback->isForwarding = 0; @@ -341,6 +375,7 @@ static int PlaybackPause(Context_t *context) playback_err("playback not playing or already in pause mode\n"); ret = cERR_PLAYBACK_ERROR; } + playback_printf(10, "exiting with value %d\n", ret); return ret; } @@ -348,15 +383,19 @@ static int PlaybackPause(Context_t *context) static int32_t PlaybackContinue(Context_t *context) { int32_t ret = cERR_PLAYBACK_NO_ERROR; + playback_printf(10, "\n"); + if (context->playback->isPlaying && (context->playback->isPaused || context->playback->isForwarding || context->playback->BackWard || context->playback->SlowMotion)) { if (context->playback->SlowMotion || context->playback->isForwarding || context->playback->BackWard) context->output->Command(context, OUTPUT_CLEAR, NULL); + if (context->playback->BackWard) context->output->Command(context, OUTPUT_AUDIOMUTE, "0"); + context->playback->isPaused = 0; //context->playback->isPlaying = 1; context->playback->isForwarding = 0; @@ -370,6 +409,7 @@ static int32_t PlaybackContinue(Context_t *context) playback_err("continue not possible\n"); ret = cERR_PLAYBACK_ERROR; } + playback_printf(10, "exiting with value %d\n", ret); return ret; } @@ -378,34 +418,43 @@ static int32_t PlaybackStop(Context_t *context) { int32_t ret = cERR_PLAYBACK_NO_ERROR; int wait_time = 20; + playback_printf(10, "\n"); + PlaybackDieNow(1); + if (context && context->playback && context->playback->isPlaying) { + context->playback->isPaused = 0; context->playback->isPlaying = 0; context->playback->isForwarding = 0; context->playback->BackWard = 0; context->playback->SlowMotion = 0; context->playback->Speed = 0; + context->output->Command(context, OUTPUT_STOP, NULL); context->container->selectedContainer->Command(context, CONTAINER_STOP, NULL); + } else { playback_err("stop not possible\n"); ret = cERR_PLAYBACK_ERROR; } + while ((hasThreadStarted == 1) && (--wait_time) > 0) { playback_printf(10, "Waiting for supervisor thread to terminate itself, will try another %d times\n", wait_time); usleep(100000); } + if (wait_time == 0) { playback_err("Timeout waiting for thread!\n"); ret = cERR_PLAYBACK_ERROR; } + playback_printf(10, "exiting with value %d\n", ret); return ret; } @@ -413,16 +462,22 @@ static int32_t PlaybackStop(Context_t *context) static int32_t PlaybackTerminate(Context_t *context) { int32_t ret = cERR_PLAYBACK_NO_ERROR; + int wait_time = 20; + playback_printf(20, "\n"); + PlaybackDieNow(1); + if (context && context->playback && context->playback->isPlaying) { //First Flush and than delete container, else e2 cant read length of file anymore + if (context->output->Command(context, OUTPUT_FLUSH, NULL) < 0) { playback_err("failed to flush output.\n"); } + context->playback->isPaused = 0; context->playback->isPlaying = 0; context->playback->isForwarding = 0; @@ -435,21 +490,25 @@ static int32_t PlaybackTerminate(Context_t *context) else { playback_err("%p %p %d\n", context, context->playback, context->playback->isPlaying); + /* fixme: konfetti: we should return an error here but this seems to be a condition which * can happen and is not a real error, which leads to a dead neutrino. should investigate * here later. */ } + while ((hasThreadStarted == 1) && (--wait_time) > 0) { playback_printf(10, "Waiting for supervisor thread to terminate itself, will try another %d times\n", wait_time); usleep(100000); } + if (wait_time == 0) { playback_err("Timeout waiting for thread!\n"); ret = cERR_PLAYBACK_ERROR; } + playback_printf(20, "exiting with value %d\n", ret); return ret; } @@ -457,7 +516,9 @@ static int32_t PlaybackTerminate(Context_t *context) static int PlaybackFastForward(Context_t *context, int *speed) { int32_t ret = cERR_PLAYBACK_NO_ERROR; + playback_printf(10, "speed %d\n", *speed); + /* Audio only forwarding not supported */ if (context->playback->isVideo && !context->playback->isHttp && !context->playback->BackWard && (!context->playback->isPaused || context->playback->isPlaying)) { @@ -477,14 +538,18 @@ static int PlaybackFastForward(Context_t *context, int *speed) playback_err("fast forward not possible\n"); ret = cERR_PLAYBACK_ERROR; } + playback_printf(10, "exiting with value %d\n", ret); + return ret; } static int PlaybackFastBackward(Context_t *context, int *speed) { int32_t ret = cERR_PLAYBACK_NO_ERROR; + playback_printf(10, "speed = %d\n", *speed); + /* Audio only reverse play not supported */ if (context->playback->isVideo && !context->playback->isForwarding && (!context->playback->isPaused || context->playback->isPlaying)) @@ -508,6 +573,7 @@ static int PlaybackFastBackward(Context_t *context, int *speed) context->output->Command(context, OUTPUT_AUDIOMUTE, "1"); playback_printf(1, "S %d B %d\n", context->playback->Speed, context->playback->BackWard); } + context->output->Command(context, OUTPUT_CLEAR, NULL); } else @@ -515,15 +581,19 @@ static int PlaybackFastBackward(Context_t *context, int *speed) playback_err("fast backward not possible\n"); ret = cERR_PLAYBACK_ERROR; } + context->playback->isSeeking = 0; playback_printf(10, "exiting with value %d\n", ret); + return ret; } static int32_t PlaybackSlowMotion(Context_t *context, int *speed) { int32_t ret = cERR_PLAYBACK_NO_ERROR; + playback_printf(10, "\n"); + //Audio only forwarding not supported if (context->playback->isVideo && !context->playback->isHttp && context->playback->isPlaying) { @@ -549,14 +619,18 @@ static int32_t PlaybackSlowMotion(Context_t *context, int *speed) playback_err("slowmotion not possible\n"); ret = cERR_PLAYBACK_ERROR; } + playback_printf(10, "exiting with value %d\n", ret); + return ret; } static int32_t PlaybackSeek(Context_t *context, int64_t *pos, uint8_t absolute) { int32_t ret = cERR_PLAYBACK_NO_ERROR; + playback_printf(10, "pos: %lldd\n", *pos); + if (context->playback->isPlaying && !context->playback->isForwarding && !context->playback->BackWard && !context->playback->SlowMotion && !context->playback->isPaused) { context->playback->isSeeking = 1; @@ -576,15 +650,20 @@ static int32_t PlaybackSeek(Context_t *context, int64_t *pos, uint8_t absolute) playback_err("not possible\n"); ret = cERR_PLAYBACK_ERROR; } + playback_printf(10, "exiting with value %d\n", ret); + return ret; } static int32_t PlaybackPts(Context_t *context, int64_t *pts) { int32_t ret = cERR_PLAYBACK_NO_ERROR; + playback_printf(20, "\n"); + *pts = 0; + if (context->playback->isPlaying) { ret = context->output->Command(context, OUTPUT_PTS, pts); @@ -594,15 +673,20 @@ static int32_t PlaybackPts(Context_t *context, int64_t *pts) playback_err("not possible\n"); ret = cERR_PLAYBACK_ERROR; } + playback_printf(20, "exiting with value %d\n", ret); + return ret; } static int32_t PlaybackGetFrameCount(Context_t *context, uint64_t *frameCount) { int ret = cERR_PLAYBACK_NO_ERROR; + playback_printf(20, "\n"); + *frameCount = 0; + if (context->playback->isPlaying) { ret = context->output->Command(context, OUTPUT_GET_FRAME_COUNT, frameCount); @@ -612,15 +696,20 @@ static int32_t PlaybackGetFrameCount(Context_t *context, uint64_t *frameCount) playback_err("not possible\n"); ret = cERR_PLAYBACK_ERROR; } + playback_printf(20, "exiting with value %d\n", ret); + return ret; } static int32_t PlaybackLength(Context_t *context, int64_t *length) { int32_t ret = cERR_PLAYBACK_NO_ERROR; + playback_printf(20, "\n"); + *length = -1; + if (context->playback->isPlaying) { if (context->container && context->container->selectedContainer) @@ -633,6 +722,7 @@ static int32_t PlaybackLength(Context_t *context, int64_t *length) playback_err("not possible\n"); ret = cERR_PLAYBACK_ERROR; } + playback_printf(20, "exiting with value %d\n", ret); return ret; } @@ -642,7 +732,9 @@ static int32_t PlaybackSwitchAudio(Context_t *context, int32_t *track) int32_t ret = cERR_PLAYBACK_NO_ERROR; int32_t curtrackid = 0; int32_t nextrackid = 0; + playback_printf(10, "\n"); + if (context && context->playback && context->playback->isPlaying) { if (context->manager && context->manager->audio) @@ -656,13 +748,16 @@ static int32_t PlaybackSwitchAudio(Context_t *context, int32_t *track) playback_err("switch audio not possible\n"); ret = cERR_PLAYBACK_ERROR; } + if (nextrackid != curtrackid) { + //PlaybackPause(context); if (context->output && context->output->audio) { context->output->audio->Command(context, OUTPUT_SWITCH, (void *)"audio"); } + if (context->container && context->container->selectedContainer) { context->container->selectedContainer->Command(context, CONTAINER_SWITCH_AUDIO, &nextrackid); @@ -675,6 +770,7 @@ static int32_t PlaybackSwitchAudio(Context_t *context, int32_t *track) playback_err("switch audio not possible\n"); ret = cERR_PLAYBACK_ERROR; } + playback_printf(10, "exiting with value %d\n", ret); return ret; } @@ -684,7 +780,9 @@ static int32_t PlaybackSwitchSubtitle(Context_t *context, int32_t *track) int32_t ret = cERR_PLAYBACK_NO_ERROR; int32_t curtrackid = -1; int32_t nextrackid = -1; + playback_printf(10, "Track: %d\n", *track); + if (context && context->playback && context->playback->isPlaying) { if (context->manager && context->manager->subtitle) @@ -692,12 +790,14 @@ static int32_t PlaybackSwitchSubtitle(Context_t *context, int32_t *track) context->manager->subtitle->Command(context, MANAGER_GET, &curtrackid); context->manager->subtitle->Command(context, MANAGER_SET, track); context->manager->subtitle->Command(context, MANAGER_GET, &nextrackid); + if (curtrackid != nextrackid && nextrackid > -1) { if (context->output && context->output->subtitle) { context->output->subtitle->Command(context, OUTPUT_SWITCH, (void *)"subtitle"); } + if (context->container && context->container->selectedContainer) { context->container->selectedContainer->Command(context, CONTAINER_SWITCH_SUBTITLE, &nextrackid); @@ -715,14 +815,18 @@ static int32_t PlaybackSwitchSubtitle(Context_t *context, int32_t *track) playback_err("not possible\n"); ret = cERR_PLAYBACK_ERROR; } + playback_printf(10, "exiting with value %d\n", ret); + return ret; } static int32_t PlaybackInfo(Context_t *context, char **infoString) { int32_t ret = cERR_PLAYBACK_NO_ERROR; + playback_printf(10, "\n"); + /* konfetti comment: * removed if clause here (playback running) because its * not necessary for all container. e.g. in case of ffmpeg @@ -732,7 +836,9 @@ static int32_t PlaybackInfo(Context_t *context, char **infoString) { context->container->selectedContainer->Command(context, CONTAINER_INFO, infoString); } + playback_printf(10, "exiting with value %d\n", ret); + return ret; } @@ -742,13 +848,17 @@ static int PlaybackMetadata(Context_t *context, char ***metadata) if (context->container && context->container->selectedContainer) context->container->selectedContainer->Command(context, CONTAINER_GET_METADATA, metadata); + return ret; } static int32_t Command(Context_t *context, PlaybackCmd_t command, void *argument) { int32_t ret = cERR_PLAYBACK_NO_ERROR; + playback_printf(20, "Command %d\n", command); + + switch (command) { case PLAYBACK_OPEN: @@ -851,7 +961,9 @@ static int32_t Command(Context_t *context, PlaybackCmd_t command, void *argument ret = cERR_PLAYBACK_ERROR; break; } + playback_printf(20, "exiting with value %d\n", ret); + return ret; } From e492bf70e50f8b254a8e328189663523bf426fd4 Mon Sep 17 00:00:00 2001 From: samsamsam Date: Sat, 7 Apr 2018 12:47:45 +0200 Subject: [PATCH 08/19] Add possibility to provide moov atom data as separate file. This will allow playback of MP4 files which are under download and moov atom is located at the end of file. Signed-off-by: max_10 Origin commit data ------------------ Branch: master Commit: https://github.com/neutrino-images/ni-libstb-hal/commit/0583ed7ec4b24aa5b10a14326c7243f9bc48b8b1 Author: samsamsam Date: 2018-04-07 (Sat, 07 Apr 2018) ------------------ This commit was generated by Migit --- libeplayer3-arm/container/container_ffmpeg.c | 155 ++++++++++++++++--- libeplayer3-arm/include/common.h | 8 +- libeplayer3-arm/main/exteplayer.c | 63 +++++--- libeplayer3-arm/output/writer/mipsel/h264.c | 2 +- libeplayer3-arm/output/writer/sh4/h264.c | 23 ++- 5 files changed, 198 insertions(+), 53 deletions(-) diff --git a/libeplayer3-arm/container/container_ffmpeg.c b/libeplayer3-arm/container/container_ffmpeg.c index f0f17c6..a8b4f46 100644 --- a/libeplayer3-arm/container/container_ffmpeg.c +++ b/libeplayer3-arm/container/container_ffmpeg.c @@ -1353,40 +1353,142 @@ static int32_t interrupt_cb(void *ctx) } #ifdef SAM_CUSTOM_IO +typedef struct CustomIOCtx_t +{ + FILE *pFile; + FILE *pMoovFile; + int64_t iOffset; + + char *szFile; + uint64_t iFileSize; + char *szMoovAtomFile; + uint64_t iMoovAtomOffset; +} CustomIOCtx_t; + +CustomIOCtx_t *custom_io_tab[IPTV_AV_CONTEXT_MAX_NUM] = {NULL, NULL}; + int SAM_ReadFunc(void *ptr, uint8_t *buffer, int lSize) { - size_t ret = fread((void *) buffer, (size_t) 1, (size_t) lSize, (FILE *)ptr); - return (int)ret; + CustomIOCtx_t *io = (CustomIOCtx_t *)ptr; + int ret = 0; + + if (!io->pMoovFile) + { + ret = (int)fread((void *) buffer, (size_t) 1, (size_t) lSize, io->pFile); + } + else + { + if (io->iOffset < io->iMoovAtomOffset) + { + ret = (int)fread((void *) buffer, (size_t) 1, (size_t) lSize, io->pFile); + buffer += ret; + lSize -= ret; + } + + if (io->iOffset + ret >= io->iMoovAtomOffset) + { + if (ret) + { + if (fseeko(io->pMoovFile, io->iOffset + ret - io->iMoovAtomOffset, SEEK_SET)) + { + // something goes wrong + ffmpeg_err("fseeko on moov atom file fail \n"); + lSize = 0; + } + } + + ret += (int)fread((void *) buffer, (size_t) 1, (size_t) lSize, io->pMoovFile); + } + + io->iOffset += ret; + } + return ret; } // whence: SEEK_SET, SEEK_CUR, SEEK_END (like fseek) and AVSEEK_SIZE int64_t SAM_SeekFunc(void *ptr, int64_t pos, int whence) { - if (AVSEEK_SIZE == whence) + CustomIOCtx_t *io = (CustomIOCtx_t *)ptr; + int64_t ret = -1; + if (!io->pMoovFile) { - return -1; + if (AVSEEK_SIZE != whence) + { + ret = (int64_t)fseeko(io->pFile, (off_t)pos, whence); + if (0 == ret) + { + ret = (int64_t)ftello(io->pFile); + } + } } - int ret = fseeko((FILE *)ptr, (off_t)pos, whence); - if (0 == ret) + else { - return (off_t)ftello((FILE *)ptr); + switch (whence) + { + case SEEK_SET: + ret = pos; + break; + case SEEK_CUR: + ret += pos; + break; + case SEEK_END: + ret = io->iFileSize + pos; + break; + case AVSEEK_SIZE: + return io->iFileSize; + default: + return -1; + } + + if (ret >= 0 && ret <= io->iFileSize) + { + if (ret < io->iMoovAtomOffset) + { + if (!fseeko(io->pFile, (off_t)ret, SEEK_SET)) + io->iOffset = ret; + else + ret = -1; + } + else + { + if (!fseeko(io->pMoovFile, (off_t)(ret - io->iMoovAtomOffset), SEEK_SET)) + io->iOffset = ret; + else + ret = -1; + } + } + else + { + ret = -1; + } } return ret; } -AVIOContext *container_ffmpeg_get_avio_context(char *filename, size_t avio_ctx_buffer_size) +AVIOContext *container_ffmpeg_get_avio_context(CustomIOCtx_t *custom_io, size_t avio_ctx_buffer_size) { - if (strstr(filename, "file://") == filename) - { - filename += 7; - } + if (strstr(custom_io->szFile, "file://") == custom_io->szFile) + custom_io->szFile += 7; - FILE *pFile = fopen(filename, "rb"); - if (NULL == pFile) + custom_io->pFile = fopen(custom_io->szFile, "rb"); + if (NULL == custom_io->pFile) { return NULL; } + if (custom_io->szMoovAtomFile && custom_io->szMoovAtomFile[0] != '\0') + { + if (strstr(custom_io->szMoovAtomFile, "file://") == custom_io->szMoovAtomFile) + custom_io->szMoovAtomFile += 7; + + custom_io->pMoovFile = fopen(custom_io->szMoovAtomFile, "rb"); + if (NULL == custom_io->pMoovFile) + { + fclose(custom_io->pFile); + return NULL; + } + } + AVIOContext *avio_ctx = NULL; uint8_t *avio_ctx_buffer = NULL; @@ -1395,7 +1497,7 @@ AVIOContext *container_ffmpeg_get_avio_context(char *filename, size_t avio_ctx_b { return NULL; } - avio_ctx = avio_alloc_context(avio_ctx_buffer, avio_ctx_buffer_size, 0, pFile, &SAM_ReadFunc, NULL, &SAM_SeekFunc); + avio_ctx = avio_alloc_context(avio_ctx_buffer, avio_ctx_buffer_size, 0, custom_io, &SAM_ReadFunc, NULL, &SAM_SeekFunc); if (!avio_ctx) { return NULL; @@ -1404,7 +1506,7 @@ AVIOContext *container_ffmpeg_get_avio_context(char *filename, size_t avio_ctx_b } #endif -int32_t container_ffmpeg_init_av_context(Context_t *context, char *filename, int32_t AVIdx) +int32_t container_ffmpeg_init_av_context(Context_t *context, char *filename, uint64_t fileSize, char *moovAtomFile, uint64_t moovAtomOffset, int32_t AVIdx) { int32_t err = 0; AVInputFormat *fmt = NULL; @@ -1416,7 +1518,16 @@ int32_t container_ffmpeg_init_av_context(Context_t *context, char *filename, int if (0 == strstr(filename, "://") || 0 == strncmp(filename, "file://", 7)) { - AVIOContext *avio_ctx = container_ffmpeg_get_avio_context(filename, 4096); + AVIOContext *avio_ctx = NULL; + custom_io_tab[AVIdx] = malloc(sizeof(CustomIOCtx_t)); + sizeof(custom_io_tab[AVIdx], 0x00, sizeof(CustomIOCtx_t)); + + custom_io_tab[AVIdx]->szFile = filename; + custom_io_tab[AVIdx]->iFileSize = fileSize; + custom_io_tab[AVIdx]->szMoovAtomFile = moovAtomFile; + custom_io_tab[AVIdx]->iMoovAtomOffset = moovAtomOffset; + + avio_ctx = container_ffmpeg_get_avio_context(custom_io_tab[AVIdx], 4096); if (avio_ctx) { avContextTab[AVIdx]->pb = avio_ctx; @@ -1424,6 +1535,8 @@ int32_t container_ffmpeg_init_av_context(Context_t *context, char *filename, int } else { + free(custom_io_tab[AVIdx]); + custom_io_tab[AVIdx] = NULL; return cERR_CONTAINER_FFMPEG_OPEN; } } @@ -1782,15 +1895,17 @@ int32_t container_ffmpeg_init(Context_t *context, PlayFiles_t *playFilesNames) av_log_set_callback(ffmpeg_silen_callback); context->playback->abortRequested = 0; - int32_t res = container_ffmpeg_init_av_context(context, playFilesNames->szFirstFile, 0); + int32_t res = container_ffmpeg_init_av_context(context, playFilesNames->szFirstFile, playFilesNames->iFirstFileSize, \ + playFilesNames->szFirstMoovAtomFile, playFilesNames->iFirstMoovAtomOffset, 0); if (0 != res) { return res; } - if (playFilesNames->szSecondFile) + if (playFilesNames->szSecondFile && playFilesNames->szSecondFile[0] != '\0') { - res = container_ffmpeg_init_av_context(context, playFilesNames->szSecondFile, 1); + res = container_ffmpeg_init_av_context(context, playFilesNames->szSecondFile, playFilesNames->iSecondFileSize, \ + playFilesNames->szSecondMoovAtomFile, playFilesNames->iSecondMoovAtomOffset, 1); } if (0 != res) diff --git a/libeplayer3-arm/include/common.h b/libeplayer3-arm/include/common.h index ae0f4d9..993f5b6 100644 --- a/libeplayer3-arm/include/common.h +++ b/libeplayer3-arm/include/common.h @@ -9,12 +9,16 @@ #include "playback.h" #include -typedef char PlayFilesTab_t[2]; - typedef struct PlayFiles_t { char *szFirstFile; char *szSecondFile; + char *szFirstMoovAtomFile; + char *szSecondMoovAtomFile; + uint64_t iFirstFileSize; + uint64_t iSecondFileSize; + uint64_t iFirstMoovAtomOffset; + uint64_t iSecondMoovAtomOffset; } PlayFiles_t; typedef struct Context_s diff --git a/libeplayer3-arm/main/exteplayer.c b/libeplayer3-arm/main/exteplayer.c index a6e0aea..85ab823 100644 --- a/libeplayer3-arm/main/exteplayer.c +++ b/libeplayer3-arm/main/exteplayer.c @@ -504,14 +504,14 @@ static void UpdateVideoTrack() HandleTracks(g_player->manager->video, (PlaybackCmd_t) - 1, "vc"); } -static int ParseParams(int argc, char *argv[], char *file, char *audioFile, int *pAudioTrackIdx, int *subtitleTrackIdx, uint32_t *linuxDvbBufferSizeMB) +static int ParseParams(int argc, char *argv[], PlayFiles_t *playbackFiles, int *pAudioTrackIdx, int *subtitleTrackIdx, uint32_t *linuxDvbBufferSizeMB) { int ret = 0; int c; //int digit_optind = 0; //int aopt = 0, bopt = 0; //char *copt = 0, *dopt = 0; - while ((c = getopt(argc, argv, "we3dlsrimva:n:x:u:c:h:o:p:P:t:9:0:1:4:f:b:")) != -1) + while ((c = getopt(argc, argv, "we3dlsrimva:n:x:u:c:h:o:p:P:t:9:0:1:4:f:b:F:S:O:")) != -1) { switch (c) { @@ -572,8 +572,13 @@ static int ParseParams(int argc, char *argv[], char *file, char *audioFile, int *subtitleTrackIdx = atoi(optarg); break; case 'x': - strncpy(audioFile, optarg, IPTV_MAX_FILE_PATH - 1); - map_inter_file_path(audioFile); + if (optarg[0] != '\0') + { + playbackFiles->szSecondFile = malloc(IPTV_MAX_FILE_PATH); + strncpy(playbackFiles->szSecondFile, optarg, IPTV_MAX_FILE_PATH - 1); + playbackFiles->szSecondFile[IPTV_MAX_FILE_PATH] = '\0'; + map_inter_file_path(playbackFiles->szSecondFile); + } break; case 'h': ffmpeg_av_dict_set("headers", optarg, 0); @@ -624,6 +629,21 @@ static int ParseParams(int argc, char *argv[], char *file, char *audioFile, int case 'b': *linuxDvbBufferSizeMB = 1024 * 1024 * atoi(optarg); break; + case 'S': + playbackFiles->iFirstFileSize = (uint64_t) strtoull(optarg, (char **)NULL, 10); + break; + case 'O': + playbackFiles->iFirstMoovAtomOffset = (uint64_t) strtoull(optarg, (char **)NULL, 10); + break; + case 'F': + if (optarg[0] != '\0') + { + playbackFiles->szFirstMoovAtomFile = malloc(IPTV_MAX_FILE_PATH); + strncpy(playbackFiles->szFirstMoovAtomFile, optarg, IPTV_MAX_FILE_PATH - 1); + playbackFiles->szFirstMoovAtomFile[IPTV_MAX_FILE_PATH] = '\0'; + map_inter_file_path(playbackFiles->szFirstMoovAtomFile); + } + break; default: printf("?? getopt returned character code 0%o ??\n", c); ret = -1; @@ -633,14 +653,15 @@ static int ParseParams(int argc, char *argv[], char *file, char *audioFile, int if (0 == ret && optind < argc) { ret = 0; - + playbackFiles->szFirstFile = malloc(IPTV_MAX_FILE_PATH); if (NULL == strstr(argv[optind], "://")) { - strcpy(file, "file://"); + strcpy(playbackFiles->szFirstFile, "file://"); } - strcat(file, argv[optind]); - map_inter_file_path(file); - printf("file: [%s]\n", file); + strcat(playbackFiles->szFirstFile, argv[optind]); + playbackFiles->szFirstFile[IPTV_MAX_FILE_PATH] = '\0'; + map_inter_file_path(playbackFiles->szFirstFile); + printf("file: [%s]\n", playbackFiles->szFirstFile); ++optind; } else @@ -654,11 +675,6 @@ int main(int argc, char *argv[]) { pthread_t termThread; int isTermThreadStarted = 0; - char file[IPTV_MAX_FILE_PATH]; - memset(file, '\0', sizeof(file)); - - char audioFile[IPTV_MAX_FILE_PATH]; - memset(audioFile, '\0', sizeof(audioFile)); int audioTrackIdx = -1; int subtitleTrackIdx = -1; @@ -669,9 +685,11 @@ int main(int argc, char *argv[]) memset(argvBuff, '\0', sizeof(argvBuff)); int commandRetVal = -1; /* inform client that we can handle additional commands */ - fprintf(stderr, "{\"EPLAYER3_EXTENDED\":{\"version\":%d}}\n", 45); + fprintf(stderr, "{\"EPLAYER3_EXTENDED\":{\"version\":%d}}\n", 46); - if (0 != ParseParams(argc, argv, file, audioFile, &audioTrackIdx, &subtitleTrackIdx, &linuxDvbBufferSizeMB)) + 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"); @@ -701,6 +719,9 @@ int main(int argc, char *argv[]) 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); } @@ -762,19 +783,13 @@ int main(int argc, char *argv[]) g_player->manager->video->Command(g_player, MANAGER_REGISTER_UPDATED_TRACK_INFO, UpdateVideoTrack); - if (strncmp(file, "rtmp", 4) && strncmp(file, "ffrtmp", 4)) + if (strncmp(playbackFiles.szFirstFile, "rtmp", 4) && strncmp(playbackFiles.szFirstFile, "ffrtmp", 4)) { g_player->playback->noprobe = 1; } - PlayFiles_t playbackFiles = {file, NULL}; - if ('\0' != audioFile[0]) - { - playbackFiles.szSecondFile = audioFile; - } - 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, file, commandRetVal); + 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) diff --git a/libeplayer3-arm/output/writer/mipsel/h264.c b/libeplayer3-arm/output/writer/mipsel/h264.c index 8fe4be9..b5b37da 100644 --- a/libeplayer3-arm/output/writer/mipsel/h264.c +++ b/libeplayer3-arm/output/writer/mipsel/h264.c @@ -396,7 +396,7 @@ static int writeData(WriterAVCallData_t *call) ic = 0; iov[ic++].iov_base = PesHeader; - //if (initialHeader) + if (!avc3) { if (CodecData) { diff --git a/libeplayer3-arm/output/writer/sh4/h264.c b/libeplayer3-arm/output/writer/sh4/h264.c index 39a6afa..3172c5b 100644 --- a/libeplayer3-arm/output/writer/sh4/h264.c +++ b/libeplayer3-arm/output/writer/sh4/h264.c @@ -100,7 +100,7 @@ const uint8_t Head[] = {0, 0, 0, 1}; static int32_t initialHeader = 1; static uint32_t NalLengthBytes = 1; static int avc3 = 0; - +static int sps_pps_in_stream = 0; /* ***************************** */ /* Prototypes */ /* ***************************** */ @@ -263,12 +263,23 @@ static int32_t writeData(void *_call) (call->len > 3) && ((call->data[0] == 0x00 && call->data[1] == 0x00 && call->data[2] == 0x00 && call->data[3] == 0x01) || (call->data[0] == 0xff && call->data[1] == 0xff && call->data[2] == 0xff && call->data[3] == 0xff)))) { + uint32_t i = 0; + uint8_t InsertPrivData = !sps_pps_in_stream; uint32_t PacketLength = 0; - uint32_t FakeStartCode = /*(call->Version << 8) | */PES_VERSION_FAKE_START_CODE; - + uint32_t FakeStartCode = PES_VERSION_FAKE_START_CODE; iov[ic++].iov_base = PesHeader; - initialHeader = 0; - if (initialHeader) + + while (InsertPrivData && i < 36 && (call->len - i) > 5) + { + if ((call->data[i] == 0x00 && call->data[i + 1] == 0x00 && call->data[i + 2] == 0x00 && call->data[i + 3] == 0x01 && (call->data[i + 4] == 0x67 || call->data[i + 4] == 0x68))) + { + InsertPrivData = 0; + sps_pps_in_stream = 1; + } + i += 1; + } + + if (InsertPrivData && call->private_size > 0 /*&& initialHeader*/) // some rtsp streams can update codec data at runtime { initialHeader = 0; iov[ic].iov_base = call->private_data; @@ -299,7 +310,7 @@ static int32_t writeData(void *_call) return 0; } - if (initialHeader) + if (!avc3) { uint8_t *private_data = call->private_data; uint32_t private_size = call->private_size; From de435a395d504e917e8ba1b754ab8442d2482594 Mon Sep 17 00:00:00 2001 From: samsamsam Date: Sat, 7 Apr 2018 17:48:05 +0200 Subject: [PATCH 09/19] Fix wrong playback file name Signed-off-by: max_10 Origin commit data ------------------ Branch: master Commit: https://github.com/neutrino-images/ni-libstb-hal/commit/5a885943582849302692d6c08df5c6d8cca65cc2 Author: samsamsam Date: 2018-04-07 (Sat, 07 Apr 2018) ------------------ This commit was generated by Migit --- libeplayer3-arm/main/exteplayer.c | 5 ++++- libeplayer3-arm/output/linuxdvb_buffering.c | 6 ++++++ 2 files changed, 10 insertions(+), 1 deletion(-) diff --git a/libeplayer3-arm/main/exteplayer.c b/libeplayer3-arm/main/exteplayer.c index 85ab823..b2065de 100644 --- a/libeplayer3-arm/main/exteplayer.c +++ b/libeplayer3-arm/main/exteplayer.c @@ -575,6 +575,7 @@ static int ParseParams(int argc, char *argv[], PlayFiles_t *playbackFiles, int * if (optarg[0] != '\0') { playbackFiles->szSecondFile = malloc(IPTV_MAX_FILE_PATH); + playbackFiles->szSecondFile[0] = '\0'; strncpy(playbackFiles->szSecondFile, optarg, IPTV_MAX_FILE_PATH - 1); playbackFiles->szSecondFile[IPTV_MAX_FILE_PATH] = '\0'; map_inter_file_path(playbackFiles->szSecondFile); @@ -639,6 +640,7 @@ static int ParseParams(int argc, char *argv[], PlayFiles_t *playbackFiles, int * if (optarg[0] != '\0') { playbackFiles->szFirstMoovAtomFile = malloc(IPTV_MAX_FILE_PATH); + playbackFiles->szFirstMoovAtomFile[0] = '\0'; strncpy(playbackFiles->szFirstMoovAtomFile, optarg, IPTV_MAX_FILE_PATH - 1); playbackFiles->szFirstMoovAtomFile[IPTV_MAX_FILE_PATH] = '\0'; map_inter_file_path(playbackFiles->szFirstMoovAtomFile); @@ -654,6 +656,7 @@ static int ParseParams(int argc, char *argv[], PlayFiles_t *playbackFiles, int * { ret = 0; playbackFiles->szFirstFile = malloc(IPTV_MAX_FILE_PATH); + playbackFiles->szFirstFile[0] = '\0'; if (NULL == strstr(argv[optind], "://")) { strcpy(playbackFiles->szFirstFile, "file://"); @@ -685,7 +688,7 @@ int main(int argc, char *argv[]) memset(argvBuff, '\0', sizeof(argvBuff)); int commandRetVal = -1; /* inform client that we can handle additional commands */ - fprintf(stderr, "{\"EPLAYER3_EXTENDED\":{\"version\":%d}}\n", 46); + fprintf(stderr, "{\"EPLAYER3_EXTENDED\":{\"version\":%d}}\n", 47); PlayFiles_t playbackFiles; memset(&playbackFiles, 0x00, sizeof(playbackFiles)); diff --git a/libeplayer3-arm/output/linuxdvb_buffering.c b/libeplayer3-arm/output/linuxdvb_buffering.c index 2fc472f..f66b471 100644 --- a/libeplayer3-arm/output/linuxdvb_buffering.c +++ b/libeplayer3-arm/output/linuxdvb_buffering.c @@ -33,6 +33,7 @@ #include #include #include +#include #include "common.h" #include "misc.h" @@ -309,8 +310,13 @@ int32_t LinuxDvbBuffClose(Context_t *context __attribute__((unused))) pthread_cond_signal(&bufferingdDataAddedCond); /* wait for thread end */ +#if 0 + /* This code couse symbol versioning of clock_gettime@GLIBC_2.17 */ clock_gettime(CLOCK_REALTIME, &max_wait); max_wait.tv_sec += 1; +#else + max_wait.tv_sec = time(NULL) + 2; +#endif pthread_cond_timedwait(&bufferingExitCond, &bufferingMtx, &max_wait); pthread_mutex_unlock(&bufferingMtx); From f9c295808549a6aae36dbf0fa85f88cd74739e23 Mon Sep 17 00:00:00 2001 From: max_10 Date: Wed, 11 Apr 2018 23:02:02 +0200 Subject: [PATCH 10/19] bugfix-last-commits Origin commit data ------------------ Branch: master Commit: https://github.com/neutrino-images/ni-libstb-hal/commit/d438aa31d385130cce5332c55986c587927786f7 Author: max_10 Date: 2018-04-11 (Wed, 11 Apr 2018) ------------------ No further description and justification available within origin commit message! ------------------ This commit was generated by Migit --- libarmbox/playback_libeplayer3.cpp | 2 +- libeplayer3-arm/container/container_ffmpeg.c | 21 ++++++++++++-------- 2 files changed, 14 insertions(+), 9 deletions(-) diff --git a/libarmbox/playback_libeplayer3.cpp b/libarmbox/playback_libeplayer3.cpp index c5acdba..83a75ae 100644 --- a/libarmbox/playback_libeplayer3.cpp +++ b/libarmbox/playback_libeplayer3.cpp @@ -117,7 +117,7 @@ bool cPlayback::Start(char *filename, int vpid, int vtype, int apid, int ac3, in } else isHTTP = true; - PlayFiles_t playbackFiles = { (char *) file.c_str(), NULL}; + PlayFiles_t playbackFiles = { (char *) file.c_str(), NULL, NULL, NULL, 0, 0, 0, 0}; if (player->playback->Command(player, PLAYBACK_OPEN, &playbackFiles) == 0) { if (pm == PLAYMODE_TS) diff --git a/libeplayer3-arm/container/container_ffmpeg.c b/libeplayer3-arm/container/container_ffmpeg.c index a8b4f46..7cb9fab 100644 --- a/libeplayer3-arm/container/container_ffmpeg.c +++ b/libeplayer3-arm/container/container_ffmpeg.c @@ -1378,14 +1378,14 @@ int SAM_ReadFunc(void *ptr, uint8_t *buffer, int lSize) } else { - if (io->iOffset < io->iMoovAtomOffset) + if ((uint64_t)io->iOffset < io->iMoovAtomOffset) { ret = (int)fread((void *) buffer, (size_t) 1, (size_t) lSize, io->pFile); buffer += ret; lSize -= ret; } - if (io->iOffset + ret >= io->iMoovAtomOffset) + if ((uint64_t)io->iOffset + ret >= io->iMoovAtomOffset) { if (ret) { @@ -1440,12 +1440,12 @@ int64_t SAM_SeekFunc(void *ptr, int64_t pos, int whence) return -1; } - if (ret >= 0 && ret <= io->iFileSize) + if (ret >= 0 && (uint64_t)ret <= io->iFileSize) { - if (ret < io->iMoovAtomOffset) + if ((uint64_t)ret < io->iMoovAtomOffset) { if (!fseeko(io->pFile, (off_t)ret, SEEK_SET)) - io->iOffset = ret; + io->iOffset = (uint64_t)ret; else ret = -1; } @@ -1520,7 +1520,7 @@ int32_t container_ffmpeg_init_av_context(Context_t *context, char *filename, uin { AVIOContext *avio_ctx = NULL; custom_io_tab[AVIdx] = malloc(sizeof(CustomIOCtx_t)); - sizeof(custom_io_tab[AVIdx], 0x00, sizeof(CustomIOCtx_t)); + memset(custom_io_tab[AVIdx], 0x00, sizeof(CustomIOCtx_t)); custom_io_tab[AVIdx]->szFile = filename; custom_io_tab[AVIdx]->iFileSize = fileSize; @@ -2690,7 +2690,12 @@ static int32_t container_ffmpeg_stop(Context_t *context) * avformat_close_input do not expect custom io, so it try * to release incorrectly */ - fclose(avContextTab[i]->pb->opaque); + CustomIOCtx_t *io = (CustomIOCtx_t *)avContextTab[i]->pb->opaque; + if (io->pFile) + fclose(io->pFile); + if (io->pMoovFile) + fclose(io->pMoovFile); + free(custom_io_tab[i]); av_freep(&(avContextTab[i]->pb->buffer)); av_freep(&(avContextTab[i]->pb)); use_custom_io[i] = 0; @@ -3295,4 +3300,4 @@ Container_t FFMPEGContainer = "FFMPEG", &Command, FFMPEG_Capabilities -}; \ No newline at end of file +}; From 28c7fcb2e9d89e8cb8c5fa06a8f7a696caeb7c04 Mon Sep 17 00:00:00 2001 From: samsamsam Date: Sat, 14 Apr 2018 19:41:08 +0200 Subject: [PATCH 11/19] Add buffering for SH4 Signed-off-by: max_10 Origin commit data ------------------ Branch: master Commit: https://github.com/neutrino-images/ni-libstb-hal/commit/a7da1fd3bf3fdf65381ab76e590e726627f630a1 Author: samsamsam Date: 2018-04-14 (Sat, 14 Apr 2018) ------------------ This commit was generated by Migit --- libeplayer3-arm/Makefile.am | 1 + libeplayer3-arm/container/container_ffmpeg.c | 10 ++- libeplayer3-arm/include/output.h | 1 + libeplayer3-arm/include/writer.h | 9 ++- libeplayer3-arm/main/exteplayer.c | 3 +- libeplayer3-arm/output/linuxdvb_buffering.c | 10 ++- libeplayer3-arm/output/linuxdvb_mipsel.c | 13 +++- libeplayer3-arm/output/linuxdvb_sh4.c | 54 +++++++++++++- libeplayer3-arm/output/output.c | 19 +++++ libeplayer3-arm/output/writer/common/writer.c | 74 +++++++++++++++++++ libeplayer3-arm/output/writer/mipsel/aac.c | 4 +- libeplayer3-arm/output/writer/mipsel/writer.c | 13 +--- libeplayer3-arm/output/writer/sh4/aac.c | 10 +-- libeplayer3-arm/output/writer/sh4/ac3.c | 2 +- libeplayer3-arm/output/writer/sh4/divx.c | 2 +- libeplayer3-arm/output/writer/sh4/divx2.c | 2 +- libeplayer3-arm/output/writer/sh4/dts.c | 2 +- libeplayer3-arm/output/writer/sh4/h263.c | 2 +- libeplayer3-arm/output/writer/sh4/h264.c | 32 +++----- libeplayer3-arm/output/writer/sh4/mp3.c | 2 +- libeplayer3-arm/output/writer/sh4/mpeg2.c | 2 +- libeplayer3-arm/output/writer/sh4/pcm.c | 2 +- libeplayer3-arm/output/writer/sh4/vc1.c | 6 +- libeplayer3-arm/output/writer/sh4/wma.c | 4 +- libeplayer3-arm/output/writer/sh4/writer.c | 49 ++++++++++++ libeplayer3-arm/playback/playback.c | 3 +- 26 files changed, 261 insertions(+), 70 deletions(-) create mode 100644 libeplayer3-arm/output/writer/common/writer.c diff --git a/libeplayer3-arm/Makefile.am b/libeplayer3-arm/Makefile.am index b77dbf9..7ba03f2 100644 --- a/libeplayer3-arm/Makefile.am +++ b/libeplayer3-arm/Makefile.am @@ -24,6 +24,7 @@ libeplayer3_arm_la_SOURCES = \ output/output.c \ output/writer/common/pes.c \ output/writer/common/misc.c \ + output/writer/common/writer.c \ output/writer/mipsel/writer.c \ output/writer/mipsel/aac.c \ output/writer/mipsel/ac3.c \ diff --git a/libeplayer3-arm/container/container_ffmpeg.c b/libeplayer3-arm/container/container_ffmpeg.c index 7cb9fab..5f84216 100644 --- a/libeplayer3-arm/container/container_ffmpeg.c +++ b/libeplayer3-arm/container/container_ffmpeg.c @@ -585,10 +585,16 @@ static void FFMPEGThread(Context_t *context) ffmpeg_printf(10, "\n"); while (context->playback->isCreationPhase) { - ffmpeg_err("Thread waiting for end of init phase...\n"); + ffmpeg_printf(10, "Thread waiting for end of init phase...\n"); usleep(1000); } ffmpeg_printf(10, "Running!\n"); + +#ifdef __sh__ + uint32_t bufferSize = 0; + context->output->Command(context, OUTPUT_GET_BUFFER_SIZE, &bufferSize); + ffmpeg_printf(10, "bufferSize [%u]\n", bufferSize); +#endif int8_t isWaitingForFinish = 0; while (context && context->playback && context->playback->isPlaying) @@ -602,7 +608,7 @@ static void FFMPEGThread(Context_t *context) */ #ifdef __sh__ //IF MOVIE IS PAUSED, WAIT - if (context->playback->isPaused) + if (0 == bufferSize && context->playback->isPaused) { ffmpeg_printf(20, "paused\n"); reset_finish_timeout(); diff --git a/libeplayer3-arm/include/output.h b/libeplayer3-arm/include/output.h index 533e60a..5dad251 100644 --- a/libeplayer3-arm/include/output.h +++ b/libeplayer3-arm/include/output.h @@ -29,6 +29,7 @@ typedef enum OUTPUT_GET_FRAME_COUNT, OUTPUT_GET_PROGRESSIVE, OUTPUT_SET_BUFFER_SIZE, + OUTPUT_GET_BUFFER_SIZE, } OutputCmd_t; typedef struct diff --git a/libeplayer3-arm/include/writer.h b/libeplayer3-arm/include/writer.h index b72636a..cd535d9 100644 --- a/libeplayer3-arm/include/writer.h +++ b/libeplayer3-arm/include/writer.h @@ -23,7 +23,7 @@ typedef struct unsigned int Height; unsigned char Version; unsigned int InfoFlags; - ssize_t (* WriteV) (int, const struct iovec *, size_t); + ssize_t (* WriteV) (int, const struct iovec *, int); } WriterAVCallData_t; @@ -88,8 +88,9 @@ Writer_t *getWriter(char *encoding); Writer_t *getDefaultVideoWriter(); Writer_t *getDefaultAudioWriter(); -ssize_t write_with_retry(int fd, const void *buf, size_t size); -ssize_t writev_with_retry(int fd, const struct iovec *iov, size_t ic); +ssize_t write_with_retry(int fd, const void *buf, int size); +ssize_t writev_with_retry(int fd, const struct iovec *iov, int ic); -ssize_t WriteWithRetry(Context_t *context, int pipefd, int fd, const void *buf, size_t size); +ssize_t WriteWithRetry(Context_t *context, int pipefd, int fd, const void *buf, int size); +void FlusPipe(int pipefd); #endif diff --git a/libeplayer3-arm/main/exteplayer.c b/libeplayer3-arm/main/exteplayer.c index b2065de..7538799 100644 --- a/libeplayer3-arm/main/exteplayer.c +++ b/libeplayer3-arm/main/exteplayer.c @@ -688,7 +688,7 @@ int main(int argc, char *argv[]) memset(argvBuff, '\0', sizeof(argvBuff)); int commandRetVal = -1; /* inform client that we can handle additional commands */ - fprintf(stderr, "{\"EPLAYER3_EXTENDED\":{\"version\":%d}}\n", 47); + fprintf(stderr, "{\"EPLAYER3_EXTENDED\":{\"version\":%d}}\n", 49); PlayFiles_t playbackFiles; memset(&playbackFiles, 0x00, sizeof(playbackFiles)); @@ -784,7 +784,6 @@ int main(int argc, char *argv[]) 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)) { diff --git a/libeplayer3-arm/output/linuxdvb_buffering.c b/libeplayer3-arm/output/linuxdvb_buffering.c index f66b471..6633282 100644 --- a/libeplayer3-arm/output/linuxdvb_buffering.c +++ b/libeplayer3-arm/output/linuxdvb_buffering.c @@ -224,18 +224,24 @@ static void LinuxDvbBuffThread(Context_t *context) buff_printf(20, "EXIT\n"); hasBufferingThreadStarted = false; + close(g_pfd[0]); close(g_pfd[1]); g_pfd[0] = -1; g_pfd[1] = -1; } -int32_t WriteSetBufferingSize(const uint32_t bufferSize) +int32_t LinuxDvbBuffSetSize(const uint32_t bufferSize) { maxBufferingDataSize = bufferSize; return cERR_LINUX_DVB_BUFFERING_NO_ERROR; } +uint32_t LinuxDvbBuffGetSize() +{ + return maxBufferingDataSize; +} + int32_t LinuxDvbBuffOpen(Context_t *context, char *type, int outfd) { int32_t error = 0; @@ -380,7 +386,7 @@ int32_t LinuxDvbBuffResume(Context_t *context __attribute__((unused))) return 0; } -ssize_t BufferingWriteV(int fd, const struct iovec *iov, size_t ic) +ssize_t BufferingWriteV(int fd, const struct iovec *iov, int ic) { OutputType_t dataType = OUTPUT_UNK; BufferingNode_t *nodePtr = NULL; diff --git a/libeplayer3-arm/output/linuxdvb_mipsel.c b/libeplayer3-arm/output/linuxdvb_mipsel.c index f4acac6..58afc9b 100644 --- a/libeplayer3-arm/output/linuxdvb_mipsel.c +++ b/libeplayer3-arm/output/linuxdvb_mipsel.c @@ -104,8 +104,9 @@ int32_t LinuxDvbBuffClose(Context_t *context); int32_t LinuxDvbBuffFlush(Context_t *context); int32_t LinuxDvbBuffResume(Context_t *context); -ssize_t BufferingWriteV(int fd, const struct iovec *iov, size_t ic); -int32_t WriteSetBufferingSize(const uint32_t bufferSize); +ssize_t BufferingWriteV(int fd, const struct iovec *iov, int ic); +int32_t LinuxDvbBuffSetSize(const uint32_t bufferSize); +uint32_t LinuxDvbBuffGetSize(); int LinuxDvbStop(Context_t *context, char *type); @@ -1085,12 +1086,18 @@ static int Command(Context_t *context, OutputCmd_t command, void *argument) ret = cERR_LINUXDVB_NO_ERROR; if (bufferSize > 0) { - WriteSetBufferingSize(bufferSize); + LinuxDvbBuffSetSize(bufferSize); isBufferedOutput = true; } } break; } + case OUTPUT_GET_BUFFER_SIZE: + { + ret = cERR_LINUXDVB_NO_ERROR; + *((uint32_t*)argument) = LinuxDvbBuffGetSize(); + break; + } default: linuxdvb_err("ContainerCmd %d not supported!\n", command); ret = cERR_LINUXDVB_ERROR; diff --git a/libeplayer3-arm/output/linuxdvb_sh4.c b/libeplayer3-arm/output/linuxdvb_sh4.c index 1eb6d23..be04aa7 100644 --- a/libeplayer3-arm/output/linuxdvb_sh4.c +++ b/libeplayer3-arm/output/linuxdvb_sh4.c @@ -37,6 +37,7 @@ #include #include #include +#include #include "bcm_ioctls.h" @@ -90,12 +91,21 @@ struct DVBApiVideoInfo_s static struct DVBApiVideoInfo_s videoInfo = {-1, -1, -1, -1, -1}; unsigned long long int sCURRENT_PTS = 0; +bool isBufferedOutput = false; pthread_mutex_t LinuxDVBmutex; /* ***************************** */ /* Prototypes */ /* ***************************** */ +int32_t LinuxDvbBuffOpen(Context_t *context, char *type, int outfd); +int32_t LinuxDvbBuffClose(Context_t *context); +int32_t LinuxDvbBuffFlush(Context_t *context); +int32_t LinuxDvbBuffResume(Context_t *context); + +ssize_t BufferingWriteV(int fd, const struct iovec *iov, int ic); +int32_t LinuxDvbBuffSetSize(const uint32_t bufferSize); +uint32_t LinuxDvbBuffGetSize(); int LinuxDvbStop(Context_t *context, char *type); @@ -163,11 +173,12 @@ int LinuxDvbOpen(Context_t *context __attribute__((unused)), char *type) linuxdvb_err("VIDEO_SET_SPEED: %s\n", strerror(errno)); } + if (isBufferedOutput) + LinuxDvbBuffOpen(context, type, videofd); } if (audio && audiofd < 0) { audiofd = open(AUDIODEV, O_RDWR); - if (audiofd < 0) { linuxdvb_err("failed to open %s - errno %d\n", AUDIODEV, errno); @@ -195,15 +206,18 @@ int LinuxDvbOpen(Context_t *context __attribute__((unused)), char *type) linuxdvb_err("ioctl failed with errno %d\n", errno); linuxdvb_err("AUDIO_SET_STREAMTYPE: %s\n", strerror(errno)); } + + if (isBufferedOutput) + LinuxDvbBuffOpen(context, type, audiofd); } return cERR_LINUXDVB_NO_ERROR; } -int LinuxDvbClose(Context_t *context, char *type) +int LinuxDvbClose(Context_t *context, char *type) { - unsigned char video = !strcmp("video", type); - unsigned char audio = !strcmp("audio", type); + uint8_t video = !strcmp("video", type); + uint8_t audio = !strcmp("audio", type); linuxdvb_printf(10, "v%d a%d\n", video, audio); @@ -215,6 +229,9 @@ int LinuxDvbClose(Context_t *context, char *type) getLinuxDVBMutex(FILENAME, __FUNCTION__, __LINE__); + if (isBufferedOutput) + LinuxDvbBuffClose(context); + if (video && videofd != -1) { close(videofd); @@ -438,6 +455,9 @@ int LinuxDvbContinue(Context_t *context __attribute__((unused)), char *type) ret = cERR_LINUXDVB_ERROR; } } + + if (isBufferedOutput) + LinuxDvbBuffResume(context); linuxdvb_printf(10, "exiting\n"); @@ -1060,6 +1080,7 @@ static int Write(void *_context, void *_out) call.Height = out->height; call.InfoFlags = out->infoFlags; call.Version = 0; // is unsingned char + call.WriteV = isBufferedOutput ? BufferingWriteV : writev; if (writer->writeData) { @@ -1109,6 +1130,7 @@ static int Write(void *_context, void *_out) call.FrameScale = out->timeScale; call.InfoFlags = out->infoFlags; call.Version = 0; /* -1; unsigned char cannot be negative */ + call.WriteV = isBufferedOutput ? BufferingWriteV : writev; if (writer->writeData) { @@ -1166,6 +1188,9 @@ static int reset(Context_t *context) } free(Encoding); + + if (isBufferedOutput) + LinuxDvbBuffFlush(context); return ret; } @@ -1283,6 +1308,27 @@ static int Command(void *_context, OutputCmd_t command, void *argument) *((int *)argument) = videoInfo.progressive; break; } + case OUTPUT_SET_BUFFER_SIZE: + { + ret = cERR_LINUXDVB_ERROR; + if (!isBufferedOutput) + { + uint32_t bufferSize = *((uint32_t*)argument); + ret = cERR_LINUXDVB_NO_ERROR; + if (bufferSize > 0) + { + LinuxDvbBuffSetSize(bufferSize); + isBufferedOutput = true; + } + } + break; + } + case OUTPUT_GET_BUFFER_SIZE: + { + ret = cERR_LINUXDVB_NO_ERROR; + *((uint32_t*)argument) = LinuxDvbBuffGetSize(); + break; + } default: linuxdvb_err("ContainerCmd %d not supported!\n", command); ret = cERR_LINUXDVB_ERROR; diff --git a/libeplayer3-arm/output/output.c b/libeplayer3-arm/output/output.c index d63f30c..60760e8 100644 --- a/libeplayer3-arm/output/output.c +++ b/libeplayer3-arm/output/output.c @@ -564,6 +564,25 @@ static int Command(Context_t *context, OutputCmd_t command, void *argument) } break; } + case OUTPUT_GET_BUFFER_SIZE: + { + if (context && context->playback) + { + if (context->output->video) + { + return context->output->video->Command(context, OUTPUT_GET_BUFFER_SIZE, argument); + } + else if (context->output->audio) + { + return context->output->audio->Command(context, OUTPUT_GET_BUFFER_SIZE, argument); + } + } + else + { + ret = cERR_OUTPUT_INTERNAL_ERROR; + } + break; + } default: output_err("%s::%s OutputCmd %d not supported!\n", __FILE__, __FUNCTION__, command); ret = cERR_OUTPUT_INTERNAL_ERROR; diff --git a/libeplayer3-arm/output/writer/common/writer.c b/libeplayer3-arm/output/writer/common/writer.c new file mode 100644 index 0000000..748bf36 --- /dev/null +++ b/libeplayer3-arm/output/writer/common/writer.c @@ -0,0 +1,74 @@ +/* + * linuxdvb output/writer handling. + * + * konfetti 2010 + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + */ + +/* ***************************** */ +/* Includes */ +/* ***************************** */ +#include +#include +#include + +#include "misc.h" +#include "writer.h" +#include "common.h" + +/* ***************************** */ +/* Makros/Constants */ +/* ***************************** */ + +#define WRITER_DEBUG + +#ifdef WRITER_DEBUG + +static short debug_level = 0; + +#define writer_printf(level, x...) do { \ +if (debug_level >= level) printf(x); } while (0) +#else +#define writer_printf(level, x...) +#endif + +#ifndef WRITER_SILENT +#define writer_err(x...) do { printf(x); } while (0) +#else +#define writer_err(x...) +#endif + +/* ***************************** */ +/* Types */ +/* ***************************** */ + +/* ***************************** */ +/* Varaibles */ +/* ***************************** */ + +/* ***************************** */ +/* Prototypes */ +/* ***************************** */ + +/* ***************************** */ +/* Functions */ +/* ***************************** */ +void FlusPipe(int pipefd) +{ + char tmp; + while(1 == read(pipefd, &tmp, 1)); +} diff --git a/libeplayer3-arm/output/writer/mipsel/aac.c b/libeplayer3-arm/output/writer/mipsel/aac.c index 4ec234b..906e4fa 100644 --- a/libeplayer3-arm/output/writer/mipsel/aac.c +++ b/libeplayer3-arm/output/writer/mipsel/aac.c @@ -323,8 +323,8 @@ static int writeDataLATM(WriterAVCallData_t *call) int ret = latmenc_decode_extradata(pLATMCtx, call->private_data, call->private_size); if (ret) { - printf("%02x %02x %02x %02x %02x %02x %02x %02x\n", (int)call->data[0], (int)call->data[1], (int)call->data[2], (int)call->data[3], \ - (int)call->data[4], (int)call->data[5], (int)call->data[6], (int)call->data[7]); + //printf("%02x %02x %02x %02x %02x %02x %02x %02x\n", (int)call->data[0], (int)call->data[1], (int)call->data[2], (int)call->data[3], \ + // (int)call->data[4], (int)call->data[5], (int)call->data[6], (int)call->data[7]); aac_err("latm_decode_extradata failed. ignoring...\n"); return 0; } diff --git a/libeplayer3-arm/output/writer/mipsel/writer.c b/libeplayer3-arm/output/writer/mipsel/writer.c index 209c75c..33a83ab 100644 --- a/libeplayer3-arm/output/writer/mipsel/writer.c +++ b/libeplayer3-arm/output/writer/mipsel/writer.c @@ -101,13 +101,7 @@ static Writer_t *AvailableWriter[] = /* Functions */ /* ***************************** */ -static void FlusPipe(int pipefd) -{ - char tmp; - while(1 == read(pipefd, &tmp, 1)); -} - -ssize_t WriteWithRetry(Context_t *context, int pipefd, int fd, const void *buf, size_t size) +ssize_t WriteWithRetry(Context_t *context, int pipefd, int fd, const void *buf, int size) { fd_set rfds; fd_set wfds; @@ -194,14 +188,13 @@ ssize_t WriteWithRetry(Context_t *context, int pipefd, int fd, const void *buf, return 0; } -ssize_t write_with_retry(int fd, const void *buf, size_t size) +ssize_t write_with_retry(int fd, const void *buf, int 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) @@ -239,7 +232,7 @@ ssize_t write_with_retry(int fd, const void *buf, size_t size) return 0; } -ssize_t writev_with_retry(int fd, const struct iovec *iov, size_t ic) +ssize_t writev_with_retry(int fd, const struct iovec *iov, int ic) { ssize_t len = 0; uint32_t i = 0; diff --git a/libeplayer3-arm/output/writer/sh4/aac.c b/libeplayer3-arm/output/writer/sh4/aac.c index 28b06b8..62978e5 100644 --- a/libeplayer3-arm/output/writer/sh4/aac.c +++ b/libeplayer3-arm/output/writer/sh4/aac.c @@ -211,7 +211,7 @@ static int _writeData(void *_call, int type) iov[0].iov_len = HeaderLength; iov[1].iov_base = call->data; iov[1].iov_len = call->len; - return writev(call->fd, iov, 2); + return call->WriteV(call->fd, iov, 2); } static int writeDataADTS(void *_call) @@ -279,7 +279,7 @@ static int writeDataADTS(void *_call) iov[1].iov_base = call->data; iov[1].iov_len = call->len; - return writev(call->fd, iov, 2); + return call->WriteV(call->fd, iov, 2); } static int writeDataLATM(void *_call) @@ -325,8 +325,8 @@ static int writeDataLATM(void *_call) int ret = latmenc_decode_extradata(pLATMCtx, call->private_data, call->private_size); if (ret) { - printf("%02x %02x %02x %02x %02x %02x %02x %02x\n", (int)call->data[0], (int)call->data[1], (int)call->data[2], (int)call->data[3], \ - (int)call->data[4], (int)call->data[5], (int)call->data[6], (int)call->data[7]); + //printf("%02x %02x %02x %02x %02x %02x %02x %02x\n", (int)call->data[0], (int)call->data[1], (int)call->data[2], (int)call->data[3], \ + // (int)call->data[4], (int)call->data[5], (int)call->data[6], (int)call->data[7]); aac_err("latm_decode_extradata failed. ignoring...\n"); return 0; } @@ -349,7 +349,7 @@ static int writeDataLATM(void *_call) iov[2].iov_base = pLATMCtx->buffer; iov[2].iov_len = pLATMCtx->len; - return writev(call->fd, iov, 3); + return call->WriteV(call->fd, iov, 3); } /* ***************************** */ diff --git a/libeplayer3-arm/output/writer/sh4/ac3.c b/libeplayer3-arm/output/writer/sh4/ac3.c index 3ff3df0..cba2445 100644 --- a/libeplayer3-arm/output/writer/sh4/ac3.c +++ b/libeplayer3-arm/output/writer/sh4/ac3.c @@ -130,7 +130,7 @@ static int writeData(void *_call) iov[1].iov_base = call->data; iov[1].iov_len = call->len; - return writev(call->fd, iov, 2); + return call->WriteV(call->fd, iov, 2); } /* ***************************** */ diff --git a/libeplayer3-arm/output/writer/sh4/divx.c b/libeplayer3-arm/output/writer/sh4/divx.c index e18538d..c1b97c7 100644 --- a/libeplayer3-arm/output/writer/sh4/divx.c +++ b/libeplayer3-arm/output/writer/sh4/divx.c @@ -179,7 +179,7 @@ static int writeData(void *_call) iov[ic].iov_base = call->data; iov[ic++].iov_len = call->len; - int len = writev(call->fd, iov, ic); + int len = call->WriteV(call->fd, iov, ic); divx_printf(10, "xvid_Write < len=%d\n", len); diff --git a/libeplayer3-arm/output/writer/sh4/divx2.c b/libeplayer3-arm/output/writer/sh4/divx2.c index c7b8654..fc80917 100644 --- a/libeplayer3-arm/output/writer/sh4/divx2.c +++ b/libeplayer3-arm/output/writer/sh4/divx2.c @@ -209,7 +209,7 @@ static int writeData(void *_call) iov[ic].iov_base = call->data; iov[ic++].iov_len = call->len; - int len = writev(call->fd, iov, ic); + int len = call->WriteV(call->fd, iov, ic); divx_printf(10, "xvid_Write < len=%d\n", len); diff --git a/libeplayer3-arm/output/writer/sh4/dts.c b/libeplayer3-arm/output/writer/sh4/dts.c index fb2a21f..f6cc94c 100644 --- a/libeplayer3-arm/output/writer/sh4/dts.c +++ b/libeplayer3-arm/output/writer/sh4/dts.c @@ -161,7 +161,7 @@ static int32_t writeData(void *_call) iov[1].iov_base = Data; iov[1].iov_len = Size; - int32_t len = writev(call->fd, iov, 2); + int32_t len = call->WriteV(call->fd, iov, 2); dts_printf(10, "< len %d\n", len); return len; } diff --git a/libeplayer3-arm/output/writer/sh4/h263.c b/libeplayer3-arm/output/writer/sh4/h263.c index 466d720..c29309b 100644 --- a/libeplayer3-arm/output/writer/sh4/h263.c +++ b/libeplayer3-arm/output/writer/sh4/h263.c @@ -141,7 +141,7 @@ static int writeData(void *_call) iov[0].iov_len = HeaderLength; iov[1].iov_base = call->data; iov[1].iov_len = call->len; - len = writev(call->fd, iov, 2); + len = call->WriteV(call->fd, iov, 2); h263_printf(10, "< len %d\n", len); return len; diff --git a/libeplayer3-arm/output/writer/sh4/h264.c b/libeplayer3-arm/output/writer/sh4/h264.c index 3172c5b..b749139 100644 --- a/libeplayer3-arm/output/writer/sh4/h264.c +++ b/libeplayer3-arm/output/writer/sh4/h264.c @@ -100,7 +100,6 @@ const uint8_t Head[] = {0, 0, 0, 1}; static int32_t initialHeader = 1; static uint32_t NalLengthBytes = 1; static int avc3 = 0; -static int sps_pps_in_stream = 0; /* ***************************** */ /* Prototypes */ /* ***************************** */ @@ -263,23 +262,12 @@ static int32_t writeData(void *_call) (call->len > 3) && ((call->data[0] == 0x00 && call->data[1] == 0x00 && call->data[2] == 0x00 && call->data[3] == 0x01) || (call->data[0] == 0xff && call->data[1] == 0xff && call->data[2] == 0xff && call->data[3] == 0xff)))) { - uint32_t i = 0; - uint8_t InsertPrivData = !sps_pps_in_stream; uint32_t PacketLength = 0; - uint32_t FakeStartCode = PES_VERSION_FAKE_START_CODE; + uint32_t FakeStartCode = /*(call->Version << 8) | */PES_VERSION_FAKE_START_CODE; + iov[ic++].iov_base = PesHeader; - - while (InsertPrivData && i < 36 && (call->len - i) > 5) - { - if ((call->data[i] == 0x00 && call->data[i + 1] == 0x00 && call->data[i + 2] == 0x00 && call->data[i + 3] == 0x01 && (call->data[i + 4] == 0x67 || call->data[i + 4] == 0x68))) - { - InsertPrivData = 0; - sps_pps_in_stream = 1; - } - i += 1; - } - - if (InsertPrivData && call->private_size > 0 /*&& initialHeader*/) // some rtsp streams can update codec data at runtime + initialHeader = 0; + if (initialHeader) { initialHeader = 0; iov[ic].iov_base = call->private_data; @@ -301,7 +289,7 @@ static int32_t writeData(void *_call) iov[ic++].iov_len = 1; iov[0].iov_len = InsertPesHeader(PesHeader, -1, MPEG_VIDEO_PES_START_CODE, VideoPts, FakeStartCode); - int ret = writev(call->fd, iov, ic); + int ret = call->WriteV(call->fd, iov, ic); return ret; } else if (!call->private_data || call->private_size < 7 || 1 != call->private_data[0]) @@ -310,7 +298,7 @@ static int32_t writeData(void *_call) return 0; } - if (!avc3) + if (initialHeader) { uint8_t *private_data = call->private_data; uint32_t private_size = call->private_size; @@ -368,7 +356,7 @@ static int32_t writeData(void *_call) iov[ic++].iov_len = InsertPesHeader(PesHeader, ParametersLength, MPEG_VIDEO_PES_START_CODE, INVALID_PTS_VALUE, 0); iov[ic].iov_base = HeaderData; iov[ic++].iov_len = ParametersLength; - len = writev(call->fd, iov, ic); + len = call->WriteV(call->fd, iov, ic); if (len < 0) { return len; @@ -424,7 +412,7 @@ static int32_t writeData(void *_call) } iov[0].iov_len = InsertPesHeader(PesHeader, InitialHeaderLength, MPEG_VIDEO_PES_START_CODE, INVALID_PTS_VALUE, 0); - ssize_t l = writev(call->fd, iov, ic); + ssize_t l = call->WriteV(call->fd, iov, ic); if (private_data != call->private_data) { @@ -498,7 +486,7 @@ static int32_t writeData(void *_call) h264_printf(20, " pts=%llu\n", VideoPts); iov[0].iov_len = InsertPesHeader(PesHeader, NalLength, MPEG_VIDEO_PES_START_CODE, VideoPts, 0); - ssize_t l = writev(call->fd, iov, ic); + ssize_t l = call->WriteV(call->fd, iov, ic); if (l < 0) return l; len += l; @@ -537,4 +525,4 @@ struct Writer_s WriterVideoH264 = &reset, &writeData, &caps -}; +}; \ No newline at end of file diff --git a/libeplayer3-arm/output/writer/sh4/mp3.c b/libeplayer3-arm/output/writer/sh4/mp3.c index 7ed7d02..72b0aa5 100644 --- a/libeplayer3-arm/output/writer/sh4/mp3.c +++ b/libeplayer3-arm/output/writer/sh4/mp3.c @@ -128,7 +128,7 @@ static int writeData(void *_call) iov[1].iov_base = call->data; iov[1].iov_len = call->len; - int len = writev(call->fd, iov, 2); + int len = call->WriteV(call->fd, iov, 2); mp3_printf(10, "mp3_Write-< len=%d\n", len); return len; diff --git a/libeplayer3-arm/output/writer/sh4/mpeg2.c b/libeplayer3-arm/output/writer/sh4/mpeg2.c index cb1f928..5dae349 100644 --- a/libeplayer3-arm/output/writer/sh4/mpeg2.c +++ b/libeplayer3-arm/output/writer/sh4/mpeg2.c @@ -140,7 +140,7 @@ static int writeData(void *_call) iov[1].iov_base = call->data + Position; iov[1].iov_len = PacketLength; - ssize_t l = writev(call->fd, iov, 2); + ssize_t l = call->WriteV(call->fd, iov, 2); if (l < 0) { len = l; diff --git a/libeplayer3-arm/output/writer/sh4/pcm.c b/libeplayer3-arm/output/writer/sh4/pcm.c index 4a7103f..e9bef07 100644 --- a/libeplayer3-arm/output/writer/sh4/pcm.c +++ b/libeplayer3-arm/output/writer/sh4/pcm.c @@ -333,7 +333,7 @@ static int32_t writeData(void *_call) lpcm_prv[1] = ((lpcm_prv[1] + SubFramesPerPES) & 0x1F); iov[0].iov_len = InsertPesHeader(PesHeader, iov[1].iov_len + iov[2].iov_len, PCM_PES_START_CODE, call->Pts, 0); - int32_t len = writev(call->fd, iov, 3); + int32_t len = call->WriteV(call->fd, iov, 3); if (len < 0) { break; diff --git a/libeplayer3-arm/output/writer/sh4/vc1.c b/libeplayer3-arm/output/writer/sh4/vc1.c index 4865e9f..8545eba 100644 --- a/libeplayer3-arm/output/writer/sh4/vc1.c +++ b/libeplayer3-arm/output/writer/sh4/vc1.c @@ -199,14 +199,14 @@ static int writeData(void *_call) iov[1].iov_base = PesPayload; iov[1].iov_len = PesPtr - PesPayload; iov[0].iov_len = InsertPesHeader(PesHeader, iov[1].iov_len, VC1_VIDEO_PES_START_CODE, INVALID_PTS_VALUE, 0); - len = writev(call->fd, iov, 2); + len = call->WriteV(call->fd, iov, 2); /* For VC1 the codec private data is a standard vc1 sequence header so we just copy it to the output */ iov[0].iov_base = PesHeader; iov[1].iov_base = call->private_data; iov[1].iov_len = call->private_size; iov[0].iov_len = InsertPesHeader(PesHeader, iov[1].iov_len, VC1_VIDEO_PES_START_CODE, INVALID_PTS_VALUE, 0); - len = writev(call->fd, iov, 2); + len = call->WriteV(call->fd, iov, 2); initialHeader = 0; } @@ -251,7 +251,7 @@ static int writeData(void *_call) iov[1].iov_base = call->data + Position; iov[1].iov_len = PacketLength; - ssize_t l = writev(call->fd, iov, 2); + ssize_t l = call->WriteV(call->fd, iov, 2); if (l < 0) { len = l; diff --git a/libeplayer3-arm/output/writer/sh4/wma.c b/libeplayer3-arm/output/writer/sh4/wma.c index 4b92ac5..35408df 100644 --- a/libeplayer3-arm/output/writer/sh4/wma.c +++ b/libeplayer3-arm/output/writer/sh4/wma.c @@ -140,7 +140,7 @@ static int writeData(void *_call) iov[0].iov_len = InsertPesHeader(PesHeader, call->private_size, MPEG_AUDIO_PES_START_CODE, 0, 0); iov[1].iov_base = call->private_data; iov[1].iov_len = call->private_size; - len = writev(call->fd, iov, 2); + len = call->WriteV(call->fd, iov, 2); initialHeader = 0; } @@ -153,7 +153,7 @@ static int writeData(void *_call) iov[1].iov_base = call->data; iov[1].iov_len = call->len; - ssize_t l = writev(call->fd, iov, 2); + ssize_t l = call->WriteV(call->fd, iov, 2); len = (l > -1) ? len + l : l; } diff --git a/libeplayer3-arm/output/writer/sh4/writer.c b/libeplayer3-arm/output/writer/sh4/writer.c index 1ac9cf2..ce95099 100644 --- a/libeplayer3-arm/output/writer/sh4/writer.c +++ b/libeplayer3-arm/output/writer/sh4/writer.c @@ -26,6 +26,7 @@ #include #include +#include "misc.h" #include "writer.h" /* ***************************** */ @@ -96,6 +97,54 @@ static Writer_t *AvailableWriter[] = /* ***************************** */ /* Functions */ /* ***************************** */ +ssize_t WriteWithRetry(Context_t *context, int pipefd, int fd, const void *buf, int size) +{ + fd_set rfds; + + ssize_t ret; + int retval = -1; + struct timeval tv; + + while(size > 0 && 0 == PlaybackDieNow(0) && !context->playback->isSeeking) + { + if (context->playback->isPaused) + { + FD_ZERO(&rfds); + FD_SET(pipefd, &rfds); + + tv.tv_sec = 0; + tv.tv_usec = 500000; // 500ms + + retval = select(pipefd + 1, &rfds, NULL, NULL, &tv); + if (retval < 0) + { + break; + } + + if (retval == 0) + { + //printf("RETURN FROM SELECT DUE TO TIMEOUT TIMEOUT\n"); + continue; + } + + if(FD_ISSET(pipefd, &rfds)) + { + FlusPipe(pipefd); + //printf("RETURN FROM SELECT DUE TO pipefd SET\n"); + continue; + } + } + + //printf(">> Before Write fd [%d]\n", fd); + ret = write(fd, buf, size); + //printf(">> After Write ret[%d] size[%d]\n", (int)ret, size); + if (ret == size) + ret = 0; // no error + + break; + } + return ret; +} Writer_t *getWriter(char *encoding) { diff --git a/libeplayer3-arm/playback/playback.c b/libeplayer3-arm/playback/playback.c index 6ed983e..97e0c9a 100644 --- a/libeplayer3-arm/playback/playback.c +++ b/libeplayer3-arm/playback/playback.c @@ -361,9 +361,10 @@ static int PlaybackPause(Context_t *context) if (context->playback->SlowMotion) context->output->Command(context, OUTPUT_CLEAR, NULL); + context->playback->isPaused = 1; + context->output->Command(context, OUTPUT_PAUSE, NULL); - context->playback->isPaused = 1; //context->playback->isPlaying = 1; context->playback->isForwarding = 0; context->playback->BackWard = 0; From 4c38f644f648e2b333b07b1be5b83006153e9ef8 Mon Sep 17 00:00:00 2001 From: samsamsam Date: Sun, 15 Apr 2018 16:03:16 +0200 Subject: [PATCH 12/19] Fix typo Signed-off-by: max_10 Origin commit data ------------------ Branch: master Commit: https://github.com/neutrino-images/ni-libstb-hal/commit/3c7718425e9cfcd465665f2619b41598fa80b89b Author: samsamsam Date: 2018-04-15 (Sun, 15 Apr 2018) ------------------ This commit was generated by Migit --- libeplayer3-arm/include/writer.h | 2 +- libeplayer3-arm/output/writer/common/writer.c | 2 +- libeplayer3-arm/output/writer/mipsel/writer.c | 24 ++++++++++--------- 3 files changed, 15 insertions(+), 13 deletions(-) diff --git a/libeplayer3-arm/include/writer.h b/libeplayer3-arm/include/writer.h index cd535d9..9b7b7b5 100644 --- a/libeplayer3-arm/include/writer.h +++ b/libeplayer3-arm/include/writer.h @@ -92,5 +92,5 @@ ssize_t write_with_retry(int fd, const void *buf, int size); ssize_t writev_with_retry(int fd, const struct iovec *iov, int ic); ssize_t WriteWithRetry(Context_t *context, int pipefd, int fd, const void *buf, int size); -void FlusPipe(int pipefd); +void FlushPipe(int pipefd); #endif diff --git a/libeplayer3-arm/output/writer/common/writer.c b/libeplayer3-arm/output/writer/common/writer.c index 748bf36..2447288 100644 --- a/libeplayer3-arm/output/writer/common/writer.c +++ b/libeplayer3-arm/output/writer/common/writer.c @@ -67,7 +67,7 @@ if (debug_level >= level) printf(x); } while (0) /* ***************************** */ /* Functions */ /* ***************************** */ -void FlusPipe(int pipefd) +void FlushPipe(int pipefd) { char tmp; while(1 == read(pipefd, &tmp, 1)); diff --git a/libeplayer3-arm/output/writer/mipsel/writer.c b/libeplayer3-arm/output/writer/mipsel/writer.c index 33a83ab..6154238 100644 --- a/libeplayer3-arm/output/writer/mipsel/writer.c +++ b/libeplayer3-arm/output/writer/mipsel/writer.c @@ -119,13 +119,14 @@ ssize_t WriteWithRetry(Context_t *context, int pipefd, int fd, const void *buf, FD_SET(pipefd, &rfds); FD_SET(fd, &wfds); - /* When we PAUSE LINUX DVB outputs buffers then audio/video buffers - * will be filled to full unfortunately, in such case after resume - * select never return with fd set - bug in DVB drivers? - * So, there will be to workarounds: - * 1. write to pipe pipe at resume to exit select immediately - * 2. even if fd is not set exit from select after 0,1s - * (it seems that second workaround is not needed) + /* When we PAUSE LINUX DVB outputs buffers, then audio/video buffers + * will continue to be filled. Unfortunately, in such case after resume + * select() will never return with fd set - bug in DVB drivers? + * There are to workarounds possible: + * 1. write to pipe at resume to return from select() immediately + * 2. make timeout select(), limit max time spend in the select() + * to for example 0,1s + * (at now first workaround is used) */ //tv.tv_sec = 0; //tv.tv_usec = 100000; // 100ms @@ -138,13 +139,13 @@ ssize_t WriteWithRetry(Context_t *context, int pipefd, int fd, const void *buf, //if (retval == 0) //{ - // //printf("RETURN FROM SELECT DUE TO TIMEOUT TIMEOUT\n"); + // //printf("RETURN FROM SELECT DUE TO TIMEOUT\n"); // continue; //} if(FD_ISSET(pipefd, &rfds)) { - FlusPipe(pipefd); + FlushPipe(pipefd); //printf("RETURN FROM SELECT DUE TO pipefd SET\n"); continue; } @@ -172,12 +173,13 @@ ssize_t WriteWithRetry(Context_t *context, int pipefd, int fd, const void *buf, } else if (ret == 0) { - //printf("This should not happen. Select return fd ready to write, but write return 0, errno [%d]\n", errno); + // printf("This should not happen. Select return fd ready to write, but write return 0, errno [%d]\n", errno); + // wait 10ms before next try tv.tv_sec = 0; tv.tv_usec = 10000; // 10ms retval = select(pipefd + 1, &rfds, NULL, NULL, &tv); if (retval) - FlusPipe(pipefd); + FlushPipe(pipefd); continue; } From 124cb9bafd99abac9219d199d97f48429b9b5330 Mon Sep 17 00:00:00 2001 From: samsamsam Date: Tue, 17 Apr 2018 22:35:47 +0200 Subject: [PATCH 13/19] Fix typo Signed-off-by: max_10 Origin commit data ------------------ Branch: master Commit: https://github.com/neutrino-images/ni-libstb-hal/commit/02c5f4091e07726cdcc0c28e8a9b54cad45dee0f Author: samsamsam Date: 2018-04-17 (Tue, 17 Apr 2018) ------------------ This commit was generated by Migit --- libeplayer3-arm/output/writer/sh4/writer.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libeplayer3-arm/output/writer/sh4/writer.c b/libeplayer3-arm/output/writer/sh4/writer.c index ce95099..71aa862 100644 --- a/libeplayer3-arm/output/writer/sh4/writer.c +++ b/libeplayer3-arm/output/writer/sh4/writer.c @@ -129,7 +129,7 @@ ssize_t WriteWithRetry(Context_t *context, int pipefd, int fd, const void *buf, if(FD_ISSET(pipefd, &rfds)) { - FlusPipe(pipefd); + FlushPipe(pipefd); //printf("RETURN FROM SELECT DUE TO pipefd SET\n"); continue; } From b695479593447839dd1fd81f7cdabf4e5bb09631 Mon Sep 17 00:00:00 2001 From: max_10 Date: Thu, 19 Apr 2018 20:52:17 +0200 Subject: [PATCH 14/19] fix-compiler-warnings Origin commit data ------------------ Branch: master Commit: https://github.com/neutrino-images/ni-libstb-hal/commit/785f99c06507d793014e392b93f3ad822b8f98f8 Author: max_10 Date: 2018-04-19 (Thu, 19 Apr 2018) ------------------ No further description and justification available within origin commit message! ------------------ This commit was generated by Migit --- libeplayer3-arm/output/linuxdvb_buffering.c | 2 +- libeplayer3-arm/output/writer/common/writer.c | 2 +- libeplayer3-arm/output/writer/mipsel/aac.c | 5 +++-- libeplayer3-arm/output/writer/mipsel/writer.c | 2 +- 4 files changed, 6 insertions(+), 5 deletions(-) diff --git a/libeplayer3-arm/output/linuxdvb_buffering.c b/libeplayer3-arm/output/linuxdvb_buffering.c index 6633282..1df9028 100644 --- a/libeplayer3-arm/output/linuxdvb_buffering.c +++ b/libeplayer3-arm/output/linuxdvb_buffering.c @@ -392,7 +392,7 @@ ssize_t BufferingWriteV(int fd, const struct iovec *iov, int ic) BufferingNode_t *nodePtr = NULL; uint8_t *dataPtr = NULL; uint32_t chunkSize = 0; - uint32_t i = 0; + int i = 0; buff_printf(60, "ENTER\n"); if (fd == videofd) diff --git a/libeplayer3-arm/output/writer/common/writer.c b/libeplayer3-arm/output/writer/common/writer.c index 2447288..b866e2a 100644 --- a/libeplayer3-arm/output/writer/common/writer.c +++ b/libeplayer3-arm/output/writer/common/writer.c @@ -34,7 +34,7 @@ /* Makros/Constants */ /* ***************************** */ -#define WRITER_DEBUG +//#define WRITER_DEBUG #ifdef WRITER_DEBUG diff --git a/libeplayer3-arm/output/writer/mipsel/aac.c b/libeplayer3-arm/output/writer/mipsel/aac.c index 906e4fa..e75556c 100644 --- a/libeplayer3-arm/output/writer/mipsel/aac.c +++ b/libeplayer3-arm/output/writer/mipsel/aac.c @@ -323,8 +323,9 @@ static int writeDataLATM(WriterAVCallData_t *call) int ret = latmenc_decode_extradata(pLATMCtx, call->private_data, call->private_size); if (ret) { - //printf("%02x %02x %02x %02x %02x %02x %02x %02x\n", (int)call->data[0], (int)call->data[1], (int)call->data[2], (int)call->data[3], \ - // (int)call->data[4], (int)call->data[5], (int)call->data[6], (int)call->data[7]); + /* printf("%02x %02x %02x %02x %02x %02x %02x %02x\n", (int)call->data[0], (int)call->data[1], (int)call->data[2], (int)call->data[3], \ + (int)call->data[4], (int)call->data[5], (int)call->data[6], (int)call->data[7]); + */ aac_err("latm_decode_extradata failed. ignoring...\n"); return 0; } diff --git a/libeplayer3-arm/output/writer/mipsel/writer.c b/libeplayer3-arm/output/writer/mipsel/writer.c index 6154238..c5ccb35 100644 --- a/libeplayer3-arm/output/writer/mipsel/writer.c +++ b/libeplayer3-arm/output/writer/mipsel/writer.c @@ -237,7 +237,7 @@ ssize_t write_with_retry(int fd, const void *buf, int size) ssize_t writev_with_retry(int fd, const struct iovec *iov, int ic) { ssize_t len = 0; - uint32_t i = 0; + int i = 0; for (i = 0; i < ic; ++i) { write_with_retry(fd, iov[i].iov_base, iov[i].iov_len); From 7fa71875f9f9ca9f6f727dab992851adc9b5922d Mon Sep 17 00:00:00 2001 From: GetAway Date: Thu, 26 Apr 2018 09:10:04 +0200 Subject: [PATCH 15/19] fix possible segfault Signed-off-by: Thilo Graf Origin commit data ------------------ Branch: master Commit: https://github.com/neutrino-images/ni-libstb-hal/commit/320b2f02bf81e47f90c03d85836fb68a8c60a680 Author: GetAway Date: 2018-04-26 (Thu, 26 Apr 2018) ------------------ This commit was generated by Migit --- azbox/video.cpp | 8 +++++--- libarmbox/video.cpp | 8 +++++--- libspark/video.cpp | 8 +++++--- 3 files changed, 15 insertions(+), 9 deletions(-) diff --git a/azbox/video.cpp b/azbox/video.cpp index bf08c65..8ce3817 100644 --- a/azbox/video.cpp +++ b/azbox/video.cpp @@ -158,7 +158,9 @@ int cVideo::setAspectRatio(int aspect, int mode) /* { "panscan", "letterbox", "fullscreen", "14:9", "(unset)" } */ static const char *m[] = { "1", "2", "0", "1", "(unset)" }; int n; - lt_debug("%s: a:%d m:%d %s\n", __func__, aspect, mode, m[(mode < 0||mode > 3) ? 4 : mode]); + + int mo = (mode < 0||mode > 3) ? 4 : mode; + lt_debug("%s: a:%d m:%d %s\n", __func__, aspect, mode, m[(mo]); if (aspect > 3 || aspect == 0) lt_info("%s: invalid aspect: %d\n", __func__, aspect); @@ -173,8 +175,8 @@ int cVideo::setAspectRatio(int aspect, int mode) if (mode == -1) return 0; - lt_debug("%s: /proc/scalingmode -> %s\n", __func__, m[mode]); - n = proc_put("/proc/scalingmode", m[mode], strlen(m[mode])); + lt_debug("%s: /proc/scalingmode -> %s\n", __func__, m[mo]); + n = proc_put("/proc/scalingmode", m[mo], strlen(m[mo])); if (n < 0) return 1; return 0; diff --git a/libarmbox/video.cpp b/libarmbox/video.cpp index a9f6bda..06aab75 100644 --- a/libarmbox/video.cpp +++ b/libarmbox/video.cpp @@ -365,7 +365,9 @@ int cVideo::setAspectRatio(int aspect, int mode) // static const char *m[] = { "panscan", "letterbox", "bestfit", "nonlinear", "(unset)" }; static const char *m[] = { "letterbox", "panscan", "bestfit", "nonlinear", "(unset)" }; int n; - lt_debug("%s: a:%d m:%d %s\n", __func__, aspect, mode, m[(mode < 0||mode > 3) ? 4 : mode]); + + int mo = (mode < 0||mode > 3) ? 4 : mode; + lt_debug("%s: a:%d m:%d %s\n", __func__, aspect, mode, m[mo]); if (aspect > 3 || aspect == 0) lt_info("%s: invalid aspect: %d\n", __func__, aspect); @@ -380,8 +382,8 @@ int cVideo::setAspectRatio(int aspect, int mode) if (mode == -1) return 0; - lt_debug("%s: /proc/stb/video/policy -> %s\n", __func__, m[mode]); - n = proc_put("/proc/stb/video/policy", m[mode], strlen(m[mode])); + lt_debug("%s: /proc/stb/video/policy -> %s\n", __func__, m[mo]); + n = proc_put("/proc/stb/video/policy", m[mo], strlen(m[mo])); if (n < 0) return 1; return 0; diff --git a/libspark/video.cpp b/libspark/video.cpp index 3e331d9..a190ac8 100644 --- a/libspark/video.cpp +++ b/libspark/video.cpp @@ -361,7 +361,9 @@ int cVideo::setAspectRatio(int aspect, int mode) static const char *a[] = { "n/a", "4:3", "14:9", "16:9" }; static const char *m[] = { "panscan", "letterbox", "bestfit", "nonlinear", "(unset)" }; int n; - lt_debug("%s: a:%d m:%d %s\n", __func__, aspect, mode, m[(mode < 0||mode > 3) ? 4 : mode]); + + int mo = (mode < 0||mode > 3) ? 4 : mode; + lt_debug("%s: a:%d m:%d %s\n", __func__, aspect, mode, m[mo]); if (aspect > 3 || aspect == 0) lt_info("%s: invalid aspect: %d\n", __func__, aspect); @@ -376,8 +378,8 @@ int cVideo::setAspectRatio(int aspect, int mode) if (mode == -1) return 0; - lt_debug("%s: /proc/stb/video/policy -> %s\n", __func__, m[mode]); - n = proc_put("/proc/stb/video/policy", m[mode], strlen(m[mode])); + lt_debug("%s: /proc/stb/video/policy -> %s\n", __func__, m[mo]); + n = proc_put("/proc/stb/video/policy", m[mo], strlen(m[mo])); if (n < 0) return 1; return 0; From e6f48fec2da44f38aa4ac5b318497a7a1452a05a Mon Sep 17 00:00:00 2001 From: Jacek Jendrzej Date: Fri, 18 May 2018 12:50:12 +0200 Subject: [PATCH 16/19] use SetCECState in deepstandby Origin commit data ------------------ Branch: master Commit: https://github.com/neutrino-images/ni-libstb-hal/commit/2f1e2277477e3758aa451fb36e531ea6d092ebbc Author: Jacek Jendrzej Date: 2018-05-18 (Fri, 18 May 2018) ------------------ No further description and justification available within origin commit message! ------------------ This commit was generated by Migit --- libarmbox/video.cpp | 3 +++ 1 file changed, 3 insertions(+) diff --git a/libarmbox/video.cpp b/libarmbox/video.cpp index 06aab75..2b0ad32 100644 --- a/libarmbox/video.cpp +++ b/libarmbox/video.cpp @@ -323,6 +323,9 @@ cVideo::cVideo(int, void *, void *, unsigned int unit) cVideo::~cVideo(void) { + if (standby_cec_activ && fd >= 0) + SetCECState(true); + closeDevice(); } From 161597e49b3649aa3862f3ebd1fa6265f41490e6 Mon Sep 17 00:00:00 2001 From: Jacek Jendrzej Date: Sat, 19 May 2018 18:34:26 +0200 Subject: [PATCH 17/19] add av input switch in deep/standby Origin commit data ------------------ Branch: master Commit: https://github.com/neutrino-images/ni-libstb-hal/commit/5bccf15d9ce5075cd61862f5f75f5059d626ae70 Author: Jacek Jendrzej Date: 2018-05-19 (Sat, 19 May 2018) ------------------ No further description and justification available within origin commit message! ------------------ This commit was generated by Migit --- libarmbox/video.cpp | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) diff --git a/libarmbox/video.cpp b/libarmbox/video.cpp index 2b0ad32..8d502b7 100644 --- a/libarmbox/video.cpp +++ b/libarmbox/video.cpp @@ -301,6 +301,19 @@ int image_to_mpeg2(const char *image_name, int fd) return ret; } +void setAVInput(int val) +{ + if (val != 0 && val != 1) + return; + + int input_fd = open("/proc/stb/avs/0/input", O_WRONLY); + if(input_fd){ + const char *input[] = {"encoder", "aux"}; + write(input_fd, input[val], strlen(input[val])); + close(input_fd); + } +} + cVideo::cVideo(int, void *, void *, unsigned int unit) { lt_debug("%s unit %u\n", __func__, unit); @@ -323,6 +336,8 @@ cVideo::cVideo(int, void *, void *, unsigned int unit) cVideo::~cVideo(void) { + if(fd >= 0) + setAVInput(1); if (standby_cec_activ && fd >= 0) SetCECState(true); @@ -619,10 +634,14 @@ void cVideo::Standby(unsigned int bOn) if (bOn) { closeDevice(); + if(fd < 0) + setAVInput(1); } else { openDevice(); + if(fd >= 0) + setAVInput(0); } video_standby = bOn; SetCECState(video_standby); From 2ad3047c82b7a843981fdf994feea01ee3417f43 Mon Sep 17 00:00:00 2001 From: Jacek Jendrzej Date: Sat, 19 May 2018 19:21:22 +0200 Subject: [PATCH 18/19] use enum for setAVInput Origin commit data ------------------ Branch: master Commit: https://github.com/neutrino-images/ni-libstb-hal/commit/acf02c7dbdf67efcde4bad16c146796aa5a1b64f Author: Jacek Jendrzej Date: 2018-05-19 (Sat, 19 May 2018) ------------------ No further description and justification available within origin commit message! ------------------ This commit was generated by Migit --- libarmbox/video.cpp | 13 ++++--------- 1 file changed, 4 insertions(+), 9 deletions(-) diff --git a/libarmbox/video.cpp b/libarmbox/video.cpp index 8d502b7..4017b10 100644 --- a/libarmbox/video.cpp +++ b/libarmbox/video.cpp @@ -300,12 +300,9 @@ int image_to_mpeg2(const char *image_name, int fd) av_free(formatContext); return ret; } - +enum{ENCODER,AUX}; void setAVInput(int val) { - if (val != 0 && val != 1) - return; - int input_fd = open("/proc/stb/avs/0/input", O_WRONLY); if(input_fd){ const char *input[] = {"encoder", "aux"}; @@ -337,7 +334,7 @@ cVideo::cVideo(int, void *, void *, unsigned int unit) cVideo::~cVideo(void) { if(fd >= 0) - setAVInput(1); + setAVInput(AUX); if (standby_cec_activ && fd >= 0) SetCECState(true); @@ -634,14 +631,12 @@ void cVideo::Standby(unsigned int bOn) if (bOn) { closeDevice(); - if(fd < 0) - setAVInput(1); + setAVInput(AUX); } else { openDevice(); - if(fd >= 0) - setAVInput(0); + setAVInput(ENCODER); } video_standby = bOn; SetCECState(video_standby); From 6b681a5c71e5a884b48f9d42cd37a8f125c91b96 Mon Sep 17 00:00:00 2001 From: Jacek Jendrzej Date: Fri, 25 May 2018 17:05:09 +0200 Subject: [PATCH 19/19] fix CEC TV ON after deepstandby Origin commit data ------------------ Branch: master Commit: https://github.com/neutrino-images/ni-libstb-hal/commit/19b27c9a7e5347a954d1b36d3be6f76bfba16c80 Author: Jacek Jendrzej Date: 2018-05-25 (Fri, 25 May 2018) ------------------ No further description and justification available within origin commit message! ------------------ This commit was generated by Migit --- libarmbox/video.cpp | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) diff --git a/libarmbox/video.cpp b/libarmbox/video.cpp index 4017b10..a807eb0 100644 --- a/libarmbox/video.cpp +++ b/libarmbox/video.cpp @@ -1125,7 +1125,7 @@ bool cVideo::SetCECMode(VIDEO_HDMI_CEC_MODE _deviceType) physicalAddress[0] = 0x10; physicalAddress[1] = 0x00; logicalAddress = 1; - + if (_deviceType == VIDEO_HDMI_CEC_MODE_OFF) { if (hdmiFd >= 0) { @@ -1209,11 +1209,15 @@ bool cVideo::SetCECMode(VIDEO_HDMI_CEC_MODE _deviceType) if (ioctl(hdmiFd, CEC_S_MODE, &monitor) < 0) lt_info("%s: CEC monitor failed (%m)\n", __func__); + GetCECAddressInfo(); + + if(autoview_cec_activ) + SetCECState(false); + + return true; + } - - GetCECAddressInfo(); - - return true; + return false; } void cVideo::GetCECAddressInfo()