add libeplayer3-arm test

This commit is contained in:
max_10
2017-12-16 23:41:01 +01:00
committed by Thilo Graf
parent f28d013972
commit b75f8393c2
101 changed files with 28366 additions and 21 deletions

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,560 @@
/*
* Output handling.
*
*
* 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 <stdio.h>
#include <string.h>
#include "common.h"
#include "output.h"
/* ***************************** */
/* Makros/Constants */
/* ***************************** */
#ifdef SAM_WITH_DEBUG
#define OUTPUT_DEBUG
#else
#define OUTPUT_SILENT
#endif
#ifdef OUTPUT_DEBUG
static short debug_level = 0;
#define output_printf(level, x...) do { \
if (debug_level >= level) fprintf(stderr, x); } while (0)
#else
#define output_printf(level, x...)
#endif
#ifndef OUTPUT_SILENT
#define output_err(x...) do { printf(x); } while (0)
#else
#define output_err(x...)
#endif
/* Error Constants */
#define cERR_OUTPUT_NO_ERROR 0
#define cERR_OUTPUT_INTERNAL_ERROR -1
static const char *FILENAME = "output.c";
/* ***************************** */
/* Types */
/* ***************************** */
/* ***************************** */
/* Varaibles */
/* ***************************** */
static Output_t *AvailableOutput[] =
{
&LinuxDvbOutput,
&SubtitleOutput,
NULL
};
/* ***************************** */
/* Prototypes */
/* ***************************** */
/* ***************************** */
/* MISC Functions */
/* ***************************** */
static void printOutputCapabilities()
{
int i, j;
output_printf(10, "%s::%s\n", FILENAME, __FUNCTION__);
output_printf(10, "Capabilities:\n");
for (i = 0; AvailableOutput[i] != NULL; i++)
{
output_printf(10, "\t%s : ", AvailableOutput[i]->Name);
for (j = 0; AvailableOutput[i]->Capabilities[j] != NULL; j++)
{
output_printf(10, "%s ", AvailableOutput[i]->Capabilities[j]);
}
output_printf(10, "\n");
}
}
/* ***************************** */
/* Output Functions */
/* ***************************** */
static void OutputAdd(Context_t *context, char *port)
{
int i, j;
output_printf(10, "%s::%s\n", FILENAME, __FUNCTION__);
for (i = 0; AvailableOutput[i] != NULL; i++)
{
for (j = 0; AvailableOutput[i]->Capabilities[j] != NULL; j++)
{
if (!strcmp(AvailableOutput[i]->Capabilities[j], port))
{
if (!strcmp("audio", port))
{
context->output->audio = AvailableOutput[i];
return;
}
else if (!strcmp("video", port))
{
context->output->video = AvailableOutput[i];
return;
}
else if (!strcmp("subtitle", port))
{
context->output->subtitle = AvailableOutput[i];
return;
}
}
}
}
}
static void OutputDel(Context_t *context, char *port)
{
output_printf(10, "%s::%s\n", FILENAME, __FUNCTION__);
if (!strcmp("audio", port))
{
context->output->audio = NULL;
}
else if (!strcmp("video", port))
{
context->output->video = NULL;
}
else if (!strcmp("subtitle", port))
{
context->output->subtitle = NULL;
}
}
static int Command(void *_context, OutputCmd_t command, void *argument)
{
Context_t *context = (Context_t *) _context;
int ret = cERR_OUTPUT_NO_ERROR;
output_printf(10, "%s::%s Command %d\n", FILENAME, __FUNCTION__, command);
switch (command)
{
case OUTPUT_OPEN:
{
if (context && context->playback)
{
if (context->playback->isVideo)
{
ret |= context->output->video->Command(context, OUTPUT_OPEN, "video");
}
if (context->playback->isAudio)
{
ret |= context->output->audio->Command(context, OUTPUT_OPEN, "audio");
}
if (context->playback->isSubtitle)
{
ret |= context->output->subtitle->Command(context, OUTPUT_OPEN, "subtitle");
}
}
else
{
ret = cERR_OUTPUT_INTERNAL_ERROR;
}
break;
}
case OUTPUT_CLOSE:
{
if (context && context->playback)
{
if (context->playback->isVideo)
{
ret |= context->output->video->Command(context, OUTPUT_CLOSE, "video");
}
if (context->playback->isAudio)
{
ret |= context->output->audio->Command(context, OUTPUT_CLOSE, "audio");
}
if (context->playback->isSubtitle)
{
ret |= context->output->subtitle->Command(context, OUTPUT_CLOSE, "subtitle");
}
}
else
{
ret = cERR_OUTPUT_INTERNAL_ERROR;
}
break;
}
case OUTPUT_ADD:
{
OutputAdd(context, (char *) argument);
break;
}
case OUTPUT_DEL:
{
OutputDel(context, (char *) argument);
break;
}
case OUTPUT_CAPABILITIES:
{
printOutputCapabilities();
break;
}
case OUTPUT_PLAY:
{
// 4
if (context && context->playback)
{
if (context->playback->isVideo)
{
ret = context->output->video->Command(context, OUTPUT_PLAY, "video");
}
// success or not executed, dunn care
if (!ret)
{
if (context->playback->isAudio)
{
ret = context->output->audio->Command(context, OUTPUT_PLAY, "audio");
}
}
if (!ret)
{
if (context->playback->isSubtitle)
{
ret = context->output->subtitle->Command(context, OUTPUT_PLAY, "subtitle");
}
}
}
else
{
ret = cERR_OUTPUT_INTERNAL_ERROR;
}
break;
}
case OUTPUT_STOP:
{
if (context && context->playback)
{
if (context->playback->isVideo)
{
ret |= context->output->video->Command(context, OUTPUT_STOP, "video");
}
if (context->playback->isAudio)
{
ret |= context->output->audio->Command(context, OUTPUT_STOP, "audio");
}
if (context->playback->isSubtitle)
{
ret |= context->output->subtitle->Command(context, OUTPUT_STOP, "subtitle");
}
}
else
{
ret = cERR_OUTPUT_INTERNAL_ERROR;
}
break;
}
case OUTPUT_FLUSH:
{
if (context && context->playback)
{
if (context->playback->isVideo)
{
ret |= context->output->video->Command(context, OUTPUT_FLUSH, "video");
}
if (context->playback->isAudio)
{
ret |= context->output->audio->Command(context, OUTPUT_FLUSH, "audio");
}
if (context->playback->isSubtitle)
{
ret |= context->output->subtitle->Command(context, OUTPUT_FLUSH, "subtitle");
}
}
else
{
ret = cERR_OUTPUT_INTERNAL_ERROR;
}
break;
}
case OUTPUT_PAUSE:
{
if (context && context->playback)
{
if (context->playback->isVideo)
{
ret |= context->output->video->Command(context, OUTPUT_PAUSE, "video");
}
if (context->playback->isAudio)
{
ret |= context->output->audio->Command(context, OUTPUT_PAUSE, "audio");
}
if (context->playback->isSubtitle)
{
ret |= context->output->subtitle->Command(context, OUTPUT_PAUSE, "subtitle");
}
}
else
{
ret = cERR_OUTPUT_INTERNAL_ERROR;
}
break;
}
case OUTPUT_FASTFORWARD:
{
if (context && context->playback)
{
if (context->playback->isVideo)
{
ret |= context->output->video->Command(context, OUTPUT_FASTFORWARD, "video");
}
if (context->playback->isAudio)
{
ret |= context->output->audio->Command(context, OUTPUT_FASTFORWARD, "audio");
}
}
else
{
ret = cERR_OUTPUT_INTERNAL_ERROR;
}
break;
}
case OUTPUT_REVERSE:
{
if (context && context->playback)
{
if (context->playback->isVideo)
{
ret |= context->output->video->Command(context, OUTPUT_REVERSE, "video");
}
if (context->playback->isAudio)
{
ret |= context->output->audio->Command(context, OUTPUT_REVERSE, "audio");
}
}
else
{
ret = cERR_OUTPUT_INTERNAL_ERROR;
}
break;
}
case OUTPUT_CONTINUE:
{
if (context && context->playback)
{
if (context->playback->isVideo)
{
ret |= context->output->video->Command(context, OUTPUT_CONTINUE, "video");
}
if (context->playback->isAudio)
{
ret |= context->output->audio->Command(context, OUTPUT_CONTINUE, "audio");
}
if (context->playback->isSubtitle)
{
ret |= context->output->subtitle->Command(context, OUTPUT_CONTINUE, "subtitle");
}
}
else
{
ret = cERR_OUTPUT_INTERNAL_ERROR;
}
break;
}
case OUTPUT_AVSYNC:
{
if (context && context->playback)
{
if (context->playback->isVideo && context->playback->isAudio)
{
ret |= context->output->audio->Command(context, OUTPUT_AVSYNC, "audio");
}
}
else
{
ret = cERR_OUTPUT_INTERNAL_ERROR;
}
break;
}
case OUTPUT_CLEAR:
{
if (context && context->playback)
{
if (context->playback->isVideo && (argument == NULL || *(char *) argument == 'v'))
{
ret |= context->output->video->Command(context, OUTPUT_CLEAR, "video");
}
if (context->playback->isAudio && (argument == NULL || *(char *) argument == 'a'))
{
ret |= context->output->audio->Command(context, OUTPUT_CLEAR, "audio");
}
if (context->playback->isSubtitle && (argument == NULL || *(char *) argument == 's'))
{
ret |= context->output->subtitle->Command(context, OUTPUT_CLEAR, "subtitle");
}
}
else
{
ret = cERR_OUTPUT_INTERNAL_ERROR;
}
break;
}
case OUTPUT_PTS:
{
if (context && context->playback)
{
if (context->playback->isVideo)
{
return context->output->video->Command(context, OUTPUT_PTS, argument);
}
if (context->playback->isAudio)
{
return context->output->audio->Command(context, OUTPUT_PTS, argument);
}
}
else
{
ret = cERR_OUTPUT_INTERNAL_ERROR;
}
break;
}
case OUTPUT_SWITCH:
{
if (context && context->playback)
{
if (context->playback->isAudio)
{
return context->output->audio->Command(context, OUTPUT_SWITCH, "audio");
}
if (context->playback->isVideo)
{
return context->output->video->Command(context, OUTPUT_SWITCH, "video");
}
if (context->playback->isSubtitle)
{
return context->output->subtitle->Command(context, OUTPUT_SWITCH, "subtitle");
}
}
else
{
ret = cERR_OUTPUT_INTERNAL_ERROR;
}
break;
}
case OUTPUT_SLOWMOTION:
{
if (context && context->playback)
{
if (context->playback->isVideo)
{
ret |= context->output->video->Command(context, OUTPUT_SLOWMOTION, "video");
}
if (context->playback->isAudio)
{
ret |= context->output->audio->Command(context, OUTPUT_SLOWMOTION, "audio");
}
}
else
{
ret = cERR_OUTPUT_INTERNAL_ERROR;
}
break;
}
case OUTPUT_AUDIOMUTE:
{
if (context && context->playback)
{
if (context->playback->isAudio)
{
ret |= context->output->audio->Command(context, OUTPUT_AUDIOMUTE, (char *) argument);
}
}
else
{
ret = cERR_OUTPUT_INTERNAL_ERROR;
}
break;
}
case OUTPUT_DISCONTINUITY_REVERSE:
{
if (context && context->playback)
{
if (context->playback->isVideo)
{
ret |= context->output->video->Command(context, OUTPUT_DISCONTINUITY_REVERSE, (void *) argument);
}
}
else
{
ret = cERR_OUTPUT_INTERNAL_ERROR;
}
break;
}
case OUTPUT_GET_FRAME_COUNT:
{
if (context && context->playback)
{
if (context->playback->isVideo)
{
return context->output->video->Command(context, OUTPUT_GET_FRAME_COUNT, argument);
}
if (context->playback->isAudio)
{
return context->output->audio->Command(context, OUTPUT_GET_FRAME_COUNT, argument);
}
}
else
{
ret = cERR_OUTPUT_INTERNAL_ERROR;
}
break;
case OUTPUT_GET_PROGRESSIVE:
{
if (context && context->playback)
{
if (context->playback->isVideo)
{
return context->output->video->Command(context, OUTPUT_GET_PROGRESSIVE, (void *) argument);
}
}
else
{
ret = cERR_OUTPUT_INTERNAL_ERROR;
}
break;
}
}
default:
output_err("%s::%s OutputCmd %d not supported!\n", FILENAME, __FUNCTION__, command);
ret = cERR_OUTPUT_INTERNAL_ERROR;
break;
}
output_printf(10, "%s::%s exiting with value %d\n", FILENAME, __FUNCTION__, ret);
return ret;
}
OutputHandler_t OutputHandler =
{
"Output",
NULL, //audio
NULL, //video
NULL, //subtitle
&Command
};

View File

@@ -0,0 +1,332 @@
/*
* Subtitle output to one registered client.
*
*
* 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 <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <unistd.h>
#include <fcntl.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <memory.h>
#include <asm/types.h>
#include <errno.h>
#include "common.h"
#include "output.h"
/* ***************************** */
/* Makros/Constants */
/* ***************************** */
//SULGE DEBUG ENABLED
//#define SAM_WITH_DEBUG
#ifdef SAM_WITH_DEBUG
#define SUBTITLE_DEBUG
#else
#define SUBTITLE_SILENT
#endif
#ifdef SUBTITLE_DEBUG
static short debug_level = 0;
#define subtitle_printf(level, fmt, x...) do { \
if (debug_level >= level) printf("[%s:%s] " fmt, __FILE__, __FUNCTION__, ## x); } while (0)
#else
#define subtitle_printf(level, fmt, x...)
#endif
#ifndef SUBTITLE_SILENT
#define subtitle_err(fmt, x...) do { printf("[%s:%s] " fmt, __FILE__, __FUNCTION__, ## x); } while (0)
#else
#define subtitle_err(fmt, x...)
#endif
/* Error Constants */
#define cERR_SUBTITLE_NO_ERROR 0
#define cERR_SUBTITLE_ERROR -1
static const char FILENAME[] = __FILE__;
/*
Number, Style, Name,, MarginL, MarginR, MarginV, Effect,, Text
1038,0,tdk,,0000,0000,0000,,That's not good.
1037,0,tdk,,0000,0000,0000,,{\i1}Rack them up, rack them up,{\i0}\N{\i1}rack them up.{\i0} [90]
1036,0,tdk,,0000,0000,0000,,Okay, rack them up.
*/
#define PUFFERSIZE 20
/* ***************************** */
/* Types */
/* ***************************** */
/* ***************************** */
/* Varaibles */
/* ***************************** */
static pthread_mutex_t mutex;
static int isSubtitleOpened = 0;
/* ***************************** */
/* Prototypes */
/* ***************************** */
/* ***************************** */
/* MISC Functions */
/* ***************************** */
static void getMutex(int line)
{
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)
{
pthread_mutex_unlock(&mutex);
subtitle_printf(100, "%d released mutex\n", line);
}
/* ***************************** */
/* Functions */
/* ***************************** */
static char *ass_get_text(char *str)
{
// Events are stored in the Block in this order:
// ReadOrder, Layer, Style, Name, MarginL, MarginR, MarginV, Effect, Text
// 91,0,Default,,0,0,0,,maar hij smaakt vast tof.
int i = 0;
char *p_str = str;
while (i < 8 && *p_str != '\0')
{
if (*p_str == ',')
i++;
p_str++;
}
// standardize hard break: '\N' -> '\n'
// http://docs.aegisub.org/3.2/ASS_Tags/
char *p_newline = NULL;
while ((p_newline = strstr(p_str, "\\N")) != NULL)
* (p_newline + 1) = 'n';
return p_str;
}
static char *json_string_escape(char *str)
{
static char tmp[2048];
char *ptr1 = tmp;
char *ptr2 = str;
while (*ptr2 != '\0')
{
switch (*ptr2)
{
case '"':
*ptr1++ = '\\';
*ptr1++ = '\"';
break;
case '\\':
*ptr1++ = '\\';
*ptr1++ = '\\';
break;
case '\b':
*ptr1++ = '\\';
*ptr1++ = 'b';
break;
case '\f':
*ptr1++ = '\\';
*ptr1++ = 'f';
break;
case '\n':
*ptr1++ = '\\';
*ptr1++ = 'n';
break;
case '\r':
*ptr1++ = '\\';
*ptr1++ = 'r';
break;
case '\t':
*ptr1++ = '\\';
*ptr1++ = 't';
break;
default:
*ptr1++ = *ptr2;
break;
}
++ptr2;
}
*ptr1 = '\0';
return tmp;
}
static int Flush()
{
fprintf(stderr, "{\"s_f\":{\"r\":0}}\n");
return cERR_SUBTITLE_NO_ERROR;
}
static int Write(void *_context, void *data)
{
Context_t *context = (Context_t *)_context;
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 != 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));
}
else if (!strncmp("S_TEXT/ASS", Encoding, 10))
{
fprintf(stderr, "{\"s_a\":{\"id\":%d,\"s\":%lld,\"e\":%lld,\"t\":\"%s\"}}\n", out->trackId, out->pts / 90, out->pts / 90 + out->durationMS, ass_get_text((char *)out->data));
}
else
{
subtitle_err("unknown encoding %s\n", Encoding);
return cERR_SUBTITLE_ERROR;
}
subtitle_printf(10, "<\n");
return cERR_SUBTITLE_NO_ERROR;
}
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;
}
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(void *_context, OutputCmd_t command, void *argument)
{
Context_t *context = (Context_t *) _context;
int ret = cERR_SUBTITLE_NO_ERROR;
subtitle_printf(50, "%d\n", command);
switch (command)
{
case OUTPUT_OPEN:
{
ret = subtitle_Open(context);
break;
}
case OUTPUT_CLOSE:
{
ret = subtitle_Close(context);
break;
}
case OUTPUT_PLAY:
{
break;
}
case OUTPUT_STOP:
{
break;
}
case OUTPUT_SWITCH:
{
ret = Flush();
break;
}
case OUTPUT_FLUSH:
{
ret = Flush();
break;
}
case OUTPUT_CLEAR:
{
ret = Flush();
break;
}
case OUTPUT_PAUSE:
{
subtitle_err("Subtitle Pause not implemented\n");
ret = cERR_SUBTITLE_ERROR;
break;
}
case OUTPUT_CONTINUE:
{
subtitle_err("Subtitle Continue not implemented\n");
ret = cERR_SUBTITLE_ERROR;
break;
}
default:
subtitle_err("OutputCmd %d not supported!\n", command);
ret = cERR_SUBTITLE_ERROR;
break;
}
subtitle_printf(50, "exiting with value %d\n", ret);
return ret;
}
static char *SubtitleCapabilitis[] = { "subtitle", NULL };
Output_t SubtitleOutput =
{
"Subtitle",
&Command,
&Write,
SubtitleCapabilitis
};

View File

@@ -0,0 +1,123 @@
/*
* LinuxDVB Output handling.
*
* 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 <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <unistd.h>
#include <fcntl.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/ioctl.h>
#include <linux/dvb/video.h>
#include <linux/dvb/audio.h>
#include <memory.h>
#include <asm/types.h>
#include <pthread.h>
#include <errno.h>
#include "stm_ioctls.h"
#include "bcm_ioctls.h"
#include "common.h"
#include "output.h"
#include "debug.h"
#include "misc.h"
/* ***************************** */
/* Makros/Constants */
/* ***************************** */
/* ***************************** */
/* Types */
/* ***************************** */
/* ***************************** */
/* Varaibles */
/* ***************************** */
/* ***************************** */
/* Prototypes */
/* ***************************** */
/* ***************************** */
/* MISC Functions */
/* ***************************** */
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 */
bit_buf = (bit_buf << length) | code;
bit_left -= length;
}
else
{
/* doesn't fit */
bit_buf <<= bit_left;
bit_buf |= code >> (length - bit_left);
ld->Ptr[0] = (char)(bit_buf >> 24);
ld->Ptr[1] = (char)(bit_buf >> 16);
ld->Ptr[2] = (char)(bit_buf >> 8);
ld->Ptr[3] = (char)bit_buf;
ld->Ptr += 4;
length -= bit_left;
bit_buf = code & ((1 << length) - 1);
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;
}
void FlushBits(BitPacker_t *ld)
{
ld->BitBuffer <<= ld->Remaining;
while (ld->Remaining < 32)
{
#ifdef DEBUG_PUTBITS
if (ld->debug)
dprintf("flushing 0x%2.2x\n", ld->BitBuffer >> 24);
#endif /* DEBUG_PUTBITS */
*ld->Ptr++ = ld->BitBuffer >> 24;
ld->BitBuffer <<= 8;
ld->Remaining += 8;
}
ld->Remaining = 32;
ld->BitBuffer = 0;
}

View File

@@ -0,0 +1,163 @@
/*
* linuxdvb output/writer handling.
*
* konfetti 2010 based on linuxdvb.c code from libeplayer2
*
* 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 <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <unistd.h>
#include <fcntl.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/ioctl.h>
#include <linux/dvb/video.h>
#include <linux/dvb/audio.h>
#include <memory.h>
#include <asm/types.h>
#include <pthread.h>
#include <errno.h>
#include "stm_ioctls.h"
#include "bcm_ioctls.h"
#include "common.h"
#include "output.h"
#include "debug.h"
#include "misc.h"
#include "pes.h"
#include "writer.h"
/* ***************************** */
/* Makros/Constants */
/* ***************************** */
/* ***************************** */
/* Types */
/* ***************************** */
/* ***************************** */
/* Varaibles */
/* ***************************** */
/* ***************************** */
/* Prototypes */
/* ***************************** */
/* ***************************** */
/* Functions */
/* ***************************** */
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
PutBits(&ld2, stream_id, 8); // Stream_id = Audio Stream
//4
if (-1 == size)
{
PutBits(&ld2, 0x0, 16);
}
else
{
PutBits(&ld2, size + 3 + (pts != INVALID_PTS_VALUE ? 5 : 0) + (pic_start_code ? (5) : 0), 16); // PES_packet_length
}
//6 = 4+2
PutBits(&ld2, 0x2, 2); // 10
PutBits(&ld2, 0x0, 2); // PES_Scrambling_control
PutBits(&ld2, 0x0, 1); // PES_Priority
PutBits(&ld2, 0x0, 1); // data_alignment_indicator
PutBits(&ld2, 0x0, 1); // Copyright
PutBits(&ld2, 0x0, 1); // Original or Copy
//7 = 6+1
if (pts != INVALID_PTS_VALUE)
{
PutBits(&ld2, 0x2, 2);
}
else
{
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
PutBits(&ld2, 0x0, 1); // additional_copy_ingo_flag
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);
PutBits(&ld2, (pts >> 30) & 0x7, 3);
PutBits(&ld2, 0x1, 1);
PutBits(&ld2, (pts >> 15) & 0x7fff, 15);
PutBits(&ld2, 0x1, 1);
PutBits(&ld2, pts & 0x7fff, 15);
PutBits(&ld2, 0x1, 1);
}
//14 = 9+5
if (pic_start_code)
{
PutBits(&ld2, 0x0, 8);
PutBits(&ld2, 0x0, 8);
PutBits(&ld2, 0x1, 8); // Start Code
PutBits(&ld2, pic_start_code & 0xff, 8); // 00, for picture start
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);
}

View File

@@ -0,0 +1,374 @@
/*
* linuxdvb output/writer handling.
*
* konfetti 2010 based on linuxdvb.c code from libeplayer2
*
* 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 <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <unistd.h>
#include <fcntl.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/ioctl.h>
#include <linux/dvb/video.h>
#include <linux/dvb/audio.h>
#include <memory.h>
#include <asm/types.h>
#include <pthread.h>
#include <errno.h>
#include <sys/uio.h>
#include <libavutil/intreadwrite.h>
#include "ffmpeg/latmenc.h"
#include "stm_ioctls.h"
#include "bcm_ioctls.h"
#include "common.h"
#include "output.h"
#include "debug.h"
#include "misc.h"
#include "pes.h"
#include "writer.h"
#include "aac.h"
/* ***************************** */
/* Makros/Constants */
/* ***************************** */
//#define SAM_WITH_DEBUG
#ifdef SAM_WITH_DEBUG
#define AAC_DEBUG
#else
#define AAC_SILENT
#endif
#ifdef AAC_DEBUG
static short debug_level = 0;
#define aac_printf(level, fmt, x...) do { \
if (debug_level >= level) printf("[%s:%s] " fmt, __FILE__, __FUNCTION__, ## x); } while (0)
#else
#define aac_printf(level, fmt, x...)
#endif
#ifndef AAC_SILENT
#define aac_err(fmt, x...) do { printf("[%s:%s] " fmt, __FILE__, __FUNCTION__, ## x); } while (0)
#else
#define aac_err(fmt, x...)
#endif
/* ***************************** */
/* Types */
/* ***************************** */
/* ***************************** */
/* Varaibles */
/* ***************************** */
/// ** AAC ADTS format **
///
/// AAAAAAAA AAAABCCD EEFFFFGH HHIJKLMM
/// MMMMMMMM MMMNNNNN NNNNNNOO ........
///
/// Sign Length Position Description
///
/// A 12 (31-20) Sync code
/// B 1 (19) ID
/// C 2 (18-17) layer
/// D 1 (16) protect absent
/// E 2 (15-14) profile
/// F 4 (13-10) sample freq index
/// G 1 (9) private
/// H 3 (8-6) channel config
/// I 1 (5) original/copy
/// J 1 (4) home
/// K 1 (3) copyright id
/// L 1 (2) copyright start
/// M 13 (1-0,31-21) frame length
/// N 11 (20-10) adts buffer fullness
/// O 2 (9-8) num of raw data blocks in frame
/*
LC: Audio: aac, 44100 Hz, stereo, s16, 192 kb/ ->ff f1 50 80 00 1f fc
HE: Audio: aac, 48000 Hz, stereo, s16, 77 kb/s ->ff f1 4c 80 00 1f fc
*/
/*
ADIF = basic format called Audio Data Interchange Format (ADIF)
consisting of a single header followed by the raw AAC audio data blocks
ADTS = streaming format called Audio Data Transport Stream (ADTS)
consisting of a series of frames, each frame having a header followed by the AAC audio data
LOAS = Low Overhead Audio Stream (LOAS), a self-synchronizing streaming format
*/
static unsigned char DefaultAACHeader[] =
{
0xff,
0xf1,
/*0x00, 0x00*/0x50, //((Profile & 0x03) << 6) | (SampleIndex << 2) | ((Channels >> 2) & 0x01);s
0x80, //(Channels & 0x03) << 6;
0x00,
0x1f,
0xfc
};
LATMContext *pLATMCtx = NULL;
/* ***************************** */
/* Prototypes */
/* ***************************** */
/* ***************************** */
/* MISC Functions */
/* ***************************** */
static int reset()
{
if (pLATMCtx)
{
free(pLATMCtx);
pLATMCtx = NULL;
}
return 0;
}
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
{
if (0xFF != call->data[0] || 0xF0 != (0xF0 & call->data[1]))
{
aac_err("parsing Data with missing syncword. ignoring...\n");
return 0;
}
}
else // check LOAS header
{
if (!(call->len > 2 && call->data[0] == 0x56 && (call->data[1] >> 4) == 0xe &&
(AV_RB16(call->data + 1) & 0x1FFF) + 3 == call->len))
{
aac_err("parsing Data with wrong latm header. ignoring...\n");
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;
iov[1].iov_base = call->data;
iov[1].iov_len = call->len;
return writev_with_retry(call->fd, iov, 2);
}
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)
{
aac_printf(10, "private_data = NULL\n");
memcpy(pExtraData, DefaultAACHeader, AAC_HEADER_LENGTH);
}
else
{
memcpy(pExtraData, call->private_data, AAC_HEADER_LENGTH);
}
pExtraData[3] &= 0xC0;
/* frame size over last 2 bits */
pExtraData[3] |= (PacketLength & 0x1800) >> 11;
/* frame size continued over full byte */
pExtraData[4] = (PacketLength & 0x1FF8) >> 3;
/* frame size continued first 3 bits */
pExtraData[5] = (PacketLength & 7) << 5;
/* buffer fullness(0x7FF for VBR) over 5 last bits */
pExtraData[5] |= 0x1F;
/* 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 writev_with_retry(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));
memset(pLATMCtx, 0x00, sizeof(LATMContext));
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)
{
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;
}
ret = latmenc_write_packet(pLATMCtx, call->data, call->len, call->private_data, call->private_size);
if (ret)
{
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_with_retry(call->fd, iov, 3);
}
/* ***************************** */
/* Writer Definition */
/* ***************************** */
static WriterCaps_t caps =
{
"aac",
eAudio,
"A_AAC",
-1,
AUDIOTYPE_AAC_PLUS,
-1
};
struct Writer_s WriterAudioAAC =
{
&reset,
&writeDataADTS,
NULL,
&caps
};
static WriterCaps_t caps_aac_latm =
{
"aac",
eAudio,
"A_AAC_LATM",
-1,
AUDIOTYPE_AAC_HE, // it is some misunderstanding, this should be AUDIOTYPE_AAC_LATM
-1
};
struct Writer_s WriterAudioAACLATM =
{
&reset,
&writeDataLATM,
NULL,
&caps_aac_latm
};
static WriterCaps_t caps_aacplus =
{
"aac",
eAudio,
"A_AAC_PLUS",
-1,
AUDIOTYPE_AAC_PLUS,
-1
};
struct Writer_s WriterAudioAACPLUS =
{
&reset,
&writeDataADTS,
NULL,
&caps_aacplus
};

View File

@@ -0,0 +1,170 @@
/*
* linuxdvb output/writer handling.
*
* konfetti 2010 based on linuxdvb.c code from libeplayer2
*
* 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 <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <unistd.h>
#include <fcntl.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/ioctl.h>
#include <sys/uio.h>
#include <linux/dvb/video.h>
#include <linux/dvb/audio.h>
#include <memory.h>
#include <asm/types.h>
#include <pthread.h>
#include <errno.h>
#include "stm_ioctls.h"
#include "bcm_ioctls.h"
#include "common.h"
#include "output.h"
#include "debug.h"
#include "misc.h"
#include "pes.h"
#include "writer.h"
/* ***************************** */
/* Makros/Constants */
/* ***************************** */
#define AC3_HEADER_LENGTH 7
#define AC3_DEBUG
#ifdef AC3_DEBUG
static short debug_level = 0;
#define ac3_printf(level, fmt, x...) do { \
if (debug_level >= level) printf("[%s:%s] " fmt, __FILE__, __FUNCTION__, ## x); } while (0)
#else
#define ac3_printf(level, fmt, x...)
#endif
#ifndef AC3_SILENT
#define ac3_err(fmt, x...) do { printf("[%s:%s] " fmt, __FILE__, __FUNCTION__, ## x); } while (0)
#else
#define ac3_err(fmt, x...)
#endif
/* ***************************** */
/* Types */
/* ***************************** */
/* ***************************** */
/* Varaibles */
/* ***************************** */
unsigned char AC3_SYNC_HEADER[] = {0x80, 0x01, 0x00, 0x01};
/* ***************************** */
/* Prototypes */
/* ***************************** */
/* ***************************** */
/* MISC Functions */
/* ***************************** */
static int reset()
{
return 0;
}
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[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 writev_with_retry(call->fd, iov, 2);
}
/* ***************************** */
/* Writer Definition */
/* ***************************** */
static WriterCaps_t caps_ac3 =
{
"ac3",
eAudio,
"A_AC3",
AUDIO_ENCODING_AC3,
AUDIOTYPE_AC3,
-1
};
struct Writer_s WriterAudioAC3 =
{
&reset,
&writeData,
NULL,
&caps_ac3
};
static WriterCaps_t caps_eac3 =
{
"ac3",
eAudio,
"A_EAC3",
AUDIO_ENCODING_AC3,
AUDIOTYPE_AC3_PLUS,
-1
};
struct Writer_s WriterAudioEAC3 =
{
&reset,
&writeData,
NULL,
&caps_eac3
};

View File

@@ -0,0 +1,176 @@
/*
* linuxdvb output/writer handling.
*
* konfetti 2010 based on linuxdvb.c code from libeplayer2
*
* 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 <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <unistd.h>
#include <fcntl.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/ioctl.h>
#include <sys/uio.h>
#include <linux/dvb/video.h>
#include <linux/dvb/audio.h>
#include <memory.h>
#include <asm/types.h>
#include <pthread.h>
#include <errno.h>
#include "stm_ioctls.h"
#include "bcm_ioctls.h"
#include "common.h"
#include "output.h"
#include "debug.h"
#include "misc.h"
#include "pes.h"
#include "writer.h"
/* ***************************** */
/* Makros/Constants */
/* ***************************** */
#define SAM_WITH_DEBUG
#ifdef SAM_WITH_DEBUG
#define AMR_DEBUG
#else
#define AMR_SILENT
#endif
#ifdef AMR_DEBUG
static short debug_level = 0;
#define amr_printf(level, fmt, x...) do { \
if (debug_level >= level) printf("[%s:%s] " fmt, __FILE__, __FUNCTION__, ## x); } while (0)
#else
#define amr_printf(level, fmt, x...)
#endif
#ifndef AMR_SILENT
#define amr_err(fmt, x...) do { printf("[%s:%s] " fmt, __FILE__, __FUNCTION__, ## x); } while (0)
#else
#define amr_err(fmt, x...)
#endif
/* ***************************** */
/* Types */
/* ***************************** */
/* ***************************** */
/* Varaibles */
/* ***************************** */
/* ***************************** */
/* Prototypes */
/* ***************************** */
/* ***************************** */
/* MISC Functions */
/* ***************************** */
static int reset()
{
return 0;
}
static int writeData(void *_call)
{
WriterAVCallData_t *call = (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)
{
amr_err("wrong private_data. ignoring ...\n");
hasCodecData = 1;
}
size_t payload_len = call->len;
if (hasCodecData)
{
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};
memcpy(&PesHeader[headerSize], tmp, 9);
//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 = writev_with_retry(call->fd, iov, 2);
amr_printf(10, "amr_Write-< len=%d\n", len);
return len;
}
/* ***************************** */
/* Writer Definition */
/* ***************************** */
static WriterCaps_t caps_amr =
{
"amr",
eAudio,
"A_AMR",
-1,
AUDIOTYPE_AMR,
-1
};
struct Writer_s WriterAudioAMR =
{
&reset,
&writeData,
NULL,
&caps_amr
};

View File

@@ -0,0 +1,196 @@
/*
* linuxdvb output/writer handling.
*
* konfetti 2010 based on linuxdvb.c code from libeplayer2
*
* 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 <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <unistd.h>
#include <fcntl.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/ioctl.h>
#include <sys/uio.h>
#include <linux/dvb/video.h>
#include <linux/dvb/audio.h>
#include <memory.h>
#include <asm/types.h>
#include <pthread.h>
#include <errno.h>
#include "stm_ioctls.h"
#include "bcm_ioctls.h"
#include "common.h"
#include "output.h"
#include "debug.h"
#include "misc.h"
#include "pes.h"
#include "writer.h"
/* ***************************** */
/* Makros/Constants */
/* ***************************** */
#define B_GET_BITS(w,e,b) (((w)>>(b))&(((unsigned)(-1))>>((sizeof(unsigned))*8-(e+1-b))))
#define B_SET_BITS(name,v,e,b) (((unsigned)(v))<<(b))
#ifdef SAM_WITH_DEBUG
#define DIVX_DEBUG
#else
#define DIVX_SILENT
#endif
#ifdef DIVX_DEBUG
static short debug_level = 0;
#define divx_printf(level, fmt, x...) do { \
if (debug_level >= level) printf("[%s:%s] " fmt, __FILE__, __FUNCTION__, ## x); } while (0)
#else
#define divx_printf(level, fmt, x...)
#endif
#ifndef DIVX_SILENT
#define divx_err(fmt, x...) do { printf("[%s:%s] " fmt, __FILE__, __FUNCTION__, ## x); } while (0)
#else
#define divx_err(fmt, x...)
#endif
/* ***************************** */
/* Types */
/* ***************************** */
/* ***************************** */
/* Varaibles */
/* ***************************** */
static uint8_t initialHeader = 1;
static uint8_t brcm_divx311_sequence_header[] =
{
0x00, 0x00, 0x01, 0xE0, 0x00, 0x34, 0x80, 0x80, // PES HEADER
0x05, 0x2F, 0xFF, 0xFF, 0xFF, 0xFF,
0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x20, /* 0 .. 7 */
0x08, 0xC8, 0x0D, 0x40, 0x00, 0x53, 0x88, 0x40, /* 8 .. 15 */
0x0C, 0x40, 0x01, 0x90, 0x00, 0x97, 0x53, 0x0A, /* 16 .. 24 */
0x00, 0x00, 0x00, 0x00,
0x30, 0x7F, 0x00, 0x00, 0x01, 0xB2, 0x44, 0x69, /* 0 .. 7 */
0x76, 0x58, 0x33, 0x31, 0x31, 0x41, 0x4E, 0x44 /* 8 .. 15 */
};
/* ***************************** */
/* Prototypes */
/* ***************************** */
/* ***************************** */
/* MISC Functions */
/* ***************************** */
static int reset()
{
initialHeader = 1;
return 0;
}
static int writeData(void *_call)
{
WriterAVCallData_t *call = (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;
uint8_t *data = brcm_divx311_sequence_header;
int32_t height = call->Height;
int32_t width = call->Width;
data += 38;
data[0] = B_GET_BITS(width, 11, 4);
data[1] = B_SET_BITS("width [3..0]", B_GET_BITS(width, 3, 0), 7, 4) |
B_SET_BITS("'10'", 0x02, 3, 2) |
B_SET_BITS("height [11..10]", B_GET_BITS(height, 11, 10), 1, 0);
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);
memcpy(PesHeader + headerSize, "\x00\x00\x01\xb6", 4);
headerSize += 4;
}
else
{
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 = writev_with_retry(call->fd, iov, ic);
divx_printf(10, "xvid_Write < len=%d\n", len);
return len;
}
/* ***************************** */
/* Writer Definition */
/* ***************************** */
static WriterCaps_t divix3_caps =
{
"divix3",
eVideo,
"V_DIVX3",
VIDEO_ENCODING_MPEG4P2,
STREAMTYPE_DIVX311,
-1
};
struct Writer_s WriterVideoDIVX3 =
{
&reset,
&writeData,
NULL,
&divix3_caps
};

View File

@@ -0,0 +1,178 @@
/*
* linuxdvb output/writer handling.
*
* konfetti 2010 based on linuxdvb.c code from libeplayer2
*
* 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 <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <unistd.h>
#include <fcntl.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/ioctl.h>
#include <sys/uio.h>
#include <linux/dvb/video.h>
#include <linux/dvb/audio.h>
#include <memory.h>
#include <asm/types.h>
#include <pthread.h>
#include <errno.h>
#include "stm_ioctls.h"
#include "bcm_ioctls.h"
#include "common.h"
#include "output.h"
#include "debug.h"
#include "misc.h"
#include "pes.h"
#include "writer.h"
/* ***************************** */
/* Makros/Constants */
/* ***************************** */
#define PES_AUDIO_PRIVATE_HEADER_SIZE 16 // consider maximum private header size.
#define PES_AUDIO_HEADER_SIZE (32 + PES_AUDIO_PRIVATE_HEADER_SIZE)
#define PES_AUDIO_PACKET_SIZE 2028
#define SPDIF_AUDIO_PACKET_SIZE (1024 * sizeof(unsigned int) * 2) // stereo 32bit samples.
#ifdef SAM_WITH_DEBUG
#define DTS_DEBUG
#else
#define DTS_SILENT
#endif
#ifdef DTS_DEBUG
static int16_t debug_level = 0;
#define dts_printf(level, fmt, x...) do { \
if (debug_level >= level) printf("[%s:%s] " fmt, __FILE__, __FUNCTION__, ## x); } while (0)
#else
#define dts_printf(level, fmt, x...)
#endif
#ifndef DTS_SILENT
#define dts_err(fmt, x...) do { printf("[%s:%s] " fmt, __FILE__, __FUNCTION__, ## x); } while (0)
#else
#define dts_err(fmt, x...)
#endif
/* ***************************** */
/* Types */
/* ***************************** */
/* ***************************** */
/* Varaibles */
/* ***************************** */
/* ***************************** */
/* Prototypes */
/* ***************************** */
/* ***************************** */
/* MISC Functions */
/* ***************************** */
static int32_t reset()
{
return 0;
}
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)
{
// check for DTS-HD
if (!strcmp((char *)(Data + pos), "\x64\x58\x20\x25"))
{
Size = pos;
break;
}
++pos;
}
#endif
// #define DO_BYTESWAP
#ifdef DO_BYTESWAP
/* 16-bit byte swap all data before injecting it */
for (i = 0; i < Size; i += 2)
{
uint8_t Tmp = Data[i];
Data[i] = Data[i + 1];
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_with_retry(call->fd, iov, 2);
dts_printf(10, "< len %d\n", len);
return len;
}
/* ***************************** */
/* Writer Definition */
/* ***************************** */
static WriterCaps_t caps =
{
"dts",
eAudio,
"A_DTS",
AUDIO_ENCODING_DTS,
AUDIOTYPE_DTS,
-1
};
struct Writer_s WriterAudioDTS =
{
&reset,
&writeData,
NULL,
&caps
};

View File

@@ -0,0 +1,171 @@
/*
* linuxdvb output/writer handling.
*
* crow 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 <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <unistd.h>
#include <fcntl.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/ioctl.h>
#include <linux/dvb/video.h>
#include <linux/dvb/audio.h>
#include <memory.h>
#include <asm/types.h>
#include <pthread.h>
#include <errno.h>
#include <sys/uio.h>
#include "stm_ioctls.h"
#include "bcm_ioctls.h"
#include "common.h"
#include "output.h"
#include "debug.h"
#include "misc.h"
#include "pes.h"
#include "writer.h"
/* ***************************** */
/* Makros/Constants */
/* ***************************** */
//#define H263_DEBUG
#ifdef H263_DEBUG
static short debug_level = 0;
#define h263_printf(level, fmt, x...) do { \
if (debug_level >= level) printf("[%s:%s] " fmt, __FILE__, __FUNCTION__, ## x); } while (0)
#else
#define h263_printf(level, fmt, x...)
#endif
#ifndef H263_SILENT
#define h263_err(fmt, x...) do { printf("[%s:%s] " fmt, __FILE__, __FUNCTION__, ## x); } while (0)
#else
#define h263_err(fmt, x...)
#endif
/* ***************************** */
/* Types */
/* ***************************** */
/* ***************************** */
/* Varaibles */
/* ***************************** */
/* ***************************** */
/* Prototypes */
/* ***************************** */
/* ***************************** */
/* MISC Functions */
/* ***************************** */
static int32_t reset()
{
return 0;
}
static int32_t writeData(void *_call)
{
WriterAVCallData_t *call = (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 = writev_with_retry(call->fd, iov, 2);
h263_printf(10, "< len %d\n", len);
return len;
}
/* ***************************** */
/* Writer Definition */
/* ***************************** */
static WriterCaps_t caps_h263 =
{
"h263",
eVideo,
"V_H263",
VIDEO_ENCODING_H263,
STREAMTYPE_H263,
CT_MPEG4_PART2
};
struct Writer_s WriterVideoH263 =
{
&reset,
&writeData,
NULL,
&caps_h263
};
static WriterCaps_t caps_flv =
{
"FLV",
eVideo,
"V_FLV",
VIDEO_ENCODING_FLV1,
STREAMTYPE_H263,
CT_MPEG4_PART2
};
struct Writer_s WriterVideoFLV =
{
&reset,
&writeData,
NULL,
&caps_flv
};

View File

@@ -0,0 +1,441 @@
/*
* linuxdvb output/writer handling.
*
* konfetti 2010 based on linuxdvb.c code from libeplayer2
*
* 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 <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <unistd.h>
#include <fcntl.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/ioctl.h>
#include <sys/uio.h>
#include <linux/dvb/video.h>
#include <linux/dvb/audio.h>
#include <memory.h>
#include <asm/types.h>
#include <pthread.h>
#include <errno.h>
#include <assert.h>
#include <stdint.h>
#include <poll.h>
#include "stm_ioctls.h"
#include "bcm_ioctls.h"
#include "common.h"
#include "output.h"
#include "debug.h"
#include "misc.h"
#include "pes.h"
#include "writer.h"
/* ***************************** */
/* Makros/Constants */
/* ***************************** */
//#define H264_DEBUG
#ifdef H264_DEBUG
static short debug_level = 0;
#define h264_printf(level, fmt, x...) do { \
if (debug_level >= level) printf("[%s:%s] " fmt, __FILE__, __FUNCTION__, ## x); } while (0)
#else
#define h264_printf(level, fmt, x...)
#endif
#ifndef H264_SILENT
#define h264_err(fmt, x...) do { printf("[%s:%s] " fmt, __FILE__, __FUNCTION__, ## x); } while (0)
#else
#define h264_err(fmt, x...)
#endif
#define IOVEC_SIZE 128
/* ***************************** */
/* Types */
/* ***************************** */
/* ***************************** */
/* Varaibles */
/* ***************************** */
static unsigned char Head[] = {0, 0, 0, 1};
static int initialHeader = 1;
static unsigned int NalLengthBytes = 1;
static unsigned char *CodecData = NULL;
static unsigned int CodecDataLen = 0;
static int avc3 = 0;
/* ***************************** */
/* Prototypes */
/* ***************************** */
/* ***************************** */
/* MISC Functions */
/* ***************************** */
// Please see: https://bugzilla.mozilla.org/show_bug.cgi?id=1105771
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");
return -1;
}
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");
return -1;
}
memcpy(&(pps[ppsIdx]), d + 4, nalLen);
ppsIdx += nalLen;
numPps += 1;
h264_printf(10, "PPS len[%u]...\n", nalLen);
}
d += 4 + nalLen;
}
uint32_t idx = 0;
*ppExtraData = malloc(7 + spsIdx + ppsIdx);
aExtraData = *ppExtraData;
aExtraData[idx++] = 0x1; // version
aExtraData[idx++] = sps[3]; // profile
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;
}
static int32_t PreparCodecData(unsigned char *data, unsigned int cd_len, unsigned int *NalLength)
{
h264_printf(10, "H264 check codec data..!\n");
int32_t ret = -100;
if (data)
{
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)
{
unsigned short len = (data[6] << 8) | data[7];
if (cd_len >= (len + 8))
{
unsigned int i = 0;
uint8_t profile_num[] = { 66, 77, 88, 100 };
uint8_t profile_cmp[2] = { 0x67, 0x00 };
const char *profile_str[] = { "baseline", "main", "extended", "high" };
memcpy(tmp, Head, sizeof(Head));
tmp_len += 4;
memcpy(tmp + tmp_len, data + 8, len);
for (i = 0; i < 4; ++i)
{
profile_cmp[1] = profile_num[i];
if (!memcmp(tmp + tmp_len, profile_cmp, 2))
{
uint8_t level_org = tmp[tmp_len + 3];
if (level_org > 0x29)
{
h264_printf(10, "H264 %s profile@%d.%d patched down to 4.1!", profile_str[i], level_org / 10, level_org % 10);
tmp[tmp_len + 3] = 0x29; // level 4.1
}
else
{
h264_printf(10, "H264 %s profile@%d.%d", profile_str[i], level_org / 10, level_org % 10);
}
break;
}
}
tmp_len += len;
cd_pos = 8 + len;
if (cd_len > (cd_pos + 2))
{
len = (data[cd_pos + 1] << 8) | data[cd_pos + 2];
cd_pos += 3;
if (cd_len >= (cd_pos + len))
{
memcpy(tmp + tmp_len, "\x00\x00\x00\x01", 4);
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;
}
else
{
h264_printf(10, "codec_data too short(4)");
ret = -4;
}
}
else
{
h264_printf(10, "codec_data too short(3)");
ret = -3;
}
}
else
{
h264_printf(10, "codec_data too short(2)");
ret = -2;
}
}
else if (cd_len <= 7)
{
h264_printf(10, "codec_data too short(1)");
ret = -1;
}
else
{
h264_printf(10, "wrong avcC version %d!", data[0]);
}
}
else
{
*NalLength = 0;
}
return ret;
}
static int reset()
{
initialHeader = 1;
avc3 = 0;
return 0;
}
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];
h264_printf(20, "\n");
if (call == NULL)
{
h264_err("call data is NULL...\n");
return 0;
}
TimeDelta = call->FrameRate;
TimeScale = call->FrameScale;
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) ||
(call->data[0] == 0xff && call->data[1] == 0xff && call->data[2] == 0xff && call->data[3] == 0xff))))
{
uint32_t PacketLength = 0;
uint32_t FakeStartCode = (call->Version << 8) | PES_VERSION_FAKE_START_CODE;
iov[ic++].iov_base = PesHeader;
initialHeader = 0;
//if (initialHeader) // some rtsp streams can update codec data at runtime
{
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 writev_with_retry(call->fd, iov, ic);
}
else if (!call->private_data || call->private_size < 7 || 1 != call->private_data[0])
{
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)
{
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;
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);
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);
PacketLength += iov[0].iov_len;
if (PacketLength != len)
{
h264_err("<<<< not all data have been written [%d/%d]\n", len, PacketLength);
}
}
h264_printf(10, "< len %d\n", len);
return len;
}
static int writeReverseData(void *_call)
{
WriterAVCallData_t *call = (WriterAVCallData_t *) _call;
return 0;
}
/* ***************************** */
/* Writer Definition */
/* ***************************** */
static WriterCaps_t caps =
{
"h264",
eVideo,
"V_MPEG4/ISO/AVC",
VIDEO_ENCODING_H264,
STREAMTYPE_MPEG4_H264,
CT_H264
};
struct Writer_s WriterVideoH264 =
{
&reset,
&writeData,
&writeReverseData,
&caps
};

View File

@@ -0,0 +1,310 @@
/*
* linuxdvb output/writer handling.
*
* konfetti 2010 based on linuxdvb.c code from libeplayer2
*
* 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 <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <unistd.h>
#include <fcntl.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/ioctl.h>
#include <sys/uio.h>
#include <linux/dvb/video.h>
#include <linux/dvb/audio.h>
#include <memory.h>
#include <asm/types.h>
#include <pthread.h>
#include <errno.h>
#include <assert.h>
#include <stdint.h>
#include <poll.h>
#include "stm_ioctls.h"
#include "bcm_ioctls.h"
#include "common.h"
#include "output.h"
#include "debug.h"
#include "misc.h"
#include "pes.h"
#include "writer.h"
/* ***************************** */
/* Makros/Constants */
/* ***************************** */
//#define H265_DEBUG
#ifdef H265_DEBUG
static short debug_level = 10;
#define h264_printf(level, fmt, x...) do { \
if (debug_level >= level) printf("[%s:%s] " fmt, __FILE__, __FUNCTION__, ## x); } while (0)
#else
#define h264_printf(level, fmt, x...)
#endif
#ifndef H265_SILENT
#define h264_err(fmt, x...) do { printf("[%s:%s] " fmt, __FILE__, __FUNCTION__, ## x); } while (0)
#else
#define h264_err(fmt, x...)
#endif
#define IOVEC_SIZE 128
/* ***************************** */
/* Types */
/* ***************************** */
/* ***************************** */
/* Varaibles */
/* ***************************** */
static unsigned char Head[] = {0, 0, 0, 1};
static int initialHeader = 1;
static unsigned int NalLengthBytes = 1;
static unsigned char *CodecData = NULL;
static unsigned int CodecDataLen = 0;
/* ***************************** */
/* Prototypes */
/* ***************************** */
/* ***************************** */
/* MISC Functions */
/* ***************************** */
static int32_t PreparCodecData(unsigned char *data, unsigned int cd_len, unsigned int *NalLength)
{
h264_printf(10, "H265 check codec data..!\n");
int32_t ret = -100;
if (data)
{
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)
{
int i;
if (data[0] != 0)
{
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];
int pos = 23;
for (i = 0; i < num_param_sets; i++)
{
int j;
if (pos + 3 > cd_len)
{
h264_printf(10, "Buffer underrun in extra header (%d >= %u)", pos + 3, cd_len);
break;
}
// ignore flags + NAL type (1 byte)
int nal_count = data[pos + 1] << 8 | data[pos + 2];
pos += 3;
for (j = 0; j < nal_count; j++)
{
if (pos + 2 > cd_len)
{
h264_printf(10, "Buffer underrun in extra nal header (%d >= %u)", pos + 2, cd_len);
break;
}
int nal_size = data[pos] << 8 | data[pos + 1];
pos += 2;
if (pos + nal_size > cd_len)
{
h264_printf(10, "Buffer underrun in extra nal (%d >= %u)", pos + 2 + nal_size, cd_len);
break;
}
memcpy(tmp + tmp_len, "\x00\x00\x00\x01", 4);
tmp_len += 4;
memcpy(tmp + tmp_len, data + pos, nal_size);
tmp_len += nal_size;
pos += nal_size;
}
}
CodecData = malloc(tmp_len);
memcpy(CodecData, tmp, tmp_len);
CodecDataLen = tmp_len;
}
}
}
else
{
*NalLength = 0;
}
return ret;
}
static int reset()
{
initialHeader = 1;
return 0;
}
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];
h264_printf(20, "\n");
if (call == NULL)
{
h264_err("call data is NULL...\n");
return 0;
}
TimeDelta = call->FrameRate;
TimeScale = call->FrameScale;
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)
{
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 writev_with_retry(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);
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);
PacketLength += iov[0].iov_len;
if (PacketLength != len)
{
h264_err("<<<< not all data have been written [%d/%d]\n", len, PacketLength);
}
}
h264_printf(10, "< len %d\n", len);
return len;
}
static int writeReverseData(void *_call)
{
WriterAVCallData_t *call = (WriterAVCallData_t *) _call;
return 0;
}
/* ***************************** */
/* Writer Definition */
/* ***************************** */
static WriterCaps_t caps =
{
"h265",
eVideo,
"V_HEVC",
-1,
STREAMTYPE_MPEG4_H265,
CT_H265
};
struct Writer_s WriterVideoH265 =
{
&reset,
&writeData,
&writeReverseData,
&caps
};

View File

@@ -0,0 +1,266 @@
/*
* linuxdvb output/writer handling.
*
* konfetti 2010 based on linuxdvb.c code from libeplayer2
*
* 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 */
/* ***************************** */
#define _XOPEN_SOURCE
#include <unistd.h>
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <fcntl.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/ioctl.h>
#include <sys/uio.h>
#include <linux/dvb/video.h>
#include <linux/dvb/audio.h>
#include <memory.h>
#include <asm/types.h>
#include <pthread.h>
#include <errno.h>
#include <libavcodec/avcodec.h>
#include "stm_ioctls.h"
#include "bcm_ioctls.h"
#include "common.h"
#include "output.h"
#include "debug.h"
#include "misc.h"
#include "pes.h"
#include "writer.h"
#include "pcm.h"
/* ***************************** */
/* Makros/Constants */
/* ***************************** */
//#define SAM_WITH_DEBUG
#ifdef SAM_WITH_DEBUG
#define LPCM_DEBUG
#else
#define LPCM_SILENT
#endif
#ifdef LPCM_DEBUG
static uint16_t debug_level = 1;
#define lpcm_printf(level, fmt, x...) do { \
if (debug_level >= level) printf("[%s:%s] " fmt, __FILE__, __FUNCTION__, ## x); } while (0)
#else
#define lpcm_printf(level, fmt, x...)
#endif
#ifndef LPCM_SILENT
#define lpcm_err(fmt, x...) do { printf("[%s:%s] " fmt, __FILE__, __FUNCTION__, ## x); } while (0)
#else
#define lpcm_err(fmt, x...)
#endif
#define LLPCM_VOB_HEADER_LEN (6)
/* ***************************** */
/* Types */
/* ***************************** */
/* ***************************** */
/* Varaibles */
/* ***************************** */
static uint8_t PesHeader[PES_MAX_HEADER_SIZE];
static uint8_t initialHeader = 1;
static uint8_t i_freq_code = 0;
static int32_t i_frame_samples;
static int32_t i_frame_size;
static int32_t i_buffer_used;
static int32_t i_frame_num;
static int32_t i_bitspersample;
static uint8_t *p_buffer = 0;
static uint8_t *p_frame_buffer = 0;
/* ***************************** */
/* Prototypes */
/* ***************************** */
/* ***************************** */
/* MISC Functions */
/* ***************************** */
/* https://www.videolan.org/developers/vlc/modules/codec/lpcm.c
* LPCM DVD header :
* - number of frames in this packet (8 bits)
* - first access unit (16 bits) == 0x0003 ?
* - emphasis (1 bit)
* - mute (1 bit)
* - reserved (1 bit)
* - current frame (5 bits)
* - quantisation (2 bits) 0 == 16bps, 1 == 20bps, 2 == 24bps, 3 == illegal
* - frequency (2 bits) 0 == 48 kHz, 1 == 96 kHz, 2 == 44.1 kHz, 3 == 32 kHz
* - reserved (1 bit)
* - number of channels - 1 (3 bits) 1 == 2 channels
* - dynamic range (8 bits) 0x80 == neutral
*/
static int32_t reset()
{
initialHeader = 1;
return 0;
}
static int32_t writeData(void *_call)
{
WriterAVCallData_t *call = (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);
int32_t i_ret_size = 0;
if (i_channels > 8)
{
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);
lpcm_printf(1, "i_channels: [%d]\n", i_channels);
switch (i_rate)
{
case 48000:
i_freq_code = 0;
break;
case 96000:
i_freq_code = 1;
break;
case 44100:
i_freq_code = 2;
break;
case 32000:
i_freq_code = 3;
break;
default:
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;
if (NULL != p_buffer)
{
free(p_buffer);
}
p_buffer = malloc(i_frame_samples * i_channels * 16);
if (NULL != p_frame_buffer)
{
free(p_frame_buffer);
}
p_frame_buffer = malloc(i_frame_size);
i_buffer_used = 0;
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)
{
uint8_t *frame = (uint8_t *)p_frame_buffer;
frame[0] = 1; /* one frame in packet */
frame[1] = 0;
frame[2] = 0; /* no first access unit */
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);
#else
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;
iov[1].iov_base = frame;
iov[1].iov_len = i_frame_size;
i_ret_size += writev_with_retry(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;
}
/* ***************************** */
/* Writer Definition */
/* ***************************** */
static WriterCaps_t caps_lpcm =
{
"ipcm",
eAudio,
"A_LPCM",
AUDIO_ENCODING_LPCMA,
AUDIOTYPE_LPCM,
-1
};
struct Writer_s WriterAudioLPCM =
{
&reset,
&writeData, /* writeDataLPCM */
NULL,
&caps_lpcm
};

View File

@@ -0,0 +1,189 @@
/*
* linuxdvb output/writer handling.
*
* konfetti 2010 based on linuxdvb.c code from libeplayer2
*
* 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 <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <unistd.h>
#include <fcntl.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/ioctl.h>
#include <sys/uio.h>
#include <linux/dvb/video.h>
#include <linux/dvb/audio.h>
#include <memory.h>
#include <asm/types.h>
#include <pthread.h>
#include <errno.h>
#include "stm_ioctls.h"
#include "bcm_ioctls.h"
#include "common.h"
#include "output.h"
#include "debug.h"
#include "misc.h"
#include "pes.h"
#include "writer.h"
/* ***************************** */
/* Makros/Constants */
/* ***************************** */
#define MP3_DEBUG
#ifdef MP3_DEBUG
static short debug_level = 0;
#define mp3_printf(level, fmt, x...) do { \
if (debug_level >= level) printf("[%s:%s] " fmt, __FILE__, __FUNCTION__, ## x); } while (0)
#else
#define mp3_printf(level, fmt, x...)
#endif
#ifndef MP3_SILENT
#define mp3_err(fmt, x...) do { printf("[%s:%s] " fmt, __FILE__, __FUNCTION__, ## x); } while (0)
#else
#define mp3_err(fmt, x...)
#endif
/* ***************************** */
/* Types */
/* ***************************** */
/* ***************************** */
/* Varaibles */
/* ***************************** */
/* ***************************** */
/* Prototypes */
/* ***************************** */
/* ***************************** */
/* MISC Functions */
/* ***************************** */
static int reset()
{
return 0;
}
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 = writev_with_retry(call->fd, iov, 2);
mp3_printf(10, "mp3_Write-< len=%d\n", len);
return len;
}
/* ***************************** */
/* Writer Definition */
/* ***************************** */
static WriterCaps_t caps_mp3 =
{
"mp3",
eAudio,
"A_MP3",
AUDIO_ENCODING_MP3,
AUDIOTYPE_MP3,
-1
};
struct Writer_s WriterAudioMP3 =
{
&reset,
&writeData,
NULL,
&caps_mp3
};
static WriterCaps_t caps_mpegl3 =
{
"mpeg/l3",
eAudio,
"A_MPEG/L3",
AUDIO_ENCODING_MPEG2,
AUDIOTYPE_MP3,
-1
};
struct Writer_s WriterAudioMPEGL3 =
{
&reset,
&writeData,
NULL,
&caps_mpegl3
};
static WriterCaps_t caps_vorbis =
{
"vorbis",
eAudio,
"A_VORBIS",
AUDIO_ENCODING_VORBIS,
AUDIO_ENCODING_MP3,
-1
};
struct Writer_s WriterAudioVORBIS =
{
&reset,
&writeData,
NULL,
&caps_vorbis
};

View File

@@ -0,0 +1,180 @@
/*
* linuxdvb output/writer handling.
*
* konfetti 2010 based on linuxdvb.c code from libeplayer2
*
* 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 <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <unistd.h>
#include <fcntl.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/ioctl.h>
#include <sys/uio.h>
#include <linux/dvb/video.h>
#include <linux/dvb/audio.h>
#include <memory.h>
#include <asm/types.h>
#include <pthread.h>
#include <errno.h>
#include "stm_ioctls.h"
#include "bcm_ioctls.h"
#include "common.h"
#include "output.h"
#include "debug.h"
#include "misc.h"
#include "pes.h"
#include "writer.h"
/* ***************************** */
/* Makros/Constants */
/* ***************************** */
#define MPEG2_DEBUG
#ifdef MPEG2_DEBUG
static short debug_level = 0;
#define mpeg2_printf(level, fmt, x...) do { \
if (debug_level >= level) printf("[%s:%s] " fmt, __FILE__, __FUNCTION__, ## x); } while (0)
#else
#define mpeg2_printf(level, fmt, x...)
#endif
#ifndef MPEG2_SILENT
#define mpeg2_err(fmt, x...) do { printf("[%s:%s] " fmt, __FILE__, __FUNCTION__, ## x); } while (0)
#else
#define mpeg2_err(fmt, x...)
#endif
/* ***************************** */
/* Types */
/* ***************************** */
/* ***************************** */
/* Varaibles */
/* ***************************** */
/* ***************************** */
/* Prototypes */
/* ***************************** */
/* ***************************** */
/* MISC Functions */
/* ***************************** */
static int reset()
{
return 0;
}
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)
{
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 = writev_with_retry(call->fd, iov, 2);
if (l < 0)
{
len = l;
break;
}
len += l;
Position += PacketLength;
call->Pts = INVALID_PTS_VALUE;
}
mpeg2_printf(10, "< len %d\n", len);
return len;
}
/* ***************************** */
/* Writer Definition */
/* ***************************** */
static WriterCaps_t caps =
{
"mpeg2",
eVideo,
"V_MPEG2",
VIDEO_ENCODING_AUTO,
STREAMTYPE_MPEG2,
CT_MPEG2
};
struct Writer_s WriterVideoMPEG2 =
{
&reset,
&writeData,
NULL,
&caps
};
static WriterCaps_t mpg1_caps =
{
"mpge1",
eVideo,
"V_MPEG1",
VIDEO_ENCODING_H264,
STREAMTYPE_MPEG1,
CT_MPEG1
};
struct Writer_s WriterVideoMPEG1 =
{
&reset,
&writeData,
NULL,
&mpg1_caps
};

View File

@@ -0,0 +1,164 @@
/*
* linuxdvb output/writer handling.
*
* konfetti 2010 based on linuxdvb.c code from libeplayer2
*
* 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 <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <unistd.h>
#include <fcntl.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/ioctl.h>
#include <sys/uio.h>
#include <linux/dvb/video.h>
#include <linux/dvb/audio.h>
#include <memory.h>
#include <asm/types.h>
#include <pthread.h>
#include <errno.h>
#include "stm_ioctls.h"
#include "bcm_ioctls.h"
#include "common.h"
#include "output.h"
#include "debug.h"
#include "misc.h"
#include "pes.h"
#include "writer.h"
/* ***************************** */
/* Makros/Constants */
/* ***************************** */
//#define SAM_WITH_DEBUG
#ifdef SAM_WITH_DEBUG
#define MPEG4_DEBUG
#else
#define MPEG4_SILENT
#endif
#ifdef MPEG4_DEBUG
static short debug_level = 0;
#define mpeg4_printf(level, fmt, x...) do { \
if (debug_level >= level) printf("[%s:%s] " fmt, __FILE__, __FUNCTION__, ## x); } while (0)
#else
#define mpeg4_printf(level, fmt, x...)
#endif
#ifndef MPEG4_SILENT
#define mpeg4_err(fmt, x...) do { printf("[%s:%s] " fmt, __FILE__, __FUNCTION__, ## x); } while (0)
#else
#define mpeg4_err(fmt, x...)
#endif
/* ***************************** */
/* Types */
/* ***************************** */
/* ***************************** */
/* Varaibles */
/* ***************************** */
static int initialHeader = 1;
/* ***************************** */
/* Prototypes */
/* ***************************** */
/* ***************************** */
/* MISC Functions */
/* ***************************** */
static int reset()
{
initialHeader = 1;
return 0;
}
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 = writev_with_retry(call->fd, iov, ic);
mpeg4_printf(10, "xvid_Write < len=%d\n", len);
return len;
}
/* ***************************** */
/* Writer Definition */
/* ***************************** */
static WriterCaps_t mpeg4p2_caps =
{
"mpeg4p2",
eVideo,
"V_MPEG4",
VIDEO_ENCODING_MPEG4P2,
STREAMTYPE_MPEG4_Part2,
-1
};
struct Writer_s WriterVideoMPEG4 =
{
&reset,
&writeData,
NULL,
&mpeg4p2_caps
};

View File

@@ -0,0 +1,312 @@
/*
* linuxdvb output/writer handling.
*
* konfetti 2010 based on linuxdvb.c code from libeplayer2
*
* 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 <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <unistd.h>
#include <fcntl.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/ioctl.h>
#include <sys/uio.h>
#include <linux/dvb/video.h>
#include <linux/dvb/audio.h>
#include <memory.h>
#include <asm/types.h>
#include <pthread.h>
#include <errno.h>
#include <libavcodec/avcodec.h>
#include "stm_ioctls.h"
#include "bcm_ioctls.h"
#include "common.h"
#include "output.h"
#include "debug.h"
#include "misc.h"
#include "pes.h"
#include "writer.h"
#include "pcm.h"
/* ***************************** */
/* Makros/Constants */
/* ***************************** */
#ifdef SAM_WITH_DEBUG
#define PCM_DEBUG
#else
#define PCM_SILENT
#endif
#ifdef PCM_DEBUG
static uint16_t debug_level = 0;
#define pcm_printf(level, fmt, x...) do { \
if (debug_level >= level) printf("[%s:%s] " fmt, __FILE__, __FUNCTION__, ## x); } while (0)
#else
#define pcm_printf(level, fmt, x...)
#endif
#ifndef PCM_SILENT
#define pcm_err(fmt, x...) do { printf("[%s:%s] " fmt, __FILE__, __FUNCTION__, ## x); } while (0)
#else
#define pcm_err(fmt, x...)
#endif
/* ***************************** */
/* Types */
/* ***************************** */
/* ***************************** */
/* Varaibles */
/* ***************************** */
static uint8_t initialHeader = 1;
static uint8_t codec_data[18];
static uint64_t fixed_buffertimestamp;
static uint64_t fixed_bufferduration;
static uint32_t fixed_buffersize;
static uint8_t *fixed_buffer;
static uint32_t fixed_bufferfilled;
/* ***************************** */
/* Prototypes */
/* ***************************** */
/* ***************************** */
/* MISC Functions */
/* ***************************** */
static int32_t reset()
{
initialHeader = 1;
return 0;
}
static int32_t writeData(void *_call)
{
WriterAVCallData_t *call = (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)
{
printf("ioctl %d", ioctl(call->fd, AUDIO_SELECT_SOURCE, AUDIO_SOURCE_MEMORY));
printf("ioctl %d", ioctl(call->fd, AUDIO_PAUSE));
printf("ioctl %d", ioctl(call->fd, AUDIO_SET_BYPASS_MODE, 0x30));
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)
{
case AV_CODEC_ID_PCM_S8:
case AV_CODEC_ID_PCM_U8:
width = depth = 8;
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:
width = depth = 16;
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:
width = depth = 24;
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:
width = depth = 32;
break;
default:
break;
}
uint8_t *data = codec_data;
byterate = channels * rate * width / 8;
block_align = channels * width / 8;
memset(data, 0, sizeof(codec_data));
/* format tag */
*(data++) = format & 0xff;
*(data++) = (format >> 8) & 0xff;
/* channels */
*(data++) = channels & 0xff;
*(data++) = (channels >> 8) & 0xff;
/* sample rate */
*(data++) = rate & 0xff;
*(data++) = (rate >> 8) & 0xff;
*(data++) = (rate >> 16) & 0xff;
*(data++) = (rate >> 24) & 0xff;
/* byte rate */
*(data++) = byterate & 0xff;
*(data++) = (byterate >> 8) & 0xff;
*(data++) = (byterate >> 16) & 0xff;
*(data++) = (byterate >> 24) & 0xff;
/* block align */
*(data++) = block_align & 0xff;
*(data++) = (block_align >> 8) & 0xff;
/* 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;
if (NULL != fixed_buffer)
{
free(fixed_buffer);
}
fixed_buffer = malloc(fixed_buffersize);
}
fixed_bufferfilled = 0;
//printf("PCM fixed_buffersize [%u] [%s]\n", fixed_buffersize, LE ? "LE":"BE");
}
while (size > 0)
{
uint32_t cpSize = (fixed_buffersize - fixed_bufferfilled);
if (cpSize > size)
{
memcpy(fixed_buffer + fixed_bufferfilled, buffer, size);
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())
{
addHeaderSize = 4;
}
uint32_t headerSize = InsertPesHeader(PesHeader, fixed_buffersize + 4 + addHeaderSize + sizeof(codec_data), MPEG_AUDIO_PES_START_CODE, fixed_buffertimestamp, 0);
if (IsDreambox())
{
PesHeader[headerSize++] = 0x42; // B
PesHeader[headerSize++] = 0x43; // C
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;
iov[1].iov_base = fixed_buffer;
iov[1].iov_len = fixed_buffersize;
writev_with_retry(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);
close(g_fd_dump);
}
return size;
}
/* ***************************** */
/* Writer Definition */
/* ***************************** */
static WriterCaps_t caps_pcm =
{
"pcm",
eAudio,
"A_PCM",
AUDIO_ENCODING_LPCMA,
0x30,
-1
};
struct Writer_s WriterAudioPCM =
{
&reset,
&writeData,
NULL,
&caps_pcm
};
static WriterCaps_t caps_ipcm =
{
"ipcm",
eAudio,
"A_IPCM",
AUDIO_ENCODING_LPCMA,
0x30,
-1
};
struct Writer_s WriterAudioIPCM =
{
&reset,
&writeData, /* writeDataIPCM */
NULL,
&caps_ipcm
};

View File

@@ -0,0 +1,200 @@
/*
* linuxdvb output/writer handling.
*
* konfetti 2010 based on linuxdvb.c code from libeplayer2
*
* 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 <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <unistd.h>
#include <fcntl.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/ioctl.h>
#include <sys/uio.h>
#include <linux/dvb/video.h>
#include <linux/dvb/audio.h>
#include <memory.h>
#include <asm/types.h>
#include <pthread.h>
#include <errno.h>
#include "stm_ioctls.h"
#include "bcm_ioctls.h"
#include "common.h"
#include "output.h"
#include "debug.h"
#include "misc.h"
#include "pes.h"
#include "writer.h"
/* ***************************** */
/* Makros/Constants */
/* ***************************** */
#define VC1_SEQUENCE_LAYER_METADATA_START_CODE 0x80
#define VC1_FRAME_START_CODE 0x0d
#define SAM_WITH_DEBUG
#ifdef SAM_WITH_DEBUG
#define VC1_DEBUG
#else
#define VC1_SILENT
#endif
#ifdef VC1_DEBUG
static short debug_level = 10;
#define vc1_printf(level, fmt, x...) do { \
if (debug_level >= level) printf("[%s:%s] " fmt, __FILE__, __FUNCTION__, ## x); } while (0)
#else
#define vc1_printf(level, fmt, x...)
#endif
#ifndef VC1_SILENT
#define vc1_err(fmt, x...) do { printf("[%s:%s] " fmt, __FILE__, __FUNCTION__, ## x); } while (0)
#else
#define vc1_err(fmt, x...)
#endif
/* ***************************** */
/* Types */
/* ***************************** */
static const unsigned char SequenceLayerStartCode[] = {0x00, 0x00, 0x01, VC1_SEQUENCE_LAYER_METADATA_START_CODE};
static const uint8_t Vc1FrameStartCode[] = {0, 0, 1, VC1_FRAME_START_CODE};
/* ***************************** */
/* Varaibles */
/* ***************************** */
static int initialHeader = 1;
static video_codec_data_t videocodecdata = {0, 0};
/* ***************************** */
/* Prototypes */
/* ***************************** */
/* ***************************** */
/* MISC Functions */
/* ***************************** */
static int reset()
{
initialHeader = 1;
return 0;
}
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 writev_with_retry(call->fd, iov, ic);
}
/* ***************************** */
/* Writer Definition */
/* ***************************** */
static WriterCaps_t caps =
{
"vc1",
eVideo,
"V_VC1",
VIDEO_ENCODING_VC1,
STREAMTYPE_VC1,
CT_MPEG4_PART2
};
struct Writer_s WriterVideoVC1 =
{
&reset,
&writeData,
NULL,
&caps
};

View File

@@ -0,0 +1,228 @@
/*
* linuxdvb output/writer handling.
*
* konfetti 2010 based on linuxdvb.c code from libeplayer2
*
* 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 <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <unistd.h>
#include <fcntl.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/ioctl.h>
#include <sys/uio.h>
#include <linux/dvb/video.h>
#include <linux/dvb/audio.h>
#include <memory.h>
#include <asm/types.h>
#include <pthread.h>
#include <errno.h>
#include "stm_ioctls.h"
#include "bcm_ioctls.h"
#include "common.h"
#include "output.h"
#include "debug.h"
#include "misc.h"
#include "pes.h"
#include "writer.h"
/* ***************************** */
/* Makros/Constants */
/* ***************************** */
//#define SAM_WITH_DEBUG
#ifdef SAM_WITH_DEBUG
#define VP_DEBUG
#else
#define VP_SILENT
#endif
#ifdef VP_DEBUG
static short debug_level = 10;
#define vp_printf(level, fmt, x...) do { \
if (debug_level >= level) printf("[%s:%s] " fmt, __FILE__, __FUNCTION__, ## x); } while (0)
#else
#define vp_printf(level, fmt, x...)
#endif
#ifndef VP_SILENT
#define vp_err(fmt, x...) do { printf("[%s:%s] " fmt, __FILE__, __FUNCTION__, ## x); } while (0)
#else
#define vp_err(fmt, x...)
#endif
/* ***************************** */
/* Types */
/* ***************************** */
/* ***************************** */
/* Varaibles */
/* ***************************** */
/* ***************************** */
/* Prototypes */
/* ***************************** */
/* ***************************** */
/* MISC Functions */
/* ***************************** */
static int reset()
{
return 0;
}
static int writeData(void *_call, int is_vp6)
{
WriterAVCallData_t *call = (WriterAVCallData_t *) _call;
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;
memcpy(PesHeader + pes_header_len, "BCMV", 4);
pes_header_len += 4;
if (is_vp6)
++len;
PesHeader[pes_header_len++] = (len & 0xFF000000) >> 24;
PesHeader[pes_header_len++] = (len & 0x00FF0000) >> 16;
PesHeader[pes_header_len++] = (len & 0x0000FF00) >> 8;
PesHeader[pes_header_len++] = (len & 0x000000FF) >> 0;
PesHeader[pes_header_len++] = 0;
PesHeader[pes_header_len++] = 0;
if (is_vp6)
PesHeader[pes_header_len++] = 0;
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);
}
static int writeDataVP6(void *_call)
{
return writeData(_call, 1);
}
static int writeDataVP89(void *_call)
{
return writeData(_call, 0);
}
/* ***************************** */
/* Writer Definition */
/* ***************************** */
static WriterCaps_t capsVP6 =
{
"vp6",
eVideo,
"V_VP6",
VIDEO_ENCODING_VC1,
STREAMTYPE_VB6,
CT_VP6
};
struct Writer_s WriterVideoVP6 =
{
&reset,
&writeDataVP6,
NULL,
&capsVP6
};
static WriterCaps_t capsVP8 =
{
"vp8",
eVideo,
"V_VP8",
VIDEO_ENCODING_VC1,
STREAMTYPE_VB8,
CT_VP8
};
struct Writer_s WriterVideoVP8 =
{
&reset,
&writeDataVP89,
NULL,
&capsVP8
};
static WriterCaps_t capsVP9 =
{
"vp9",
eVideo,
"V_VP9",
VIDEO_ENCODING_VC1,
STREAMTYPE_VB9,
CT_VP9
};
struct Writer_s WriterVideoVP9 =
{
&reset,
&writeDataVP89,
NULL,
&capsVP9
};
static WriterCaps_t capsSPARK =
{
"spark",
eVideo,
"V_SPARK",
VIDEO_ENCODING_VC1,
STREAMTYPE_SPARK,
CT_SPARK
};
struct Writer_s WriterVideoSPARK =
{
&reset,
&writeDataVP89,
NULL,
&capsSPARK
};

View File

@@ -0,0 +1,202 @@
/*
* linuxdvb output/writer handling.
*
* konfetti 2010 based on linuxdvb.c code from libeplayer2
*
* 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 <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <unistd.h>
#include <fcntl.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/ioctl.h>
#include <sys/uio.h>
#include <linux/dvb/video.h>
#include <linux/dvb/audio.h>
#include <memory.h>
#include <asm/types.h>
#include <pthread.h>
#include <errno.h>
#include "stm_ioctls.h"
#include "bcm_ioctls.h"
#include "common.h"
#include "output.h"
#include "debug.h"
#include "misc.h"
#include "pes.h"
#include "writer.h"
/* ***************************** */
/* Makros/Constants */
/* ***************************** */
#ifdef SAM_WITH_DEBUG
#define WMA_DEBUG
#else
#define WMA_SILENT
#endif
#ifdef WMA_DEBUG
static short debug_level = 0;
#define wma_printf(level, fmt, x...) do { \
if (debug_level >= level) printf("[%s:%s] " fmt, __FILE__, __FUNCTION__, ## x); } while (0)
#else
#define wma_printf(level, fmt, x...)
#endif
#ifndef WMA_SILENT
#define wma_err(fmt, x...) do { printf("[%s:%s] " fmt, __FILE__, __FUNCTION__, ## x); } while (0)
#else
#define wma_err(fmt, x...)
#endif
/* ***************************** */
/* Types */
/* ***************************** */
/* ***************************** */
/* Varaibles */
/* ***************************** */
static int initialHeader = 1;
static uint8_t *PesHeader = NULL;
static uint32_t MaxPesHeader = 0;
/* ***************************** */
/* Prototypes */
/* ***************************** */
/* ***************************** */
/* MISC Functions */
/* ***************************** */
static int reset()
{
initialHeader = 1;
return 0;
}
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;
}
uint32_t packetLength = 4 + call->private_size + call->len;
if (IsDreambox())
{
packetLength += 4;
}
if ((packetLength + PES_MAX_HEADER_SIZE) > MaxPesHeader)
{
if (PesHeader)
{
free(PesHeader);
}
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())
{
PesHeader[headerSize++] = 0x42; // B
PesHeader[headerSize++] = 0x43; // C
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;
iov[1].iov_base = call->data;
iov[1].iov_len = call->len;
return writev_with_retry(call->fd, iov, 2);
}
/* ***************************** */
/* Writer Definition */
/* ***************************** */
static WriterCaps_t capsWMAPRO =
{
"wma/pro",
eAudio,
"A_WMA/PRO",
AUDIO_ENCODING_WMA,
AUDIOTYPE_WMA_PRO,
-1
};
struct Writer_s WriterAudioWMAPRO =
{
&reset,
&writeData,
NULL,
&capsWMAPRO
};
static WriterCaps_t capsWMA =
{
"wma",
eAudio,
"A_WMA",
AUDIO_ENCODING_WMA,
AUDIOTYPE_WMA,
-1
};
struct Writer_s WriterAudioWMA =
{
&reset,
&writeData,
NULL,
&capsWMA
};

View File

@@ -0,0 +1,206 @@
/*
* linuxdvb output/writer handling.
*
* konfetti 2010 based on linuxdvb.c code from libeplayer2
*
* 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 <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <unistd.h>
#include <fcntl.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/ioctl.h>
#include <sys/uio.h>
#include <linux/dvb/video.h>
#include <linux/dvb/audio.h>
#include <memory.h>
#include <asm/types.h>
#include <pthread.h>
#include <errno.h>
#include "stm_ioctls.h"
#include "bcm_ioctls.h"
#include "common.h"
#include "output.h"
#include "debug.h"
#include "misc.h"
#include "pes.h"
#include "writer.h"
/* ***************************** */
/* Makros/Constants */
/* ***************************** */
#define WMV_FRAME_START_CODE 0x0d
//#define SAM_WITH_DEBUG
#ifdef SAM_WITH_DEBUG
#define WMV_DEBUG
#else
#define WMV_SILENT
#endif
#ifdef WMV_DEBUG
static short debug_level = 10;
#define wmv_printf(level, fmt, x...) do { \
if (debug_level >= level) printf("[%s:%s] " fmt, __FILE__, __FUNCTION__, ## x); } while (0)
#else
#define wmv_printf(level, fmt, x...)
#endif
#ifndef WMV_SILENT
#define wmv_err(fmt, x...) do { printf("[%s:%s] " fmt, __FILE__, __FUNCTION__, ## x); } while (0)
#else
#define wmv_err(fmt, x...)
#endif
/* ***************************** */
/* Types */
/* ***************************** */
static const uint8_t Vc1FrameStartCode[] = {0, 0, 1, WMV_FRAME_START_CODE};
/* ***************************** */
/* Varaibles */
/* ***************************** */
static int initialHeader = 1;
static video_codec_data_t videocodecdata = {0, 0};
/* ***************************** */
/* Prototypes */
/* ***************************** */
/* ***************************** */
/* MISC Functions */
/* ***************************** */
static int reset()
{
initialHeader = 1;
return 0;
}
static int writeData(void *_call)
{
WriterAVCallData_t *call = (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)
{
initialHeader = 0;
if (videocodecdata.data)
{
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);
data += 18;
/* width */
*(data++) = (call->Width >> 8) & 0xff;
*(data++) = call->Width & 0xff;
/* height */
*(data++) = (call->Height >> 8) & 0xff;
*(data++) = call->Height & 0xff;
if (call->private_data && codec_size) memcpy(data, call->private_data, codec_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 writev_with_retry(call->fd, iov, ic);
}
/* ***************************** */
/* Writer Definition */
/* ***************************** */
static WriterCaps_t caps =
{
"wmv",
eVideo,
"V_WMV",
VIDEO_ENCODING_WMV,
STREAMTYPE_VC1_SM,
CT_MPEG4_PART2
};
struct Writer_s WriterVideoWMV =
{
&reset,
&writeData,
NULL,
&caps
};

View File

@@ -0,0 +1,204 @@
/*
* 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 <stdlib.h>
#include <string.h>
#include <errno.h>
#include "misc.h"
#include "writer.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 */
/* ***************************** */
static Writer_t *AvailableWriter[] =
{
&WriterAudioAAC,
&WriterAudioAACLATM,
&WriterAudioAACLATM,
&WriterAudioAACPLUS,
&WriterAudioAC3,
&WriterAudioEAC3,
&WriterAudioMP3,
&WriterAudioMPEGL3,
&WriterAudioPCM,
&WriterAudioIPCM,
&WriterAudioLPCM,
&WriterAudioDTS,
&WriterAudioWMA,
&WriterAudioWMAPRO,
&WriterVideoH264,
&WriterVideoH265,
&WriterVideoH263,
&WriterVideoMPEG4,
&WriterVideoMPEG2,
&WriterVideoMPEG1,
&WriterVideoVC1,
&WriterVideoDIVX3,
&WriterVideoVP6,
&WriterVideoVP8,
&WriterVideoVP9,
&WriterVideoSPARK,
&WriterVideoWMV,
NULL
};
/* ***************************** */
/* Prototypes */
/* ***************************** */
/* ***************************** */
/* Functions */
/* ***************************** */
ssize_t write_with_retry(int fd, const void *buf, size_t 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)
{
case EINTR:
case EAGAIN:
usleep(1000);
continue;
default:
retval = -3;
break;
}
if (retval < 0)
{
break;
}
}
if (ret < 0)
{
return ret;
}
size -= ret;
buf += ret;
if (size > 0)
{
if (usleep(1000))
{
writer_err("usleep error \n");
}
}
}
return 0;
}
ssize_t writev_with_retry(int fd, const struct iovec *iov, size_t ic)
{
ssize_t len = 0;
int i = 0;
for (i = 0; i < ic; ++i)
{
write_with_retry(fd, iov[i].iov_base, iov[i].iov_len);
len += iov[i].iov_len;
if (PlaybackDieNow(0))
{
return -1;
}
}
return len;
}
Writer_t *getWriter(char *encoding)
{
int i;
for (i = 0; AvailableWriter[i] != NULL; i++)
{
if (strcmp(AvailableWriter[i]->caps->textEncoding, encoding) == 0)
{
writer_printf(50, "%s: found writer \"%s\" for \"%s\"\n", __func__, AvailableWriter[i]->caps->name, 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)
{
writer_printf(50, "%s: found writer \"%s\"\n", __func__, AvailableWriter[i]->caps->name);
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)
{
writer_printf(50, "%s: found writer \"%s\"\n", __func__, AvailableWriter[i]->caps->name);
return AvailableWriter[i];
}
}
writer_printf(1, "%s: no writer found\n", __func__);
return NULL;
}

View File

@@ -0,0 +1,372 @@
/*
* linuxdvb output/writer handling.
*
* konfetti 2010 based on linuxdvb.c code from libeplayer2
*
* 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 <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <unistd.h>
#include <fcntl.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/ioctl.h>
#include <linux/dvb/video.h>
#include <linux/dvb/audio.h>
#include <linux/dvb/stm_ioctls.h>
#include <memory.h>
#include <asm/types.h>
#include <pthread.h>
#include <errno.h>
#include <sys/uio.h>
#include <libavutil/intreadwrite.h>
#include "ffmpeg/latmenc.h"
#include "common.h"
#include "output.h"
#include "debug.h"
#include "misc.h"
#include "pes.h"
#include "writer.h"
#include "aac.h"
/* ***************************** */
/* Makros/Constants */
/* ***************************** */
//#define SAM_WITH_DEBUG
#ifdef SAM_WITH_DEBUG
#define AAC_DEBUG
#else
#define AAC_SILENT
#endif
#ifdef AAC_DEBUG
static short debug_level = 0;
#define aac_printf(level, fmt, x...) do { \
if (debug_level >= level) printf("[%s:%s] " fmt, __FILE__, __FUNCTION__, ## x); } while (0)
#else
#define aac_printf(level, fmt, x...)
#endif
#ifndef AAC_SILENT
#define aac_err(fmt, x...) do { printf("[%s:%s] " fmt, __FILE__, __FUNCTION__, ## x); } while (0)
#else
#define aac_err(fmt, x...)
#endif
/* ***************************** */
/* Types */
/* ***************************** */
/* ***************************** */
/* Varaibles */
/* ***************************** */
/// ** AAC ADTS format **
///
/// AAAAAAAA AAAABCCD EEFFFFGH HHIJKLMM
/// MMMMMMMM MMMNNNNN NNNNNNOO ........
///
/// Sign Length Position Description
///
/// A 12 (31-20) Sync code
/// B 1 (19) ID
/// C 2 (18-17) layer
/// D 1 (16) protect absent
/// E 2 (15-14) profile
/// F 4 (13-10) sample freq index
/// G 1 (9) private
/// H 3 (8-6) channel config
/// I 1 (5) original/copy
/// J 1 (4) home
/// K 1 (3) copyright id
/// L 1 (2) copyright start
/// M 13 (1-0,31-21) frame length
/// N 11 (20-10) adts buffer fullness
/// O 2 (9-8) num of raw data blocks in frame
/*
LC: Audio: aac, 44100 Hz, stereo, s16, 192 kb/ ->ff f1 50 80 00 1f fc
HE: Audio: aac, 48000 Hz, stereo, s16, 77 kb/s ->ff f1 4c 80 00 1f fc
*/
/*
ADIF = basic format called Audio Data Interchange Format (ADIF)
consisting of a single header followed by the raw AAC audio data blocks
ADTS = streaming format called Audio Data Transport Stream (ADTS)
consisting of a series of frames, each frame having a header followed by the AAC audio data
LOAS = Low Overhead Audio Stream (LOAS), a self-synchronizing streaming format
*/
static unsigned char DefaultAACHeader[] =
{
0xff,
0xf1,
/*0x00, 0x00*/0x50, //((Profile & 0x03) << 6) | (SampleIndex << 2) | ((Channels >> 2) & 0x01);s
0x80, //(Channels & 0x03) << 6;
0x00,
0x1f,
0xfc
};
LATMContext *pLATMCtx = NULL;
/* ***************************** */
/* Prototypes */
/* ***************************** */
/* ***************************** */
/* MISC Functions */
/* ***************************** */
static int reset()
{
if (pLATMCtx)
{
free(pLATMCtx);
pLATMCtx = NULL;
}
return 0;
}
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
{
if (0xFF != call->data[0] || 0xF0 != (0xF0 & call->data[1]))
{
aac_err("parsing Data with missing syncword. ignoring...\n");
return 0;
}
}
else // check LOAS header
{
if (!(call->len > 2 && call->data[0] == 0x56 && (call->data[1] >> 4) == 0xe &&
(AV_RB16(call->data + 1) & 0x1FFF) + 3 == call->len))
{
aac_err("parsing Data with wrong latm header. ignoring...\n");
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;
iov[1].iov_base = call->data;
iov[1].iov_len = call->len;
return writev(call->fd, iov, 2);
}
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)
{
aac_printf(10, "private_data = NULL\n");
memcpy(pExtraData, DefaultAACHeader, AAC_HEADER_LENGTH);
}
else
{
memcpy(pExtraData, call->private_data, AAC_HEADER_LENGTH);
}
pExtraData[3] &= 0xC0;
/* frame size over last 2 bits */
pExtraData[3] |= (PacketLength & 0x1800) >> 11;
/* frame size continued over full byte */
pExtraData[4] = (PacketLength & 0x1FF8) >> 3;
/* frame size continued first 3 bits */
pExtraData[5] = (PacketLength & 7) << 5;
/* buffer fullness(0x7FF for VBR) over 5 last bits */
pExtraData[5] |= 0x1F;
/* 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));
memset(pLATMCtx, 0x00, sizeof(LATMContext));
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)
{
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;
}
ret = latmenc_write_packet(pLATMCtx, call->data, call->len, call->private_data, call->private_size);
if (ret)
{
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);
}
/* ***************************** */
/* Writer Definition */
/* ***************************** */
static WriterCaps_t caps =
{
"aac",
eAudio,
"A_AAC",
AUDIO_ENCODING_AAC,
-1,
-1
};
struct Writer_s WriterAudioAAC =
{
&reset,
&writeDataADTS,
NULL,
&caps
};
static WriterCaps_t caps_aac_latm =
{
"aac",
eAudio,
"A_AAC_LATM",
AUDIO_ENCODING_AAC,
-1, // it is some misunderstanding, this should be AUDIOTYPE_AAC_LATM
-1
};
struct Writer_s WriterAudioAACLATM =
{
&reset,
&writeDataLATM,
NULL,
&caps_aac_latm
};
static WriterCaps_t caps_aacplus =
{
"aac",
eAudio,
"A_AAC_PLUS",
AUDIO_ENCODING_AAC,
-1,
-1
};
struct Writer_s WriterAudioAACPLUS =
{
&reset,
&writeDataADTS,
NULL,
&caps_aacplus
};

View File

@@ -0,0 +1,165 @@
/*
* linuxdvb output/writer handling.
*
* konfetti 2010 based on linuxdvb.c code from libeplayer2
*
* 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 <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <unistd.h>
#include <fcntl.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/ioctl.h>
#include <sys/uio.h>
#include <linux/dvb/video.h>
#include <linux/dvb/audio.h>
#include <linux/dvb/stm_ioctls.h>
#include <memory.h>
#include <asm/types.h>
#include <pthread.h>
#include <errno.h>
#include "common.h"
#include "output.h"
#include "debug.h"
#include "misc.h"
#include "pes.h"
#include "writer.h"
/* ***************************** */
/* Makros/Constants */
/* ***************************** */
#define AC3_HEADER_LENGTH 7
#ifdef SAM_WITH_DEBUG
#define AC3_DEBUG
#else
#define AC3_SILENT
#endif
#ifdef AC3_DEBUG
static short debug_level = 0;
#define ac3_printf(level, fmt, x...) do { \
if (debug_level >= level) printf("[%s:%s] " fmt, __FILE__, __FUNCTION__, ## x); } while (0)
#else
#define ac3_printf(level, fmt, x...)
#endif
#ifndef AC3_SILENT
#define ac3_err(fmt, x...) do { printf("[%s:%s] " fmt, __FILE__, __FUNCTION__, ## x); } while (0)
#else
#define ac3_err(fmt, x...)
#endif
/* ***************************** */
/* Types */
/* ***************************** */
/* ***************************** */
/* Varaibles */
/* ***************************** */
/* ***************************** */
/* Prototypes */
/* ***************************** */
/* ***************************** */
/* MISC Functions */
/* ***************************** */
static int reset()
{
return 0;
}
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);
}
/* ***************************** */
/* Writer Definition */
/* ***************************** */
static WriterCaps_t caps_ac3 =
{
"ac3",
eAudio,
"A_AC3",
AUDIO_ENCODING_AC3,
-1,
-1
};
struct Writer_s WriterAudioAC3 =
{
&reset,
&writeData,
NULL,
&caps_ac3
};
static WriterCaps_t caps_eac3 =
{
"ac3",
eAudio,
"A_EAC3",
AUDIO_ENCODING_AC3,
-1,
-1
};
struct Writer_s WriterAudioEAC3 =
{
&reset,
&writeData,
NULL,
&caps_eac3
};

View File

@@ -0,0 +1,237 @@
/*
* linuxdvb output/writer handling.
*
* konfetti 2010 based on linuxdvb.c code from libeplayer2
*
* 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 <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <unistd.h>
#include <fcntl.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/ioctl.h>
#include <sys/uio.h>
#include <linux/dvb/video.h>
#include <linux/dvb/audio.h>
#include <linux/dvb/stm_ioctls.h>
#include <memory.h>
#include <asm/types.h>
#include <pthread.h>
#include <errno.h>
#include "common.h"
#include "output.h"
#include "debug.h"
#include "misc.h"
#include "pes.h"
#include "writer.h"
/* ***************************** */
/* Makros/Constants */
/* ***************************** */
#ifdef SAM_WITH_DEBUG
#define DIVX_DEBUG
#else
#define DIVX_SILENT
#endif
#ifdef DIVX_DEBUG
static short debug_level = 0;
#define divx_printf(level, fmt, x...) do { \
if (debug_level >= level) printf("[%s:%s] " fmt, __FILE__, __FUNCTION__, ## x); } while (0)
#else
#define divx_printf(level, fmt, x...)
#endif
#ifndef DIVX_SILENT
#define divx_err(fmt, x...) do { printf("[%s:%s] " fmt, __FILE__, __FUNCTION__, ## x); } while (0)
#else
#define divx_err(fmt, x...)
#endif
/* ***************************** */
/* Types */
/* ***************************** */
/* ***************************** */
/* Varaibles */
/* ***************************** */
static int initialHeader = 1;
/* ***************************** */
/* Prototypes */
/* ***************************** */
/* ***************************** */
/* MISC Functions */
/* ***************************** */
static int reset()
{
initialHeader = 1;
return 0;
}
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)
{
if (size != oldSize)
{
update = 1;
}
else
{
uint32_t i = 0;
for (i = 0; i < size; i++)
{
if (data[i] != oldData[i])
{
update = 1;
break;
}
}
}
}
if (update)
{
if (oldData != NULL)
{
free(oldData);
}
oldData = malloc(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;
}
/* ***************************** */
/* Writer Definition */
/* ***************************** */
static WriterCaps_t mpeg4p2_caps =
{
"mpeg4p2",
eVideo,
"V_MPEG4",
VIDEO_ENCODING_MPEG4P2,
-1,
-1
};
struct Writer_s WriterVideoMPEG4 =
{
&reset,
&writeData,
NULL,
&mpeg4p2_caps
};
struct Writer_s WriterVideoMSCOMP =
{
&reset,
&writeData,
NULL,
&mpeg4p2_caps
};
static WriterCaps_t fourcc_caps =
{
"fourcc",
eVideo,
"V_MS/VFW/FOURCC",
VIDEO_ENCODING_MPEG4P2,
-1,
-1
};
struct Writer_s WriterVideoFOURCC =
{
&reset,
&writeData,
NULL,
&fourcc_caps
};
static WriterCaps_t divx_caps =
{
"divx",
eVideo,
"V_MKV/XVID",
VIDEO_ENCODING_MPEG4P2,
-1,
-1
};
struct Writer_s WriterVideoDIVX =
{
&reset,
&writeData,
NULL,
&divx_caps
};

View File

@@ -0,0 +1,263 @@
/*
* linuxdvb output/writer handling.
*
* konfetti 2010 based on linuxdvb.c code from libeplayer2
*
* 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 <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <unistd.h>
#include <fcntl.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/ioctl.h>
#include <sys/uio.h>
#include <linux/dvb/video.h>
#include <linux/dvb/audio.h>
#include <linux/dvb/stm_ioctls.h>
#include <memory.h>
#include <asm/types.h>
#include <pthread.h>
#include <errno.h>
#include "common.h"
#include "output.h"
#include "debug.h"
#include "misc.h"
#include "pes.h"
#include "writer.h"
/* ***************************** */
/* Makros/Constants */
/* ***************************** */
#ifdef SAM_WITH_DEBUG
#define DIVX_DEBUG
#else
#define DIVX_SILENT
#endif
#ifdef DIVX_DEBUG
static short debug_level = 0;
#define divx_printf(level, fmt, x...) do { \
if (debug_level >= level) printf("[%s:%s] " fmt, __FILE__, __FUNCTION__, ## x); } while (0)
#else
#define divx_printf(level, fmt, x...)
#endif
#ifndef DIVX_SILENT
#define divx_err(fmt, x...) do { printf("[%s:%s] " fmt, __FILE__, __FUNCTION__, ## x); } while (0)
#else
#define divx_err(fmt, x...)
#endif
/* ***************************** */
/* Types */
/* ***************************** */
/* ***************************** */
/* Varaibles */
/* ***************************** */
static int initialHeader = 1;
/* ***************************** */
/* Prototypes */
/* ***************************** */
/* ***************************** */
/* MISC Functions */
/* ***************************** */
static int reset()
{
initialHeader = 1;
return 0;
}
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)
{
if (size != oldSize)
{
update = 1;
}
else
{
uint32_t i = 0;
for (i = 0; i < size; i++)
{
if (data[i] != oldData[i])
{
update = 1;
break;
}
}
}
}
if (update)
{
if (oldData != NULL)
{
free(oldData);
}
oldData = malloc(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;
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 = writev(call->fd, iov, ic);
divx_printf(10, "xvid_Write < len=%d\n", len);
return len;
}
/* ***************************** */
/* Writer Definition */
/* ***************************** */
static WriterCaps_t mpeg4p2_caps =
{
"mpeg4p2",
eVideo,
"V_MPEG4",
VIDEO_ENCODING_MPEG4P2,
-1,
-1
};
struct Writer_s WriterVideoMPEG4 =
{
&reset,
&writeData,
NULL,
&mpeg4p2_caps
};
struct Writer_s WriterVideoMSCOMP =
{
&reset,
&writeData,
NULL,
&mpeg4p2_caps
};
static WriterCaps_t fourcc_caps =
{
"fourcc",
eVideo,
"V_MS/VFW/FOURCC",
VIDEO_ENCODING_MPEG4P2,
-1,
-1
};
struct Writer_s WriterVideoFOURCC =
{
&reset,
&writeData,
NULL,
&fourcc_caps
};
static WriterCaps_t divx_caps =
{
"divx",
eVideo,
"V_MKV/XVID",
VIDEO_ENCODING_MPEG4P2,
-1,
-1
};
struct Writer_s WriterVideoDIVX =
{
&reset,
&writeData,
NULL,
&divx_caps
};

View File

@@ -0,0 +1,176 @@
/*
* linuxdvb output/writer handling.
*
* konfetti 2010 based on linuxdvb.c code from libeplayer2
*
* 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 <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <unistd.h>
#include <fcntl.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/ioctl.h>
#include <sys/uio.h>
#include <linux/dvb/video.h>
#include <linux/dvb/audio.h>
#include <linux/dvb/stm_ioctls.h>
#include <memory.h>
#include <asm/types.h>
#include <pthread.h>
#include <errno.h>
#include "common.h"
#include "output.h"
#include "debug.h"
#include "misc.h"
#include "pes.h"
#include "writer.h"
/* ***************************** */
/* Makros/Constants */
/* ***************************** */
#define PES_AUDIO_PRIVATE_HEADER_SIZE 16 // consider maximum private header size.
#define PES_AUDIO_HEADER_SIZE (32 + PES_AUDIO_PRIVATE_HEADER_SIZE)
#define PES_AUDIO_PACKET_SIZE 2028
#define SPDIF_AUDIO_PACKET_SIZE (1024 * sizeof(unsigned int) * 2) // stereo 32bit samples.
#ifdef SAM_WITH_DEBUG
#define DTS_DEBUG
#else
#define DTS_SILENT
#endif
#ifdef DTS_DEBUG
static short debug_level = 0;
#define dts_printf(level, fmt, x...) do { \
if (debug_level >= level) printf("[%s:%s] " fmt, __FILE__, __FUNCTION__, ## x); } while (0)
#else
#define dts_printf(level, fmt, x...)
#endif
#ifndef DTS_SILENT
#define dts_err(fmt, x...) do { printf("[%s:%s] " fmt, __FILE__, __FUNCTION__, ## x); } while (0)
#else
#define dts_err(fmt, x...)
#endif
/* ***************************** */
/* Types */
/* ***************************** */
/* ***************************** */
/* Varaibles */
/* ***************************** */
/* ***************************** */
/* Prototypes */
/* ***************************** */
/* ***************************** */
/* MISC Functions */
/* ***************************** */
static int reset()
{
return 0;
}
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)
{
// check for DTS-HD
if (!strcmp((char *)(Data + pos), "\x64\x58\x20\x25"))
{
Size = pos;
break;
}
++pos;
}
#endif
// #define DO_BYTESWAP
#ifdef DO_BYTESWAP
/* 16-bit byte swap all data before injecting it */
for (i = 0; i < Size; i += 2)
{
uint8_t Tmp = Data[i];
Data[i] = Data[i + 1];
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;
}
/* ***************************** */
/* Writer Definition */
/* ***************************** */
static WriterCaps_t caps =
{
"dts",
eAudio,
"A_DTS",
AUDIO_ENCODING_DTS,
-1,
-1
};
struct Writer_s WriterAudioDTS =
{
&reset,
&writeData,
NULL,
&caps
};

View File

@@ -0,0 +1,173 @@
/*
* linuxdvb output/writer handling.
*
* crow 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 <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <unistd.h>
#include <fcntl.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/ioctl.h>
#include <linux/dvb/video.h>
#include <linux/dvb/audio.h>
#include <linux/dvb/stm_ioctls.h>
#include <memory.h>
#include <asm/types.h>
#include <pthread.h>
#include <errno.h>
#include <sys/uio.h>
#include "common.h"
#include "output.h"
#include "debug.h"
#include "misc.h"
#include "pes.h"
#include "writer.h"
/* ***************************** */
/* Makros/Constants */
/* ***************************** */
#ifdef SAM_WITH_DEBUG
#define H263_DEBUG
#else
#define H263_SILENT
#endif
#ifdef H263_DEBUG
static short debug_level = 0;
static const char *FILENAME = "h263.c";
#define h263_printf(level, fmt, x...) do { \
if (debug_level >= level) printf("[%s:%s] " fmt, FILENAME, __FUNCTION__, ## x); } while (0)
#else
#define h263_printf(level, fmt, x...)
#endif
#ifndef H263_SILENT
#define h263_err(fmt, x...) do { printf("[%s:%s] " fmt, FILENAME, __FUNCTION__, ## x); } while (0)
#else
#define h263_err(fmt, x...)
#endif
/* ***************************** */
/* Types */
/* ***************************** */
/* ***************************** */
/* Varaibles */
/* ***************************** */
/* ***************************** */
/* Prototypes */
/* ***************************** */
/* ***************************** */
/* MISC Functions */
/* ***************************** */
static int reset()
{
return 0;
}
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;
}
/* ***************************** */
/* Writer Definition */
/* ***************************** */
static WriterCaps_t caps_h263 =
{
"h263",
eVideo,
"V_H263",
VIDEO_ENCODING_H263,
-1,
-1
};
struct Writer_s WriterVideoH263 =
{
&reset,
&writeData,
NULL,
&caps_h263
};
static WriterCaps_t caps_flv =
{
"FLV",
eVideo,
"V_FLV",
VIDEO_ENCODING_FLV1,
-1,
-1
};
struct Writer_s WriterVideoFLV =
{
&reset,
&writeData,
NULL,
&caps_flv
};

View File

@@ -0,0 +1,480 @@
/*
* linuxdvb output/writer handling.
*
* konfetti 2010 based on linuxdvb.c code from libeplayer2
*
* 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 <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <unistd.h>
#include <fcntl.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/ioctl.h>
#include <sys/uio.h>
#include <linux/dvb/video.h>
#include <linux/dvb/audio.h>
#include <linux/dvb/stm_ioctls.h>
#include <memory.h>
#include <asm/types.h>
#include <pthread.h>
#include <errno.h>
#include <assert.h>
#include <stdint.h>
#include "common.h"
#include "output.h"
#include "debug.h"
#include "misc.h"
#include "pes.h"
#include "writer.h"
/* ***************************** */
/* Makros/Constants */
/* ***************************** */
#ifdef SAM_WITH_DEBUG
#define H264_DEBUG
#else
#define H264_SILENT
#endif
#ifdef H264_DEBUG
static short debug_level = 0;
#define h264_printf(level, fmt, x...) do { \
if (debug_level >= level) printf("[%s:%s] " fmt, __FILE__, __FUNCTION__, ## x); } while (0)
#else
#define h264_printf(level, fmt, x...)
#endif
#ifndef H264_SILENT
#define h264_err(fmt, x...) do { printf("[%s:%s] " fmt, __FILE__, __FUNCTION__, ## x); } while (0)
#else
#define h264_err(fmt, x...)
#endif
#define NALU_TYPE_PLAYER2_CONTAINER_PARAMETERS 24
#define CONTAINER_PARAMETERS_VERSION 0x00
/* ***************************** */
/* Types */
/* ***************************** */
typedef struct avcC_s
{
unsigned char Version; /* configurationVersion */
unsigned char Profile; /* AVCProfileIndication */
unsigned char Compatibility; /* profile_compatibility */
unsigned char Level; /* AVCLevelIndication */
unsigned char NalLengthMinusOne; /* held in bottom two bits */
unsigned char NumParamSets; /* held in bottom 5 bits */
unsigned char Params[1]; /* {length,params}{length,params}...sequence then picture*/
} avcC_t;
/* ***************************** */
/* Varaibles */
/* ***************************** */
const uint8_t Head[] = {0, 0, 0, 1};
static int32_t initialHeader = 1;
static uint32_t NalLengthBytes = 1;
static int avc3 = 0;
/* ***************************** */
/* Prototypes */
/* ***************************** */
/* ***************************** */
/* MISC Functions */
/* ***************************** */
// Please see: https://bugzilla.mozilla.org/show_bug.cgi?id=1105771
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");
return -1;
}
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");
return -1;
}
memcpy(&(pps[ppsIdx]), d + 4, nalLen);
ppsIdx += nalLen;
numPps += 1;
h264_printf(10, "PPS len[%u]...\n", nalLen);
}
d += 4 + nalLen;
}
uint32_t idx = 0;
*ppExtraData = malloc(7 + spsIdx + ppsIdx);
aExtraData = *ppExtraData;
aExtraData[idx++] = 0x1; // version
aExtraData[idx++] = sps[3]; // profile
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;
}
static int32_t reset()
{
initialHeader = 1;
avc3 = 0;
return 0;
}
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;
uint32_t TimeScale;
int32_t len = 0;
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) ||
(call->data[0] == 0xff && call->data[1] == 0xff && call->data[2] == 0xff && call->data[3] == 0xff))))
{
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;
/*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;
}
else if (!call->private_data || call->private_size < 7 || 1 != call->private_data[0])
{
h264_err("No valid private data available!\n");
return 0;
}
if (initialHeader)
{
uint8_t *private_data = call->private_data;
uint32_t private_size = call->private_size;
avcC_t *avcCHeader = (avcC_t *)private_data;
unsigned int i;
unsigned int ParamSets;
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);
if (private_data != call->private_data)
{
avc3 = 1;
avcCHeader = (avcC_t *)private_data;
}
}
HeaderData[ParametersLength++] = 0x00; // Start code
HeaderData[ParametersLength++] = 0x00;
HeaderData[ParametersLength++] = 0x01;
HeaderData[ParametersLength++] = NALU_TYPE_PLAYER2_CONTAINER_PARAMETERS;
// 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;
HeaderData[ParametersLength++] = (TimeDelta >> 8) & 0xff;
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);
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;
h264_printf(20, "avcC contents:\n");
h264_printf(20, " version: %d\n", avcCHeader->Version);
h264_printf(20, " profile: %d\n", avcCHeader->Profile);
h264_printf(20, " profile compatibility: %d\n", avcCHeader->Compatibility);
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);
iov[ic].iov_base = &avcCHeader->Params[ParamOffset + 2];
iov[ic++].iov_len = PsLength;
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);
iov[ic].iov_base = &avcCHeader->Params[ParamOffset + 2];
iov[ic++].iov_len = PsLength;
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;
switch (NalLengthBytes)
{
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);
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
{
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;
}
static int writeReverseData(void *_call)
{
WriterAVCallData_t *call = (WriterAVCallData_t *) _call;
h264_printf(10, "\n");
if (call == NULL)
{
h264_err("call data is NULL...\n");
return 0;
}
h264_printf(10, "VideoPts %lld\n", call->Pts);
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;
}
return 0;
}
/* ***************************** */
/* Writer Definition */
/* ***************************** */
static WriterCaps_t caps =
{
"h264",
eVideo,
"V_MPEG4/ISO/AVC",
VIDEO_ENCODING_H264,
-1,
-1
};
struct Writer_s WriterVideoH264 =
{
&reset,
&writeData,
&writeReverseData,
&caps
};

View File

@@ -0,0 +1,178 @@
/*
* linuxdvb output/writer handling.
*
* konfetti 2010 based on linuxdvb.c code from libeplayer2
*
* 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 <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <unistd.h>
#include <fcntl.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/ioctl.h>
#include <sys/uio.h>
#include <linux/dvb/video.h>
#include <linux/dvb/audio.h>
#include <linux/dvb/stm_ioctls.h>
#include <memory.h>
#include <asm/types.h>
#include <pthread.h>
#include <errno.h>
#include "common.h"
#include "output.h"
#include "debug.h"
#include "misc.h"
#include "pes.h"
#include "writer.h"
/* ***************************** */
/* Makros/Constants */
/* ***************************** */
#ifdef SAM_WITH_DEBUG
#define MP3_DEBUG
#else
#define MP3_SILENT
#endif
#ifdef MP3_DEBUG
static short debug_level = 0;
#define mp3_printf(level, fmt, x...) do { \
if (debug_level >= level) printf("[%s:%s] " fmt, __FILE__, __FUNCTION__, ## x); } while (0)
#else
#define mp3_printf(level, fmt, x...)
#endif
#ifndef MP3_SILENT
#define mp3_err(fmt, x...) do { printf("[%s:%s] " fmt, __FILE__, __FUNCTION__, ## x); } while (0)
#else
#define mp3_err(fmt, x...)
#endif
/* ***************************** */
/* Types */
/* ***************************** */
/* ***************************** */
/* Varaibles */
/* ***************************** */
/* ***************************** */
/* Prototypes */
/* ***************************** */
/* ***************************** */
/* MISC Functions */
/* ***************************** */
static int reset()
{
return 0;
}
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;
}
/* ***************************** */
/* Writer Definition */
/* ***************************** */
static WriterCaps_t caps_mp3 =
{
"mp3",
eAudio,
"A_MP3",
AUDIO_ENCODING_MP3
};
struct Writer_s WriterAudioMP3 =
{
&reset,
&writeData,
NULL,
&caps_mp3
};
static WriterCaps_t caps_mpegl3 =
{
"mpeg/l3",
eAudio,
"A_MPEG/L3",
AUDIO_ENCODING_MPEG2
};
struct Writer_s WriterAudioMPEGL3 =
{
&reset,
&writeData,
NULL,
&caps_mpegl3
};
static WriterCaps_t caps_vorbis =
{
"vorbis",
eAudio,
"A_VORBIS",
AUDIO_ENCODING_VORBIS
};
struct Writer_s WriterAudioVORBIS =
{
&reset,
&writeData,
NULL,
&caps_vorbis
};

View File

@@ -0,0 +1,181 @@
/*
* linuxdvb output/writer handling.
*
* konfetti 2010 based on linuxdvb.c code from libeplayer2
*
* 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 <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <unistd.h>
#include <fcntl.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/ioctl.h>
#include <sys/uio.h>
#include <linux/dvb/video.h>
#include <linux/dvb/audio.h>
#include <linux/dvb/stm_ioctls.h>
#include <memory.h>
#include <asm/types.h>
#include <pthread.h>
#include <errno.h>
#include "common.h"
#include "output.h"
#include "debug.h"
#include "misc.h"
#include "pes.h"
#include "writer.h"
/* ***************************** */
/* Makros/Constants */
/* ***************************** */
#ifdef SAM_WITH_DEBUG
#define MPEG2_DEBUG
#else
#define MPEG2_SILENT
#endif
#ifdef MPEG2_DEBUG
static short debug_level = 0;
#define mpeg2_printf(level, fmt, x...) do { \
if (debug_level >= level) printf("[%s:%s] " fmt, __FILE__, __FUNCTION__, ## x); } while (0)
#else
#define mpeg2_printf(level, fmt, x...)
#endif
#ifndef MPEG2_SILENT
#define mpeg2_err(fmt, x...) do { printf("[%s:%s] " fmt, __FILE__, __FUNCTION__, ## x); } while (0)
#else
#define mpeg2_err(fmt, x...)
#endif
/* ***************************** */
/* Types */
/* ***************************** */
/* ***************************** */
/* Varaibles */
/* ***************************** */
/* ***************************** */
/* Prototypes */
/* ***************************** */
/* ***************************** */
/* MISC Functions */
/* ***************************** */
static int reset()
{
return 0;
}
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)
{
len = l;
break;
}
len += l;
Position += PacketLength;
call->Pts = INVALID_PTS_VALUE;
}
mpeg2_printf(10, "< len %d\n", len);
return len;
}
/* ***************************** */
/* Writer Definition */
/* ***************************** */
static WriterCaps_t caps =
{
"mpeg2",
eVideo,
"V_MPEG2",
VIDEO_ENCODING_AUTO,
-1,
-1,
};
struct Writer_s WriterVideoMPEG2 =
{
&reset,
&writeData,
NULL,
&caps
};
static WriterCaps_t h264_caps =
{
"mpges_h264",
eVideo,
"V_MPEG2/H264",
VIDEO_ENCODING_H264,
-1,
-1
};
struct Writer_s WriterVideoMPEGH264 =
{
&reset,
&writeData,
NULL,
&h264_caps
};

View File

@@ -0,0 +1,354 @@
/*
* linuxdvb output/writer handling.
*
* konfetti 2010 based on linuxdvb.c code from libeplayer2
*
* 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 <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <unistd.h>
#include <fcntl.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/ioctl.h>
#include <sys/uio.h>
#include <linux/dvb/video.h>
#include <linux/dvb/audio.h>
#include <linux/dvb/stm_ioctls.h>
#include <memory.h>
#include <asm/types.h>
#include <pthread.h>
#include <errno.h>
#include <libavcodec/avcodec.h>
#include "common.h"
#include "output.h"
#include "debug.h"
#include "misc.h"
#include "pes.h"
#include "writer.h"
#include "pcm.h"
/* ***************************** */
/* Makros/Constants */
/* ***************************** */
#ifdef SAM_WITH_DEBUG
#define PCM_DEBUG
#else
#define PCM_SILENT
#endif
#ifdef PCM_DEBUG
static short debug_level = 0;
#define pcm_printf(level, fmt, x...) do { \
if (debug_level >= level) printf("[%s:%s] " fmt, __FILE__, __FUNCTION__, ## x); } while (0)
#else
#define pcm_printf(level, fmt, x...)
#endif
#ifndef PCM_SILENT
#define pcm_err(fmt, x...) do { printf("[%s:%s] " fmt, __FILE__, __FUNCTION__, ## x); } while (0)
#else
#define pcm_err(fmt, x...)
#endif
/* ***************************** */
/* Types */
/* ***************************** */
/* ***************************** */
/* Varaibles */
/* ***************************** */
static int32_t initialHeader = 1;
static uint32_t SubFrameLen = 0;
static uint32_t SubFramesPerPES = 0;
// reference: search for TypeLpcmDVDAudio in player/frame_parser/frame_parser_audio_lpcm.cpp
static const uint8_t clpcm_prv[14] =
{
0xA0, //sub_stream_id
0, 0, //resvd and UPC_EAN_ISRC stuff, unused
0x0A, //private header length
0, 9, //first_access_unit_pointer
0x00, //emph,rsvd,stereo,downmix
0x0F, //quantisation word length 1,2
0x0F, //audio sampling freqency 1,2
0, //resvd, multi channel type
0, //bit shift on channel GR2, assignment
0x80, //dynamic range control
0, 0 //resvd for copyright management
};
static uint8_t lpcm_prv[14];
static uint8_t breakBuffer[8192];
static uint32_t breakBufferFillSize = 0;
/* ***************************** */
/* Prototypes */
/* ***************************** */
/* ***************************** */
/* MISC Functions */
/* ***************************** */
static int32_t prepareClipPlay(int32_t uNoOfChannels, int32_t uSampleRate, int32_t uBitsPerSample, uint8_t bLittleEndian __attribute__((unused)))
{
printf("rate: %d ch: %d bits: %d (%d bps)\n",
uSampleRate/*Format->dwSamplesPerSec*/,
uNoOfChannels/*Format->wChannels*/,
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)
{
case 48000:
SubFrameLen = 40;
break;
case 96000:
lpcm_prv[8] |= 0x10;
SubFrameLen = 80;
break;
case 192000:
lpcm_prv[8] |= 0x20;
SubFrameLen = 160;
break;
case 44100:
lpcm_prv[8] |= 0x80;
SubFrameLen = 40;
break;
case 88200:
lpcm_prv[8] |= 0x90;
SubFrameLen = 80;
break;
case 176400:
lpcm_prv[8] |= 0xA0;
SubFrameLen = 160;
break;
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:
lpcm_prv[7] |= 0x20;
case 16:
break;
default:
printf("inappropriate bits per sample (%d) - must be 16 or 24\n", uBitsPerSample);
return 1;
}
return 0;
}
static int32_t reset()
{
initialHeader = 1;
return 0;
}
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 = writev(call->fd, iov, 3);
if (len < 0)
{
break;
}
}
free(injectBuffer);
return size;
}
/* ***************************** */
/* Writer Definition */
/* ***************************** */
static WriterCaps_t caps_pcm =
{
"pcm",
eAudio,
"A_PCM",
AUDIO_ENCODING_LPCMA
};
struct Writer_s WriterAudioPCM =
{
&reset,
&writeData,
NULL,
&caps_pcm
};
static WriterCaps_t caps_ipcm =
{
"ipcm",
eAudio,
"A_IPCM",
AUDIO_ENCODING_LPCMA
};
struct Writer_s WriterAudioIPCM =
{
&reset,
&writeData,
NULL,
&caps_ipcm
};

View File

@@ -0,0 +1,154 @@
/*
* linuxdvb output/writer handling.
*
* konfetti 2010 based on linuxdvb.c code from libeplayer2
*
* 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 <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <unistd.h>
#include <fcntl.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/ioctl.h>
#include <linux/dvb/video.h>
#include <linux/dvb/audio.h>
#include <linux/dvb/stm_ioctls.h>
#include <memory.h>
#include <asm/types.h>
#include <pthread.h>
#include <errno.h>
#include "common.h"
#include "output.h"
#include "debug.h"
#include "misc.h"
#include "pes.h"
#include "writer.h"
/* ***************************** */
/* Makros/Constants */
/* ***************************** */
/* ***************************** */
/* Types */
/* ***************************** */
/* ***************************** */
/* Varaibles */
/* ***************************** */
/* ***************************** */
/* Prototypes */
/* ***************************** */
/* ***************************** */
/* Functions */
/* ***************************** */
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
PutBits(&ld2, stream_id, 8); // Stream_id = Audio Stream
//4
if (-1 == size)
{
PutBits(&ld2, 0x0, 16);
}
else
{
PutBits(&ld2, size + 3 + (pts != INVALID_PTS_VALUE ? 5 : 0) + (pic_start_code ? (5) : 0), 16); // PES_packet_length
}
//6 = 4+2
PutBits(&ld2, 0x2, 2); // 10
PutBits(&ld2, 0x0, 2); // PES_Scrambling_control
PutBits(&ld2, 0x0, 1); // PES_Priority
PutBits(&ld2, 0x0, 1); // data_alignment_indicator
PutBits(&ld2, 0x0, 1); // Copyright
PutBits(&ld2, 0x0, 1); // Original or Copy
//7 = 6+1
if (pts != INVALID_PTS_VALUE)
{
PutBits(&ld2, 0x2, 2);
}
else
{
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
PutBits(&ld2, 0x0, 1); // additional_copy_ingo_flag
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);
PutBits(&ld2, (pts >> 30) & 0x7, 3);
PutBits(&ld2, 0x1, 1);
PutBits(&ld2, (pts >> 15) & 0x7fff, 15);
PutBits(&ld2, 0x1, 1);
PutBits(&ld2, pts & 0x7fff, 15);
PutBits(&ld2, 0x1, 1);
}
//14 = 9+5
if (pic_start_code)
{
PutBits(&ld2, 0x0, 8);
PutBits(&ld2, 0x0, 8);
PutBits(&ld2, 0x1, 8); // Start Code
PutBits(&ld2, pic_start_code & 0xff, 8); // 00, for picture start
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);
}

View File

@@ -0,0 +1,263 @@
/*
* linuxdvb output/writer handling.
*
* konfetti 2010 based on linuxdvb.c code from libeplayer2
*
* 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 <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <unistd.h>
#include <fcntl.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/ioctl.h>
#include <sys/uio.h>
#include <linux/dvb/video.h>
#include <linux/dvb/audio.h>
#include <linux/dvb/stm_ioctls.h>
#include <memory.h>
#include <asm/types.h>
#include <pthread.h>
#include <errno.h>
#include "common.h"
#include "output.h"
#include "debug.h"
#include "misc.h"
#include "pes.h"
#include "writer.h"
/* ***************************** */
/* Makros/Constants */
/* ***************************** */
#define WMV3_PRIVATE_DATA_LENGTH 4
#define METADATA_STRUCT_A_START 12
#define METADATA_STRUCT_B_START 24
#define METADATA_STRUCT_B_FRAMERATE_START 32
#define METADATA_STRUCT_C_START 8
#define VC1_SEQUENCE_LAYER_METADATA_START_CODE 0x80
#define VC1_FRAME_START_CODE 0x0d
#ifdef SAM_WITH_DEBUG
#define VC1_DEBUG
#else
#define VC1_SILENT
#endif
#ifdef VC1_DEBUG
static short debug_level = 0;
#define vc1_printf(level, fmt, x...) do { \
if (debug_level >= level) printf("[%s:%s] " fmt, __FILE__, __FUNCTION__, ## x); } while (0)
#else
#define vc1_printf(level, fmt, x...)
#endif
#ifndef VC1_SILENT
#define vc1_err(fmt, x...) do { printf("[%s:%s] " fmt, __FILE__, __FUNCTION__, ## x); } while (0)
#else
#define vc1_err(fmt, x...)
#endif
/* ***************************** */
/* Types */
/* ***************************** */
static const unsigned char SequenceLayerStartCode[] = {0x00, 0x00, 0x01, VC1_SEQUENCE_LAYER_METADATA_START_CODE};
static const unsigned char Metadata[] =
{
0x00, 0x00, 0x00, 0xc5,
0x04, 0x00, 0x00, 0x00,
0xc0, 0x00, 0x00, 0x00, /* Struct C set for for advanced profile*/
0x00, 0x00, 0x00, 0x00, /* Struct A */
0x00, 0x00, 0x00, 0x00,
0x0c, 0x00, 0x00, 0x00,
0x60, 0x00, 0x00, 0x00, /* Struct B */
0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00
};
/* ***************************** */
/* Varaibles */
/* ***************************** */
static int initialHeader = 1;
static unsigned char FrameHeaderSeen = 0;
/* ***************************** */
/* Prototypes */
/* ***************************** */
/* ***************************** */
/* MISC Functions */
/* ***************************** */
static int reset()
{
initialHeader = 1;
FrameHeaderSeen = 0;
return 0;
}
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 = 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));
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 = 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;
}
/* ***************************** */
/* Writer Definition */
/* ***************************** */
static WriterCaps_t caps =
{
"vc1",
eVideo,
"V_VC1",
VIDEO_ENCODING_VC1,
-1,
-1
};
struct Writer_s WriterVideoVC1 =
{
&reset,
&writeData,
NULL,
&caps
};

View File

@@ -0,0 +1,146 @@
/*
* linuxdvb output/writer handling.
*
* konfetti 2010 based on linuxdvb.c code from libeplayer2
*
* 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 <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <unistd.h>
#include <fcntl.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/ioctl.h>
#include <linux/dvb/video.h>
#include <linux/dvb/audio.h>
#include <memory.h>
#include <asm/types.h>
#include <pthread.h>
#include <errno.h>
#include "common.h"
#include "output.h"
#include "debug.h"
#include "stm_ioctls.h"
#include "misc.h"
#include "pes.h"
#include "writer.h"
/* ***************************** */
/* Makros/Constants */
/* ***************************** */
#ifdef SAM_WITH_DEBUG
#define VORBIS_DEBUG
#else
#define VORBIS_SILENT
#endif
#ifdef VORBIS_DEBUG
static short debug_level = 1;
#define vorbis_printf(level, fmt, x...) do { \
if (debug_level >= level) printf("[%s:%s] " fmt, __FILE__, __FUNCTION__, ## x); } while (0)
#else
#define vorbis_printf(level, fmt, x...)
#endif
#ifndef VORBIS_SILENT
#define vorbis_err(fmt, x...) do { printf("[%s:%s] " fmt, __FILE__, __FUNCTION__, ## x); } while (0)
#else
#define vorbis_err(fmt, x...)
#endif
/* ***************************** */
/* Types */
/* ***************************** */
/* ***************************** */
/* Varaibles */
/* ***************************** */
/* ***************************** */
/* Prototypes */
/* ***************************** */
/* ***************************** */
/* MISC Functions */
/* ***************************** */
static int reset()
{
return 0;
}
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;
}
/* ***************************** */
/* Writer Definition */
/* ***************************** */
static WriterCaps_t caps_vorbis =
{
"vorbis",
eAudio,
"A_VORBIS",
AUDIO_ENCODING_VORBIS,
-1,
-1
};
struct Writer_s WriterAudioVORBIS =
{
&reset,
&writeData,
NULL,
&caps_vorbis
};

View File

@@ -0,0 +1,191 @@
/*
* linuxdvb output/writer handling.
*
* konfetti 2010 based on linuxdvb.c code from libeplayer2
*
* 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 <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <unistd.h>
#include <fcntl.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/ioctl.h>
#include <sys/uio.h>
#include <linux/dvb/video.h>
#include <linux/dvb/audio.h>
#include <linux/dvb/stm_ioctls.h>
#include <memory.h>
#include <asm/types.h>
#include <pthread.h>
#include <errno.h>
#include "common.h"
#include "output.h"
#include "debug.h"
#include "misc.h"
#include "pes.h"
#include "writer.h"
/* ***************************** */
/* Makros/Constants */
/* ***************************** */
#ifdef SAM_WITH_DEBUG
#define WMA_DEBUG
#else
#define WMA_SILENT
#endif
#ifdef WMA_DEBUG
static short debug_level = 0;
#define wma_printf(level, fmt, x...) do { \
if (debug_level >= level) printf("[%s:%s] " fmt, __FILE__, __FUNCTION__, ## x); } while (0)
#else
#define wma_printf(level, fmt, x...)
#endif
#ifndef WMA_SILENT
#define wma_err(fmt, x...) do { printf("[%s:%s] " fmt, __FILE__, __FUNCTION__, ## x); } while (0)
#else
#define wma_err(fmt, x...)
#endif
/* ***************************** */
/* Types */
/* ***************************** */
/* ***************************** */
/* Varaibles */
/* ***************************** */
static int initialHeader = 1;
/* ***************************** */
/* Prototypes */
/* ***************************** */
/* ***************************** */
/* MISC Functions */
/* ***************************** */
static int reset()
{
initialHeader = 1;
return 0;
}
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);
iov[1].iov_base = call->private_data;
iov[1].iov_len = call->private_size;
len = writev(call->fd, iov, 2);
initialHeader = 0;
}
if (len > -1 && call->len > 0 && call->data)
{
unsigned char PesHeader[PES_MAX_HEADER_SIZE];
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;
ssize_t l = writev(call->fd, iov, 2);
len = (l > -1) ? len + l : l;
}
wma_printf(10, "wma < %d\n", len);
return len;
}
/* ***************************** */
/* Writer Definition */
/* ***************************** */
static WriterCaps_t capsWMAPRO =
{
"wma/pro",
eAudio,
"A_WMA/PRO",
AUDIO_ENCODING_WMA,
-1,
-1
};
struct Writer_s WriterAudioWMAPRO =
{
&reset,
&writeData,
NULL,
&capsWMAPRO
};
static WriterCaps_t capsWMA =
{
"wma",
eAudio,
"A_WMA",
AUDIO_ENCODING_WMA,
-1,
-1
};
struct Writer_s WriterAudioWMA =
{
&reset,
&writeData,
NULL,
&capsWMA
};

View File

@@ -0,0 +1,254 @@
/*
* linuxdvb output/writer handling.
*
* konfetti 2010 based on linuxdvb.c code from libeplayer2
*
* 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 <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <unistd.h>
#include <fcntl.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/ioctl.h>
#include <sys/uio.h>
#include <linux/dvb/video.h>
#include <linux/dvb/audio.h>
#include <linux/dvb/stm_ioctls.h>
#include <memory.h>
#include <asm/types.h>
#include <pthread.h>
#include <errno.h>
#include "common.h"
#include "output.h"
#include "debug.h"
#include "misc.h"
#include "pes.h"
#include "writer.h"
/* ***************************** */
/* Makros/Constants */
/* ***************************** */
#define WMV3_PRIVATE_DATA_LENGTH 4
#define METADATA_STRUCT_A_START 12
#define METADATA_STRUCT_B_START 24
#define METADATA_STRUCT_B_FRAMERATE_START 32
#define METADATA_STRUCT_C_START 8
#ifdef SAM_WITH_DEBUG
#define WMV_DEBUG
#else
#define WMV_SILENT
#endif
#ifdef WMV_DEBUG
static short debug_level = 0;
#define wmv_printf(level, fmt, x...) do { \
if (debug_level >= level) printf("[%s:%s] " fmt, __FILE__, __FUNCTION__, ## x); } while (0)
#else
#define wmv_printf(level, fmt, x...)
#endif
#ifndef WMV_SILENT
#define wmv_err(fmt, x...) do { printf("[%s:%s] " fmt, __FILE__, __FUNCTION__, ## x); } while (0)
#else
#define wmv_err(fmt, x...)
#endif
/* ***************************** */
/* Types */
/* ***************************** */
typedef struct
{
unsigned char privateData[WMV3_PRIVATE_DATA_LENGTH];
unsigned int width;
unsigned int height;
unsigned int framerate;
} awmv_t;
static const unsigned char Metadata[] =
{
0x00, 0x00, 0x00, 0xc5,
0x04, 0x00, 0x00, 0x00,
0xc0, 0x00, 0x00, 0x00, /* Struct C set for for advanced profile*/
0x00, 0x00, 0x00, 0x00, /* Struct A */
0x00, 0x00, 0x00, 0x00,
0x0c, 0x00, 0x00, 0x00,
0x60, 0x00, 0x00, 0x00, /* Struct B */
0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00
};
/* ***************************** */
/* Varaibles */
/* ***************************** */
static int initialHeader = 1;
/* ***************************** */
/* Prototypes */
/* ***************************** */
/* ***************************** */
/* MISC Functions */
/* ***************************** */
static int reset()
{
initialHeader = 1;
return 0;
}
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)
{
unsigned char PesPacket[PES_MIN_HEADER_SIZE + 128];
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;
*PesPtr++ = (private_data.height >> 16) & 0xff;
*PesPtr++ = private_data.height >> 24;
*PesPtr++ = (private_data.width >> 0) & 0xff;
*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;
unsigned char insertSampleHeader = 1;
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;
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;
unsigned int PrivateHeaderLength;
PrivateHeaderLength = InsertVideoPrivateDataHeader(&PesHeader[HeaderLength],
call->len);
/* Update PesLength */
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;
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;
}
/* ***************************** */
/* Writer Definition */
/* ***************************** */
static WriterCaps_t caps =
{
"wmv",
eVideo,
"V_WMV",
VIDEO_ENCODING_WMV,
-1,
-1
};
struct Writer_s WriterVideoWMV =
{
&reset,
&writeData,
NULL,
&caps
};

View File

@@ -0,0 +1,144 @@
/*
* 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 <stdlib.h>
#include <string.h>
#include "writer.h"
/* ***************************** */
/* Makros/Constants */
/* ***************************** */
#ifdef SAM_WITH_DEBUG
#define WRITER_DEBUG
#else
#define WRITER_SILENT
#endif
#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 */
/* ***************************** */
static Writer_t *AvailableWriter[] =
{
&WriterAudioIPCM,
&WriterAudioPCM,
&WriterAudioMP3,
&WriterAudioMPEGL3,
&WriterAudioAC3,
&WriterAudioAAC,
&WriterAudioDTS,
&WriterAudioWMA,
&WriterAudioVORBIS,
&WriterVideoMPEG2,
&WriterVideoMPEGH264,
&WriterVideoH264,
&WriterVideoDIVX,
&WriterVideoFOURCC,
&WriterVideoMSCOMP,
&WriterVideoWMV,
&WriterVideoH263,
&WriterVideoFLV,
&WriterVideoVC1,
NULL
};
// &WriterAudioFLAC,
/* ***************************** */
/* Prototypes */
/* ***************************** */
/* ***************************** */
/* Functions */
/* ***************************** */
Writer_t *getWriter(char *encoding)
{
int i;
for (i = 0; AvailableWriter[i] != NULL; i++)
{
if (strcmp(AvailableWriter[i]->caps->textEncoding, encoding) == 0)
{
writer_printf(50, "%s: found writer \"%s\" for \"%s\"\n", __func__, AvailableWriter[i]->caps->name, 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)
{
writer_printf(50, "%s: found writer \"%s\"\n", __func__, AvailableWriter[i]->caps->name);
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)
{
writer_printf(50, "%s: found writer \"%s\"\n", __func__, AvailableWriter[i]->caps->name);
return AvailableWriter[i];
}
}
writer_printf(1, "%s: no writer found\n", __func__);
return NULL;
}