diff --git a/libeplayer3/output/writer/h264.c b/libeplayer3/output/writer/h264.c index 0d4aec4..fd78434 100644 --- a/libeplayer3/output/writer/h264.c +++ b/libeplayer3/output/writer/h264.c @@ -31,12 +31,14 @@ #include #include #include +#include #include #include #include #include #include #include +#include #include "common.h" #include "output.h" @@ -112,13 +114,14 @@ static int writeData(void* _call) unsigned char* PacketStart = NULL; unsigned int PacketStartSIZE = 0; - unsigned int HeaderLength; unsigned char PesHeader[PES_MAX_HEADER_SIZE]; unsigned long long int VideoPts; unsigned int TimeDelta; unsigned int TimeScale; int len = 0; static int NoOtherBeginningFound = 1; + int ic = 0; + struct iovec iov[128]; h264_printf(10, "\n"); if (call == NULL) @@ -149,34 +152,30 @@ static int writeData(void* _call) (call->data[0] == 0x00 && call->data[1] == 0x00 && call->data[2] == 0x01 && NoOtherBeginningFound) || (call->data[0] == 0xff && call->data[1] == 0xff && call->data[2] == 0xff && call->data[3] == 0xff)) { + unsigned int PacketLength = 0; unsigned int FakeStartCode = (call->Version << 8) | PES_VERSION_FAKE_START_CODE; - unsigned int PrivateLength=0; - if(initialHeader)PrivateLength = call->private_size; - HeaderLength = InsertPesHeader(PesHeader, call->len, - MPEG_VIDEO_PES_START_CODE, call->Pts, FakeStartCode); + iov[ic++].iov_base = PesHeader; + if (initialHeader) { + initialHeader = 0; + iov[ic].iov_base = call->private_data; + 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; /*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 */ - unsigned char *PacketData = malloc(HeaderLength + call->len + PrivateLength + 1); - - memcpy(PacketData, PesHeader, HeaderLength); - if(initialHeader){ - memcpy (PacketData + HeaderLength, call->private_data, PrivateLength); - initialHeader=0; - } - memcpy (PacketData + HeaderLength + PrivateLength, call->data, call->len); - - len = write(call->fd, PacketData, call->len + HeaderLength + PrivateLength + 1); - - free(PacketData); - - return len; + iov[ic].iov_base = ""; + iov[ic++].iov_len = 1; + iov[0].iov_len = InsertPesHeader(PesHeader, PacketLength, MPEG_VIDEO_PES_START_CODE, call->Pts, FakeStartCode); + return writev(call->fd, iov, ic); } NoOtherBeginningFound = 0; if (initialHeader) { - unsigned char* HeaderData = malloc(BUFFER_SIZE+PADDING_LENGTH); avcC_t* avcCHeader = (avcC_t*)call->private_data; int i; unsigned int ParamSets; @@ -184,10 +183,8 @@ static int writeData(void* _call) unsigned int InitialHeaderLength = 0; unsigned int ParametersLength; - if (avcCHeader == NULL) - { + if (avcCHeader == NULL) { h264_err("private_data NULL\n"); - free(HeaderData); return -1; } @@ -196,6 +193,7 @@ static int writeData(void* _call) ParametersLength = 0; + unsigned char HeaderData[19]; HeaderData[ParametersLength++] = 0x00; // Start code HeaderData[ParametersLength++] = 0x00; HeaderData[ParametersLength++] = 0x01; @@ -222,13 +220,16 @@ static int writeData(void* _call) HeaderData[ParametersLength++] = 0xff; HeaderData[ParametersLength++] = 0x80; // Rsbp trailing bits - HeaderLength = InsertPesHeader (PesHeader, ParametersLength, MPEG_VIDEO_PES_START_CODE, INVALID_PTS_VALUE, 0); + assert(ParametersLength <= sizeof(HeaderData)); - PacketStart = malloc(HeaderLength + ParametersLength); - PacketStartSIZE = HeaderLength + ParametersLength; - memcpy (PacketStart, PesHeader, HeaderLength); - memcpy (PacketStart + HeaderLength, HeaderData, ParametersLength); - len += write (call->fd, PacketStart, HeaderLength + ParametersLength); + ic = 0; + iov[ic].iov_base = PesHeader; + 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); + if (len < 0) + return len; NalLengthBytes = (avcCHeader->NalLengthMinusOne & 0x03) + 1; ParamSets = avcCHeader->NumParamSets & 0x1f; @@ -242,26 +243,18 @@ static int writeData(void* _call) 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); - if (HeaderLength + InitialHeaderLength + sizeof(Head) > PacketStartSIZE) { - PacketStart = realloc(PacketStart, HeaderLength + InitialHeaderLength + sizeof(Head)); - PacketStartSIZE = HeaderLength + InitialHeaderLength + sizeof(Head); - } - - memcpy (PacketStart + HeaderLength + InitialHeaderLength, Head, sizeof(Head)); + iov[ic].iov_base = (char *)Head; + iov[ic++].iov_len = sizeof(Head); InitialHeaderLength += sizeof(Head); - - if (HeaderLength + InitialHeaderLength + PsLength > PacketStartSIZE) { - PacketStart = realloc(PacketStart, HeaderLength + InitialHeaderLength + PsLength); - PacketStartSIZE = HeaderLength + InitialHeaderLength + PsLength; - } - - memcpy (PacketStart + HeaderLength + InitialHeaderLength, &avcCHeader->Params[ParamOffset+2], PsLength); - + iov[ic].iov_base = &avcCHeader->Params[ParamOffset+2]; + iov[ic++].iov_len = PsLength; InitialHeaderLength += PsLength; ParamOffset += PsLength+2; } @@ -276,39 +269,29 @@ static int writeData(void* _call) h264_printf (20, " pps %d has length %d\n", i, PsLength); - if (HeaderLength + InitialHeaderLength + sizeof(Head) > PacketStartSIZE) { - PacketStart = realloc(PacketStart, HeaderLength + InitialHeaderLength + sizeof(Head)); - PacketStartSIZE = HeaderLength + InitialHeaderLength + sizeof(Head); - } - - memcpy (PacketStart + HeaderLength + InitialHeaderLength, Head, sizeof(Head)); + iov[ic].iov_base = (char *) Head; + iov[ic++].iov_len = sizeof(Head); InitialHeaderLength += sizeof(Head); - - if (HeaderLength + InitialHeaderLength + PsLength > PacketStartSIZE) { - PacketStart = realloc(PacketStart, HeaderLength + InitialHeaderLength + PsLength); - PacketStartSIZE = HeaderLength + InitialHeaderLength + PsLength; - } - - memcpy (PacketStart + HeaderLength + InitialHeaderLength, &avcCHeader->Params[ParamOffset+2], PsLength); + iov[ic].iov_base = &avcCHeader->Params[ParamOffset+2]; + iov[ic++].iov_len = PsLength; InitialHeaderLength += PsLength; ParamOffset += PsLength+2; } - HeaderLength = InsertPesHeader (PesHeader, InitialHeaderLength, MPEG_VIDEO_PES_START_CODE, INVALID_PTS_VALUE, 0); - memcpy (PacketStart, PesHeader, HeaderLength); - - len += write (call->fd, PacketStart, HeaderLength + InitialHeaderLength); + 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 (l < 0) + return l; + len += l; initialHeader = 0; - - free(PacketStart); - free(HeaderData); } unsigned int SampleSize = call->len; unsigned int NalStart = 0; unsigned int VideoPosition = 0; + ic = 0; do { unsigned int NalLength; unsigned char NalData[4]; @@ -316,10 +299,13 @@ static int writeData(void* _call) memcpy (NalData, call->data + VideoPosition, NalLengthBytes); VideoPosition += NalLengthBytes; - NalLength = (NalLengthBytes == 1) ? NalData[0] : - (NalLengthBytes == 2) ? (NalData[0] << 8) | NalData[1] : - (NalLengthBytes == 3) ? (NalData[0] << 16) | (NalData[1] << 8) | NalData[2] : - (NalData[0] << 24) | (NalData[1] << 16) | (NalData[2] << 8) | NalData[3]; + NalStart += NalLengthBytes; + switch(NalLength) { + case 1: NalLength = (NalData[0]); break; + case 2: NalLength = (NalData[0] << 8) | (NalData[1]); break; + case 3: NalLength = (NalData[0] << 16) | (NalData[1] << 8) | (NalData[2]); break; + default: 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); @@ -330,45 +316,35 @@ static int writeData(void* _call) NalStart = SampleSize; } else { - NalStart += NalLength + NalLengthBytes; + NalStart += NalLength; while (NalLength > 0) { unsigned int PacketLength = (NalLength < BUFFER_SIZE) ? NalLength : BUFFER_SIZE; int ExtraLength = 0; -#ifndef MARTII - unsigned char* PacketStart; -#endif NalLength -= PacketLength; + ic = 0; + iov[ic++].iov_base = PesHeader; + if (NalPresent) { - PacketStart = malloc(sizeof(Head) + PacketLength); - memcpy (PacketStart + sizeof(Head), call->data + VideoPosition, PacketLength); - VideoPosition += PacketLength; + NalPresent = 0; + iov[ic].iov_base = (char *)Head; + iov[ic++].iov_len = sizeof(Head); + PacketLength += sizeof(Head); + } - memcpy (PacketStart, Head, sizeof(Head)); - ExtraLength = sizeof(Head); - } else { - PacketStart = malloc(PacketLength); - memcpy (PacketStart, call->data + VideoPosition, PacketLength); - VideoPosition += PacketLength; - } - - PacketLength += ExtraLength; + iov[ic].iov_base = call->data + VideoPosition; + iov[ic++].iov_len = PacketLength; + VideoPosition += PacketLength; h264_printf (20, " pts=%llu\n", VideoPts); - HeaderLength = InsertPesHeader (PesHeader, PacketLength, MPEG_VIDEO_PES_START_CODE, VideoPts, 0); + iov[0].iov_len = InsertPesHeader (PesHeader, PacketLength, MPEG_VIDEO_PES_START_CODE, VideoPts, 0); + ssize_t l = writev(call->fd, iov, ic); + if (l < 0) + return l; + len += l; - unsigned char* WritePacketStart = malloc(HeaderLength + PacketLength); - memcpy (WritePacketStart, PesHeader, HeaderLength); - memcpy (WritePacketStart+HeaderLength, PacketStart, PacketLength); - free(PacketStart); - - PacketLength += HeaderLength; - len += write (call->fd, WritePacketStart, PacketLength); - free(WritePacketStart); - - NalPresent = 0; VideoPts = INVALID_PTS_VALUE; } }