diff --git a/libeplayer3-arm/main/exteplayer.c b/libeplayer3-arm/main/exteplayer.c index 1daf97e..3a30bcc 100644 --- a/libeplayer3-arm/main/exteplayer.c +++ b/libeplayer3-arm/main/exteplayer.c @@ -698,7 +698,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", 53); + fprintf(stderr, "{\"EPLAYER3_EXTENDED\":{\"version\":%d}}\n", 54); PlayFiles_t playbackFiles; memset(&playbackFiles, 0x00, sizeof(playbackFiles)); diff --git a/libeplayer3-arm/output/writer/mipsel/mpeg2.c b/libeplayer3-arm/output/writer/mipsel/mpeg2.c index c40667b..414a1c5 100644 --- a/libeplayer3-arm/output/writer/mipsel/mpeg2.c +++ b/libeplayer3-arm/output/writer/mipsel/mpeg2.c @@ -61,6 +61,11 @@ /* Variables */ /* ***************************** */ +static bool must_send_header = true; +static uint8_t *private_data = NULL; +static uint32_t private_size = 0; + + /* ***************************** */ /* Prototypes */ /* ***************************** */ @@ -71,6 +76,7 @@ static int reset() { + must_send_header = true; return 0; } @@ -78,8 +84,9 @@ static int writeData(WriterAVCallData_t *call) { unsigned char PesHeader[PES_MAX_HEADER_SIZE]; - int len = 0; - unsigned int Position = 0; + static uint8_t PesHeader[PES_MAX_HEADER_SIZE]; + int32_t len = 0; + uint32_t Position = 0; mpeg2_printf(10, "\n"); @@ -103,35 +110,143 @@ static int writeData(WriterAVCallData_t *call) return 0; } - while (Position < call->len) + uint8_t *data = call->data; + uint32_t data_len = call->len; + + if (!private_data && !call->private_data && data_len > 3 && !memcmp(data, "\x00\x00\x01\xb3", 4)) { - 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) + bool ok = true; + uint32_t pos = 4; + uint32_t sheader_data_len = 0; + while (pos < data_len && ok) { - len = l; + if (pos >= data_len) break; + pos += 7; + if (pos >= data_len) break; + sheader_data_len = 12; + if (data[pos] & 2) + { + // intra matrix + pos += 64; + if (pos >= data_len) break; + sheader_data_len += 64; + } + if (data[pos] & 1) + { + // non intra matrix + pos += 64; + if (pos >= data_len) break; + sheader_data_len += 64; + } + pos += 1; + if (pos + 3 >= data_len) break; + if (!memcmp(&data[pos], "\x00\x00\x01\xb5", 4)) + { + // extended start code + pos += 3; + sheader_data_len += 3; + do + { + pos += 1; + ++sheader_data_len; + if (pos + 2 > data_len) + { + ok = false; + break; + } + } + while (memcmp(&data[pos], "\x00\x00\x01", 3)); + if (!ok) break; + } + if (pos + 3 >= data_len) break; + if (!memcmp(&data[pos], "\x00\x00\x01\xb2", 4)) + { + // private data + pos += 3; + sheader_data_len += 3; + do + { + pos += 1; + ++sheader_data_len; + if (pos + 2 > data_len) + { + ok = false; + break; + } + } + while (memcmp(&data[pos], "\x00\x00\x01", 3)); + if (!ok) break; + } + + free(private_data); + private_data = malloc(sheader_data_len); + if (private_data) + { + private_size = sheader_data_len; + memcpy(private_data, data + pos - sheader_data_len, sheader_data_len); + } + must_send_header = false; break; } - len += l; + } + else if ((private_data || call->private_data) && must_send_header) + { + uint8_t *codec_data = NULL; + uint32_t codec_data_size = 0; + int pos = 0; - Position += PacketLength; - call->Pts = INVALID_PTS_VALUE; + if (private_data) + { + codec_data = private_data; + codec_data_size = private_size; + } + else + { + codec_data = call->private_data; + codec_data_size = call->private_size; + } + + while (pos <= data_len - 4) + { + if (memcmp(&data[pos], "\x00\x00\x01\xb8", 4)) /* find group start code */ + { + pos++; + continue; + } + + struct iovec iov[4]; + iov[0].iov_base = PesHeader; + iov[0].iov_len = InsertPesHeader(PesHeader, call->len + codec_data_size, MPEG_VIDEO_PES_START_CODE, call->Pts, 0); + + iov[1].iov_base = data; + iov[1].iov_len = pos; + + iov[2].iov_base = codec_data; + iov[2].iov_len = codec_data_size; + + iov[3].iov_base = data + pos; + iov[3].iov_len = data_len - pos; + + must_send_header = false; + return call->WriteV(call->fd, iov, 4); + } } - mpeg2_printf(10, "< len %d\n", len); - return len; + struct iovec iov[2]; + + iov[0].iov_base = PesHeader; + iov[0].iov_len = InsertPesHeader(PesHeader, call->len, MPEG_VIDEO_PES_START_CODE, call->Pts, 0); + + iov[1].iov_base = data; + iov[1].iov_len = data_len; + + PesHeader[6] = 0x81; + + UpdatePesHeaderPayloadSize(PesHeader, data_len + iov[0].iov_len - 6); + if (iov[0].iov_len != WriteExt(call->WriteV, call->fd, iov[0].iov_base, iov[0].iov_len)) return -1; + if (iov[1].iov_len != WriteExt(call->WriteV, call->fd, iov[1].iov_base, iov[1].iov_len)) return -1; + + return 1; } /* ***************************** */ @@ -144,7 +259,7 @@ static WriterCaps_t caps = "V_MPEG2", VIDEO_ENCODING_AUTO, STREAMTYPE_MPEG2, - CT_MPEG2 + -1 }; struct Writer_s WriterVideoMPEG2 = @@ -159,9 +274,9 @@ static WriterCaps_t mpg1_caps = "mpge1", eVideo, "V_MPEG1", - VIDEO_ENCODING_H264, + VIDEO_ENCODING_AUTO, STREAMTYPE_MPEG1, - CT_MPEG1 + -1 }; struct Writer_s WriterVideoMPEG1 = diff --git a/libeplayer3-arm/output/writer/mipsel/writer.c b/libeplayer3-arm/output/writer/mipsel/writer.c index 4852940..45a2bb8 100644 --- a/libeplayer3-arm/output/writer/mipsel/writer.c +++ b/libeplayer3-arm/output/writer/mipsel/writer.c @@ -40,8 +40,6 @@ #define getDVBMutex(pmtx) do { if (pmtx) pthread_mutex_lock(pmtx);} while(false); #define releaseDVBMutex(pmtx) do { if (pmtx) pthread_mutex_unlock(pmtx);} while(false); -#define FULL_PROTECTION_MODE 1 - /* ***************************** */ /* Types */ /* ***************************** */ @@ -108,6 +106,15 @@ ssize_t WriteWithRetry(Context_t *context, int pipefd, int fd, void *pDVBMtx, co int maxFd = pipefd > fd ? pipefd : fd; struct timeval tv; + static bool first = true; + if (first && STB_HISILICON == GetSTBType()) + { + // workaround: playback of some files does not start + // if injection of the frist frame is to fast + usleep(100000); + } + first = false; + while (size > 0 && 0 == PlaybackDieNow(0) && !context->playback->isSeeking) { FD_ZERO(&rfds); @@ -149,70 +156,7 @@ ssize_t WriteWithRetry(Context_t *context, int pipefd, int fd, void *pDVBMtx, co if (FD_ISSET(fd, &wfds)) { - // special protection to not allow inject AV data - // at PAUSE, SEEK and vice versa - if (pDVBMtx && STB_HISILICON == GetSTBType()) - { - DVBState_t dvbSts = DVB_STS_UNKNOWN; - getDVBMutex(pDVBMtx); - ret = 0; - if (PlaybackDieNow(0)) - dvbSts = DVB_STS_EXIT; - else if (context->playback->isSeeking) - dvbSts = DVB_STS_SEEK; - else if (context->playback->isPaused) - dvbSts = DVB_STS_PAUSE; - else - { -#ifdef FULL_PROTECTION_MODE - ret = write(fd, buf, size); -#endif - } - releaseDVBMutex(pDVBMtx); - - if (dvbSts == DVB_STS_EXIT || dvbSts == DVB_STS_SEEK) - { - return 0; - } - else if (dvbSts == DVB_STS_PAUSE) - { - 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)) - { - FlushPipe(pipefd); - //printf("RETURN FROM SELECT DUE TO pipefd SET\n"); - continue; - } - } -#ifndef FULL_PROTECTION_MODE - else - { - ret = write(fd, buf, size); - } -#endif - } - else - { - ret = write(fd, buf, size); - } - + ret = write(fd, buf, size); if (ret < 0) { switch (errno)