コード例 #1
0
ファイル: mpeg4.c プロジェクト: 68foxboris/exteplayer3
static int writeData(void* _call)
{
    WriterAVCallData_t* call = (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;
        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 = call->WriteV(call->fd, iov, ic);

    mpeg4_printf(10, "xvid_Write < len=%d\n", len);

    return len;
}
コード例 #2
0
ファイル: mp3.c プロジェクト: Audioniek/apps
static int writeData(void* _call)
{
    WriterAVCallData_t* call = (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)
    {
        memcpy(&PesHeader[headerSize], call->private_data, call->private_size);
        headerSize += call->private_size;
    }
    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);

    mp3_printf(10, "mp3_Write-< len=%d\n", len);
    return len;
}
コード例 #3
0
ファイル: vc1.c プロジェクト: 68foxboris/exteplayer3
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];
        unsigned char   PesPayload[128];
        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;
        *PesPtr++ = (call->Height >> 16) & 0xff;
        *PesPtr++ =  call->Height >> 24;
        *PesPtr++ = (call->Width  >>  0) & 0xff;
        *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 = 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 = call->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));
                    HeaderLength += sizeof(Vc1FrameStartCode);
                }
                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 = call->WriteV(call->fd, iov, 2);
            if (l < 0) 
            {
                len = l;
                break;
            }
            len += l;

            Position += PacketLength;
            call->Pts = INVALID_PTS_VALUE;
        }
    }

    vc1_printf(10, "< %d\n", len);
    return len;
}
コード例 #4
0
ファイル: h265.c プロジェクト: 68foxboris/exteplayer3
static int writeData(void* _call)
{
    WriterAVCallData_t* call = (WriterAVCallData_t*) _call;

    unsigned char           PesHeader[PES_MAX_HEADER_SIZE];
    unsigned long long int  VideoPts;
    unsigned int            TimeDelta;
    unsigned int            TimeScale;
    int                     len = 0;
    int ic = 0;
    struct iovec iov[IOVEC_SIZE];
    h265_printf(20, "\n");

    if (call == NULL)
    {
        h264_err("call data is NULL...\n");
        return 0;
    }

    TimeDelta = call->FrameRate;
    TimeScale = call->FrameScale;
    VideoPts  = call->Pts;
    
    h265_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
    {
        h265_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) 
        {
            initialHeader = 0;
            iov[ic].iov_base  = call->private_data;
            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)
        {
            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;
            iov[ic++].iov_len = CodecDataLen;
            PacketLength     += CodecDataLen;
            initialHeader = 0;
        }
    }

    if (CodecData != NULL)
    {
        uint32_t pos = 0;
        do
        {
            if (ic >= IOVEC_SIZE)
            {
                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++)
            {
                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);
        
        h265_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)
        {
            h264_err("<<<< not all data have been written [%d/%d]\n", len, PacketLength);
        }
    }

    h265_printf (10, "< len %d\n", len);
    return len;
}
コード例 #5
0
ファイル: divx2.c プロジェクト: 68foxboris/exteplayer3
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;
    unsigned char  Version             = 5;
    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
       PutBits(&ld, 0x0, 8);
       PutBits(&ld, 0x0, 8);
     */
    PutBits(&ld, 0x1b0, 32);      // startcode
    PutBits(&ld, 0, 8);           // profile = reserved
    PutBits(&ld, 0x1b2, 32);      // startcode (user data)
    PutBits(&ld, 0x53545443, 32); // STTC - an embedded ST timecode from an avi file
    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 = call->WriteV(call->fd, iov, ic);

    divx_printf(10, "xvid_Write < len=%d\n", len);

    return len;
}
コード例 #6
0
ファイル: vc1.c プロジェクト: 68foxboris/exteplayer3
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);
    
    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) 
    {
        initialHeader = 0;
        if(videocodecdata.data)
        {
            free(videocodecdata.data);
            videocodecdata.data = NULL;
        }
        videocodecdata.length = call->private_size + 8;
        videocodecdata.data  = malloc(videocodecdata.length);
        memset(videocodecdata.data, 0, videocodecdata.length);
        memcpy(videocodecdata.data + 8, call->private_data, call->private_size);
        if(IsDreambox() || 0 != ioctl(call->fd, VIDEO_SET_CODEC_DATA, &videocodecdata))
        {
            iov[ic].iov_base  = videocodecdata.data;
            iov[ic++].iov_len = videocodecdata.length;
            PacketLength     += videocodecdata.length;
        }
    }
    
    uint8_t needFrameStartCode = 0;
    if( sizeof(Vc1FrameStartCode) >= call->len
        || memcmp(call->data, Vc1FrameStartCode, sizeof(Vc1FrameStartCode)) != 0 )
    {
        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);
}
コード例 #7
0
static int writeData(void* _call)
{
    WriterAVCallData_t* call = (WriterAVCallData_t*) _call;

    static uint8_t PesHeader[PES_MAX_HEADER_SIZE];
    int32_t len = 0;
    uint32_t 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;
    }

    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))
    {
        bool ok = true;
        uint32_t pos = 4;
        uint32_t sheader_data_len = 0;
        while (pos < data_len && ok)
        {
            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;
        }
    }
    else if ((private_data || call->private_data) && must_send_header)
    {
        uint8_t *codec_data = NULL;
        uint32_t codec_data_size = 0;
        int pos = 0;

        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);
        }
    }

    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;
}
コード例 #8
0
ファイル: pcm.c プロジェクト: Audioniek/apps
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;
        uint8_t LE = 0;
        switch (codecID)
        {
            case AV_CODEC_ID_PCM_S8:
            case AV_CODEC_ID_PCM_U8:
                break;
            case AV_CODEC_ID_PCM_S16LE:
            case AV_CODEC_ID_PCM_U16LE:
                LE = 1;
            case AV_CODEC_ID_PCM_S16BE:
            case AV_CODEC_ID_PCM_U16BE:
                break;
            case AV_CODEC_ID_PCM_S24LE:
            case AV_CODEC_ID_PCM_U24LE:
                LE = 1;
            case AV_CODEC_ID_PCM_S24BE:
            case AV_CODEC_ID_PCM_U24BE:
                break;
            case AV_CODEC_ID_PCM_S32LE:
            case AV_CODEC_ID_PCM_U32LE:
                LE = 1;
            case AV_CODEC_ID_PCM_S32BE:
            case AV_CODEC_ID_PCM_U32BE:
                break;
            default:
                break;
        }
        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);
        if((size - pos) < SubFrameLen)
        {
            breakBufferFillSize = size - pos;
            memcpy(breakBuffer, &buffer[pos], sizeof(uint8_t) * breakBufferFillSize);
            //printf("PCM %s - Unplayed=%d\n", __FUNCTION__, breakBufferFillSize);
            break;
        }

        //get first PES's worth
        if(breakBufferFillSize > 0)
        {
            memcpy(injectBuffer, breakBuffer, sizeof(uint8_t)*breakBufferFillSize);
            memcpy(&injectBuffer[breakBufferFillSize], &buffer[pos], sizeof(unsigned char)*(SubFrameLen - breakBufferFillSize));
            pos += (SubFrameLen - breakBufferFillSize);
            breakBufferFillSize = 0;
        }
        else
        {
            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) 
        {
            for(n=0; n<SubFrameLen; n+=2)
            {
                uint8_t tmp;
                tmp=injectBuffer[n];
                injectBuffer[n]=injectBuffer[n+1];
                injectBuffer[n+1]=tmp;
            }
        } 
        else
        {
            //      0   1   2   3   4   5   6   7   8   9  10  11
            //    A1c A1b A1a-B1c B1b B1a-A2c A2b A2a-B2c B2b B2a
            // to A1a A1b B1a B1b.A2a A2b B2a B2b-A1c B1c A2c B2c
            for(n=0; n<SubFrameLen; n+=12) {
                unsigned char t, *p = &injectBuffer[n];
                t = p[0];
                p[ 0] = p[ 2];
                p[ 2] = p[ 5];
                p[ 5] = p[ 7];
                p[ 7] = p[11];
                p[11] = p[ 9];
                p[ 9] = p[ 3];
                p[ 3] = p[ 4];
                p[ 4] = p[ 8];
                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 = call->WriteV(call->fd, iov, 3);
        if (len < 0)
        {
            break;
        }
    }
    free(injectBuffer);

    return size;
}