add libeplayer3 from tdt git

This imports libeplayer3 as of commit 9160371ccc6 (2012-02-02)
git://gitorious.org/open-duckbox-project-sh4/tdt.git
It would be better to use the original repo, but I need too many
changes for now :-(
This commit is contained in:
Stefan Seyfried
2012-02-14 23:01:24 +01:00
parent 16caec5a44
commit e4a2e1cbb7
49 changed files with 13696 additions and 0 deletions

File diff suppressed because it is too large Load Diff

353
libeplayer3/output/output.c Normal file
View File

@@ -0,0 +1,353 @@
/*
* 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 */
/* ***************************** */
#define OUTPUT_DEBUG
#ifdef OUTPUT_DEBUG
static short debug_level = 0;
#define output_printf(level, x...) do { \
if (debug_level >= level) printf(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 = __FILE__;
/* ***************************** */
/* Types */
/* ***************************** */
/* ***************************** */
/* Varaibles */
/* ***************************** */
/* ***************************** */
/* 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];
else if (!strcmp("video", port))
context->output->video = AvailableOutput[i];
else if (!strcmp("subtitle", port))
context->output->subtitle = AvailableOutput[i];
break;
}
}
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");
if (!ret) { // success or not executed, dunn care
if (context->playback->isAudio)
ret = context->output->audio->Command(context, OUTPUT_PLAY, "audio");
if (!ret) { // success or not executed, dunn care
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");
//if (context->playback->isSubtitle)
// ret |= context->output->subtitle->Command(context, OUTPUT_PAUSE, "subtitle");
} 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);
//if (context->playback->isSubtitle)
// return context->output->subtitle->Command(context, OUTPUT_PTS, "subtitle");
} 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");
} 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");
//if (context->playback->isSubtitle)
// ret |= context->output->subtitle->Command(context, OUTPUT_PAUSE, "subtitle");
} 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);
//if (context->playback->isSubtitle)
// return context->output->subtitle->Command(context, OUTPUT_GET_FRAME_COUNT, "subtitle");
} 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,
NULL,
NULL,
&Command,
};

View File

@@ -0,0 +1,845 @@
/*
* 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 <pthread.h>
#include <errno.h>
#include "common.h"
#include "output.h"
#include "subtitle.h"
/* ***************************** */
/* Makros/Constants */
/* ***************************** */
#define SUBTITLE_DEBUG
#ifdef SUBTITLE_DEBUG
static short debug_level = 10;
#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[] = "subtitle.c";
/*
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 */
/* ***************************** */
struct sub_t {
char * text;
unsigned long long int pts;
unsigned long int milliDuration;
};
/* ***************************** */
/* Varaibles */
/* ***************************** */
static pthread_mutex_t mutex;
static pthread_t thread_sub;
void* clientData = NULL;
void (*clientFunction) (long int, size_t, char *, void *);
static struct sub_t subPuffer[PUFFERSIZE];
static int readPointer = 0;
static int writePointer = 0;
static int hasThreadStarted = 0;
static int isSubtitleOpened = 0;
static int screen_width = 0;
static int screen_height = 0;
static int destStride = 0;
static int shareFramebuffer = 0;
static int framebufferFD = -1;
static unsigned char* destination = NULL;
/* ***************************** */
/* 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);
}
void replace_all(char ** string, char * search, char * replace) {
int len = 0;
char * ptr = NULL;
char tempString[512];
char newString[512];
newString[0] = '\0';
if ((string == NULL) || (*string == NULL) || (search == NULL) || (replace == NULL))
{
subtitle_err("null pointer passed\n");
return;
}
strncpy(tempString, *string, 511);
tempString[511] = '\0';
free(*string);
while ((ptr = strstr(tempString, search)) != NULL) {
len = ptr - tempString;
strncpy(newString, tempString, len);
newString[len] = '\0';
strcat(newString, replace);
len += strlen(search);
strcat(newString, tempString+len);
strcpy(tempString, newString);
}
subtitle_printf(20, "strdup in line %d\n", __LINE__);
if(newString[0] != '\0')
*string = strdup(newString);
else
*string = strdup(tempString);
}
int subtitle_ParseASS (char **Line) {
char* Text;
int i;
char* ptr1;
if ((Line == NULL) || (*Line == NULL))
{
subtitle_err("null pointer passed\n");
return cERR_SUBTITLE_ERROR;
}
Text = strdup(*Line);
subtitle_printf(10, "-> Text = %s\n", *Line);
ptr1 = Text;
for (i=0; i < 9 && *ptr1 != '\0'; ptr1++) {
subtitle_printf(20, "%s",ptr1);
if (*ptr1 == ',')
i++;
}
free(*Line);
*Line = strdup(ptr1);
free(Text);
replace_all(Line, "\\N", "\n");
replace_all(Line, "{\\i1}", "<i>");
replace_all(Line, "{\\i0}", "</i>");
subtitle_printf(10, "<- Text=%s\n", *Line);
return cERR_SUBTITLE_NO_ERROR;
}
int subtitle_ParseSRT (char **Line) {
if ((Line == NULL) || (*Line == NULL))
{
subtitle_err("null pointer passed\n");
return cERR_SUBTITLE_ERROR;
}
subtitle_printf(20, "-> Text=%s\n", *Line);
replace_all(Line, "\x0d", "");
replace_all(Line, "\n\n", "\\N");
replace_all(Line, "\n", "");
replace_all(Line, "\\N", "\n");
replace_all(Line, "<EFBFBD>", "oe");
replace_all(Line, "<EFBFBD>", "ae");
replace_all(Line, "<EFBFBD>", "ue");
replace_all(Line, "<EFBFBD>", "Oe");
replace_all(Line, "<EFBFBD>", "Ae");
replace_all(Line, "<EFBFBD>", "Ue");
replace_all(Line, "<EFBFBD>", "ss");
subtitle_printf(10, "<- Text=%s\n", *Line);
return cERR_SUBTITLE_NO_ERROR;
}
int subtitle_ParseSSA (char **Line) {
if ((Line == NULL) || (*Line == NULL))
{
subtitle_err("null pointer passed\n");
return cERR_SUBTITLE_ERROR;
}
subtitle_printf(20, "-> Text=%s\n", *Line);
replace_all(Line, "\x0d", "");
replace_all(Line, "\n\n", "\\N");
replace_all(Line, "\n", "");
replace_all(Line, "\\N", "\n");
replace_all(Line, "<EFBFBD>", "oe");
replace_all(Line, "<EFBFBD>", "ae");
replace_all(Line, "<EFBFBD>", "ue");
replace_all(Line, "<EFBFBD>", "Oe");
replace_all(Line, "<EFBFBD>", "Ae");
replace_all(Line, "<EFBFBD>", "Ue");
replace_all(Line, "<EFBFBD>", "ss");
subtitle_printf(10, "<- Text=%s\n", *Line);
return cERR_SUBTITLE_NO_ERROR;
}
void addSub(Context_t *context, char * text, unsigned long long int pts, unsigned long int milliDuration) {
int count = 20;
subtitle_printf(50, "index %d\n", writePointer);
if(context && context->playback && !context->playback->isPlaying)
{
subtitle_err("1. aborting ->no playback\n");
return;
}
if (text == NULL)
{
subtitle_err("null pointer passed\n");
return;
}
if (pts == 0)
{
subtitle_err("pts 0\n");
return;
}
if (milliDuration == 0)
{
subtitle_err("duration 0\n");
return;
}
while (subPuffer[writePointer].text != NULL) {
//List is full, wait till we got some free space
if(context && context->playback && !context->playback->isPlaying)
{
subtitle_err("2. aborting ->no playback\n");
return;
}
/* konfetti: we dont want to block forever here. if no buffer
* is available we start ring from the beginning and loose some stuff
* which is acceptable!
*/
subtitle_printf(10, "waiting on free buffer %d - %d (%d) ...\n", writePointer, readPointer, count);
usleep(10000);
count--;
if (count == 0)
{
subtitle_err("abort waiting on buffer...\n");
break;
}
}
subtitle_printf(20, "from mkv: %s pts:%lld milliDuration:%lud\n",text,pts,milliDuration);
getMutex(__LINE__);
if (count == 0)
{
int i;
subtitle_err("freeing not delivered data\n");
//Reset all
readPointer = 0;
writePointer = 0;
for (i = 0; i < PUFFERSIZE; i++) {
if (subPuffer[i].text != NULL)
free(subPuffer[i].text);
subPuffer[i].text = NULL;
subPuffer[i].pts = 0;
subPuffer[i].milliDuration = 0;
}
}
subPuffer[writePointer].text = strdup(text);
subPuffer[writePointer].pts = pts;
subPuffer[writePointer].milliDuration = milliDuration;
writePointer++;
if (writePointer == PUFFERSIZE)
writePointer = 0;
if (writePointer == readPointer)
{
/* this should not happen, and means that there is nor reader or
* the reader has performance probs ;)
* the recovery is done at startup of this function - but next time
*/
subtitle_err("ups something went wrong. no more readers? \n");
}
releaseMutex(__LINE__);
subtitle_printf(10, "<\n");
}
int getNextSub(char ** text, unsigned long long int * pts, long int * milliDuration) {
subtitle_printf(50, "index %d\n", readPointer);
if (text == NULL)
{
subtitle_err("null pointer passed\n");
return cERR_SUBTITLE_ERROR;
}
getMutex(__LINE__);
if (subPuffer[readPointer].text == NULL)
{
/* this is acutally not an error, because it may happen
* that there is no subtitle for a while
*/
subtitle_printf(200, "null in subPuffer\n");
releaseMutex(__LINE__);
return cERR_SUBTITLE_ERROR;
}
*text = strdup(subPuffer[readPointer].text);
free(subPuffer[readPointer].text);
subPuffer[readPointer].text = NULL;
*pts = subPuffer[readPointer].pts;
subPuffer[readPointer].pts = 0;
*milliDuration = subPuffer[readPointer].milliDuration;
subPuffer[readPointer].milliDuration = 0;
readPointer++;
if (readPointer == PUFFERSIZE)
readPointer = 0;
if (writePointer == readPointer)
{
/* this may happen, in normal case the reader is ones ahead the
* writer. So this is the normal case that we eat the data
* and have the reader reached.
*/
subtitle_printf(20, "ups something went wrong. no more writers? \n");
}
releaseMutex(__LINE__);
subtitle_printf(20, "readPointer %d\n",readPointer);
subtitle_printf(10, "<\n");
return cERR_SUBTITLE_NO_ERROR;
}
/* **************************** */
/* Worker Thread */
/* **************************** */
static void* SubtitleThread(void* data) {
Context_t *context = (Context_t*) data;
char * subText = NULL;
long int subMilliDuration = 0;
unsigned long long int subPts = 0;
unsigned long long int Pts = 0;
subtitle_printf(10, "\n");
while ( context->playback->isCreationPhase ) {
subtitle_err("Thread waiting for end of init phase...\n");
usleep(1000);
}
subtitle_printf(10, "done\n");
while ( context &&
context->playback &&
context->playback->isPlaying) {
int curtrackid = -1;
if (context && context->manager && context->manager->subtitle)
context->manager->subtitle->Command(context, MANAGER_GET, &curtrackid);
subtitle_printf(50, "curtrackid %d\n", curtrackid);
if (curtrackid >= 0) {
if (getNextSub(&subText, &subPts, &subMilliDuration) != 0) {
usleep(500000);
continue;
}
if (context && context->playback)
context->playback->Command(context, PLAYBACK_PTS, &Pts);
else return NULL;
if(Pts > subPts) {
subtitle_printf(10,"subtitle is to late, ignoring\n");
if(subText != NULL)
free(subText);
continue;
}
subtitle_printf(20, "Pts:%llu < subPts%llu duration %ld\n", Pts, subPts,subMilliDuration);
while ( context &&
context->playback &&
context->playback->isPlaying &&
Pts < subPts) {
unsigned long int diff = subPts - Pts;
diff = (diff*1000)/90.0;
subtitle_printf(50, "DIFF: %lud\n", diff);
if(diff > 100)
usleep(diff);
if (context && context->playback)
context->playback->Command(context, PLAYBACK_PTS, &Pts);
else
{
subtitle_err("no playback ? terminated?\n");
break;
}
subtitle_printf(20, "cur: %llu wanted: %llu\n", Pts, subPts);
}
if ( context &&
context->playback &&
context->playback->isPlaying &&
subText != NULL ) {
if(clientFunction != NULL)
clientFunction(subMilliDuration, strlen(subText), subText, clientData);
else
subtitle_printf(10, "writing Sub failed (%ld) (%d) \"%s\"\n", subMilliDuration, strlen(subText), subText);
free(subText);
}
} /* trackID >= 0 */
else //Wait
usleep(500000);
} /* outer while */
subtitle_printf(0, "has ended\n");
hasThreadStarted = 0;
return NULL;
}
/* ***************************** */
/* Functions */
/* ***************************** */
static int Write(void* _context, void *data) {
Context_t * context = (Context_t *) _context;
char * Encoding = NULL;
char * Text;
SubtitleOut_t * out;
int DataLength;
unsigned long long int Pts;
float Duration;
subtitle_printf(10, "\n");
if (data == NULL)
{
subtitle_err("null pointer passed\n");
return cERR_SUBTITLE_ERROR;
}
out = (SubtitleOut_t*) data;
if (out->type == eSub_Txt)
{
Text = strdup((const char*) out->u.text.data);
} else
{
/* fixme handle gfx subs from container_ass and send it to
* the callback. this must be implemented also in e2/neutrino
* then.
*/
subtitle_err("subtitle gfx currently not handled\n");
return cERR_SUBTITLE_ERROR;
}
DataLength = out->u.text.len;
Pts = out->pts;
Duration = out->duration;
context->manager->subtitle->Command(context, MANAGER_GETENCODING, &Encoding);
if (Encoding == NULL)
{
subtitle_err("encoding unknown\n");
free(Text);
return cERR_SUBTITLE_ERROR;
}
subtitle_printf(20, "Encoding:%s Text:%s Len:%d\n", Encoding,Text, DataLength);
if ( !strncmp("S_TEXT/SSA", Encoding, 10) ||
!strncmp("S_SSA", Encoding, 5))
subtitle_ParseSSA(&Text);
else if(!strncmp("S_TEXT/ASS", Encoding, 10) ||
!strncmp("S_AAS", Encoding, 5))
subtitle_ParseASS(&Text);
else if(!strncmp("S_TEXT/SRT", Encoding, 10) ||
!strncmp("S_SRT", Encoding, 5))
subtitle_ParseSRT(&Text);
else
{
subtitle_err("unknown encoding %s\n", Encoding);
return cERR_SUBTITLE_ERROR;
}
subtitle_printf(10, "Text:%s Duration:%f\n", Text,Duration);
addSub(context, Text, Pts, Duration * 1000);
free(Text);
free(Encoding);
subtitle_printf(10, "<\n");
return cERR_SUBTITLE_NO_ERROR;
}
static int subtitle_Open(context) {
int i;
subtitle_printf(10, "\n");
if (isSubtitleOpened == 1)
{
subtitle_err("already opened! ignoring\n");
return cERR_SUBTITLE_ERROR;
}
getMutex(__LINE__);
//Reset all
readPointer = 0;
writePointer = 0;
for (i = 0; i < PUFFERSIZE; i++) {
subPuffer[i].text = NULL;
subPuffer[i].pts = 0;
subPuffer[i].milliDuration = 0;
}
isSubtitleOpened = 1;
releaseMutex(__LINE__);
subtitle_printf(10, "<\n");
return cERR_SUBTITLE_NO_ERROR;
}
static int subtitle_Close(Context_t* context) {
int i;
subtitle_printf(10, "\n");
getMutex(__LINE__);
//Reset all
readPointer = 0;
writePointer = 0;
for (i = 0; i < PUFFERSIZE; i++) {
if (subPuffer[i].text != NULL)
free(subPuffer[i].text);
subPuffer[i].text = NULL;
subPuffer[i].pts = 0;
subPuffer[i].milliDuration = 0;
}
isSubtitleOpened = 0;
releaseMutex(__LINE__);
subtitle_printf(10, "<\n");
return cERR_SUBTITLE_NO_ERROR;
}
static int subtitle_Play(Context_t* context) {
subtitle_printf(10, "\n");
if (hasThreadStarted == 0)
{
pthread_attr_t attr;
pthread_attr_init(&attr);
pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
if (pthread_create (&thread_sub, &attr, &SubtitleThread, (void*) context) != 0)
{
subtitle_err("Error creating thread\n");
hasThreadStarted = 0;
} else
{
subtitle_printf(10, "Created thread\n");
hasThreadStarted = 1;
}
}
else
{
subtitle_err("thread already created.\n");
return cERR_SUBTITLE_ERROR;
}
subtitle_printf(10, "<\n");
return cERR_SUBTITLE_NO_ERROR;
}
static int subtitle_Stop(context) {
int wait_time = 20;
int i;
subtitle_printf(10, "\n");
while ( (hasThreadStarted != 0) && (--wait_time) > 0 ) {
subtitle_printf(10, "Waiting for subtitle thread to terminate itself, will try another %d times\n", wait_time);
usleep(100000);
}
if (wait_time == 0) {
subtitle_err("Timeout waiting for thread!\n");
return cERR_SUBTITLE_ERROR;
}
hasThreadStarted = 0;
/* konfetti: thread has ended, so nobody will eat the date...
* free the data...
*/
getMutex(__LINE__);
//Reset all
readPointer = 0;
writePointer = 0;
for (i = 0; i < PUFFERSIZE; i++) {
if (subPuffer[i].text != NULL)
free(subPuffer[i].text);
subPuffer[i].text = NULL;
subPuffer[i].pts = 0;
subPuffer[i].milliDuration = 0;
}
releaseMutex(__LINE__);
subtitle_printf(10, "<\n");
return cERR_SUBTITLE_NO_ERROR;
}
void subtitle_SignalConnect(void (*fkt) (long int, size_t, char *, void *))
{
subtitle_printf(10, "%p\n", fkt);
clientFunction = fkt;
}
void subtitle_SignalConnectBuffer(void* data)
{
subtitle_printf(10, "%p\n", data);
clientData = data;
}
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: {
ret = subtitle_Play(context);
break;
}
case OUTPUT_STOP: {
ret = subtitle_Stop(context);
break;
}
case OUTPUT_SWITCH: {
subtitle_err("Subtitle Switch not implemented\n");
ret = cERR_SUBTITLE_ERROR;
break;
}
case OUTPUT_GET_SUBTITLE_OUTPUT: {
SubtitleOutputDef_t* out = (SubtitleOutputDef_t*)argument;
out->screen_width = screen_width;
out->screen_height = screen_height;
out->shareFramebuffer = shareFramebuffer;
out->framebufferFD = framebufferFD;
out->destination = destination;
out->destStride = destStride;
break;
}
case OUTPUT_SET_SUBTITLE_OUTPUT: {
SubtitleOutputDef_t* out = (SubtitleOutputDef_t*)argument;
screen_width = out->screen_width;
screen_height = out->screen_height;
shareFramebuffer = out->shareFramebuffer;
framebufferFD = out->framebufferFD;
destination = out->destination;
destStride = out->destStride;
break;
}
case OUTPUT_SUBTITLE_REGISTER_FUNCTION: {
subtitle_SignalConnect(argument);
break;
}
case OUTPUT_SUBTITLE_REGISTER_BUFFER: {
subtitle_SignalConnectBuffer(argument);
break;
}
case OUTPUT_FLUSH: {
subtitle_err("Subtitle Flush not implemented\n");
ret = cERR_SUBTITLE_ERROR;
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 };
struct Output_s SubtitleOutput = {
"Subtitle",
&Command,
&Write,
SubtitleCapabilitis,
};

View File

@@ -0,0 +1,290 @@
/*
* 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 */
/* ***************************** */
#define AAC_HEADER_LENGTH 7
#define AAC_DEBUG
#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
*/
/*
AvailableBytes = Writen Bytes
Sync = Bits.Get(11);
if (Sync == AAC_AUDIO_LOAS_ASS_SYNC_WORD{0x2b7})
Type = AAC_AUDIO_LOAS_FORMAT;
FrameSize = Bits.Get(13) + AAC_LOAS_ASS_SYNC_LENGTH_HEADER_SIZE{3};
if (FrameSize > AAC_LOAS_ASS_MAX_FRAME_SIZE{8192})
// ERROR
AvailableBytes = AvailableBytes - AAC_LOAS_ASS_MAX_FRAME_SIZE{8192};
ImplicitSbrExtension = true;
ExplicitSbrExtension = false;
if (AvailableBytes > 0)
useSameStreamMux = Bits->Get(1);
else
useSameStreamMux = true;
if ( !useSameStreamMux )
audioMuxVersion = Bits->Get(1); // Has to be 0
if (!audioMuxVersion)
// only get program 0 and layer 0 information ...
Bits->FlushUnseen(1 + 6 + 4 + 3); // allStreamSameTimeFraming, numSubFrames, numProgram, numLayer
audioObjectType = Bits->Get(5);
if ((audioObjectType != AAC_AUDIO_PROFILE_LC{2}) && (audioObjectType != AAC_AUDIO_PROFILE_SBR{5}))
// Error
samplingFrequencyIndex = Bits->Get(4);
channelConfiguration = Bits->Get(4);
if (audioObjectType == AAC_AUDIO_PROFILE_SBR{5})
ImplicitSbrExtension = false;
ExplicitSbrExtension = true;
samplingFrequencyIndex = Bits->Get(4);
audioObjectType = Bits->Get(5);
if (audioObjectType != AAC_AUDIO_PROFILE_LC{2})
// Error
*SampleCount = 1024 * ((ImplicitSbrExtension || ExplicitSbrExtension)?2:1);
*SamplingFrequency *= (ImplicitSbrExtension?2:1);
else
Sync |= Bits.Get(1) << 11;
if (Sync == AAC_AUDIO_ADTS_SYNC_WORD{0xfff})
Type = AAC_AUDIO_ADTS_FORMAT; // Supports only LC
ID = Bits.Get(1);
Layer = Bits.Get(2); // Has to be 0
protection_absent = Bits.Get(1);
profile_ObjectType = Bits.Get(2);
if ((profile_ObjectType+1) != AAC_AUDIO_PROFILE_LC)
return
sampling_frequency_index = Bits.Get(4);
SamplingFrequency = aac_sample_rates[sampling_frequency_index] * 2;
Bits.FlushUnseen(1); //private_bit
channel_configuration = Bits.Get(3);
Bits.FlushUnseen(1 + 1 + 1 + 1); //original/copy, home, copyright_identification_bit, copyright_identification_start
FrameSize = Bits.Get(13); // aac_frame_length
if (FrameSize < AAC_ADTS_MIN_FRAME_SIZE{7})
// Error
Bits.FlushUnseen(11); //adts_buffer_fullness
no_raw_data_blocks_in_frame = Bits.Get(2);
// multiple the sample count by two in case a sbr object is present
SampleCount = (no_raw_data_blocks_in_frame + 1) * 1024 * 2 ;
else
Sync |= Bits.Get(4) << 12;
if (Sync == AAC_AUDIO_LOAS_EPASS_SYNC_WORD{0x4de1})
Type = AAC_AUDIO_LOAS_FORMAT;
...
else
Sync |= Bits.Get(16) << 16;
if (Sync == AAC_AUDIO_ADIF_SYNC_WORD{0x41444946})
Type = AAC_AUDIO_ADIF_FORMAT;
//not supported
*/
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
};
/* ***************************** */
/* 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];
unsigned char ExtraData[AAC_HEADER_LENGTH];
unsigned int PacketLength;
aac_printf(10, "\n");
if (call == NULL)
{
aac_err("call data is NULL...\n");
return 0;
}
aac_printf(10, "AudioPts %lld\n", call->Pts);
PacketLength = call->len + AAC_HEADER_LENGTH;
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 == NULL)
{
aac_printf(10, "private_data = NULL\n");
call->private_data = DefaultAACHeader;
call->private_size = AAC_HEADER_LENGTH;
}
memcpy (ExtraData, call->private_data, AAC_HEADER_LENGTH);
ExtraData[3] |= (PacketLength >> 12) & 0x3;
ExtraData[4] = (PacketLength >> 3) & 0xff;
ExtraData[5] |= (PacketLength << 5) & 0xe0;
unsigned int HeaderLength = InsertPesHeader (PesHeader, PacketLength, AAC_AUDIO_PES_START_CODE, call->Pts, 0);
unsigned char* PacketStart = malloc(HeaderLength + sizeof(ExtraData) + call->len);
memcpy (PacketStart, PesHeader, HeaderLength);
memcpy (PacketStart + HeaderLength, ExtraData, sizeof(ExtraData));
memcpy (PacketStart + HeaderLength + sizeof(ExtraData), call->data, call->len);
aac_printf(100, "H %d d %d ExtraData %d\n", HeaderLength, call->len, sizeof(ExtraData));
int len = write(call->fd, PacketStart, HeaderLength + call->len + sizeof(ExtraData));
free(PacketStart);
return len;
}
/* ***************************** */
/* Writer Definition */
/* ***************************** */
static WriterCaps_t caps = {
"aac",
eAudio,
"A_AAC",
AUDIO_ENCODING_AAC
};
struct Writer_s WriterAudioAAC = {
&reset,
&writeData,
NULL,
&caps
};

View File

@@ -0,0 +1,151 @@
/*
* 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 */
/* ***************************** */
#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 */
/* ***************************** */
/* ***************************** */
/* 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;
}
int HeaderLength = InsertPesHeader (PesHeader, call->len, PRIVATE_STREAM_1_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);
return len;
}
/* ***************************** */
/* Writer Definition */
/* ***************************** */
static WriterCaps_t caps_ac3 = {
"ac3",
eAudio,
"A_AC3",
AUDIO_ENCODING_AC3,
};
struct Writer_s WriterAudioAC3 = {
&reset,
&writeData,
NULL,
&caps_ac3,
};

View File

@@ -0,0 +1,215 @@
/*
* 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 */
/* ***************************** */
#define DIVX_DEBUG
#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 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 int ExtraLength = 0;
unsigned char Version = 5;
unsigned int FakeStartCode = (Version << 8) | PES_VERSION_FAKE_START_CODE;
unsigned int HeaderLength = 0;
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;
}
divx_printf(10, "AudioPts %lld\n", call->Pts);
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;
}
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));
if (initialHeader) ExtraLength = call->private_size;
HeaderLength = InsertPesHeader (PesHeader, call->len, MPEG_VIDEO_PES_START_CODE, call->Pts, FakeStartCode);
unsigned char* PacketStart = malloc(call->len + HeaderLength + FakeHeaderLength + ExtraLength);
memcpy (PacketStart, PesHeader, HeaderLength);
memcpy (PacketStart + HeaderLength, FakeHeaders, FakeHeaderLength);
if (initialHeader) {
memcpy (PacketStart + HeaderLength + FakeHeaderLength, call->private_data, call->private_size);
initialHeader = 0;
}
memcpy (PacketStart + HeaderLength + FakeHeaderLength + ExtraLength, call->data, call->len);
int len = write(call->fd, PacketStart ,call->len + HeaderLength + FakeHeaderLength + ExtraLength);
free(PacketStart);
divx_printf(10, "xvid_Write < len=%d\n", len);
return len;
}
/* ***************************** */
/* Writer Definition */
/* ***************************** */
static WriterCaps_t mpeg4p2_caps = {
"mscomp",
eVideo,
"V_MSCOMP",
VIDEO_ENCODING_MPEG4P2,
};
struct Writer_s WriterVideoMSCOMP = {
&reset,
&writeData,
NULL,
&mpeg4p2_caps,
};
static WriterCaps_t fourcc_caps = {
"fourcc",
eVideo,
"V_MS/VFW/FOURCC",
VIDEO_ENCODING_MPEG4P2,
};
struct Writer_s WriterVideoFOURCC = {
&reset,
&writeData,
NULL,
&fourcc_caps,
};
static WriterCaps_t divx_caps = {
"divx",
eVideo,
"V_MKV/XVID",
VIDEO_ENCODING_MPEG4P2,
};
struct Writer_s WriterVideoDIVX = {
&reset,
&writeData,
NULL,
&divx_caps,
};

View File

@@ -0,0 +1,168 @@
/*
* 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 */
/* ***************************** */
#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.
#define DTS_DEBUG
#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 int writeData(void* _call)
{
WriterAVCallData_t* call = (WriterAVCallData_t*) _call;
int i = 0;
unsigned char PesHeader[PES_AUDIO_HEADER_SIZE];
unsigned char * Data = 0;
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;
}
memset (PesHeader, '0', PES_AUDIO_HEADER_SIZE);
Data = (unsigned char *) malloc(call->len);
memcpy(Data, call->data, call->len);
/* 16-bit byte swap all data before injecting it */
for (i=0; i< call->len; i+=2)
{
unsigned char Tmp = Data[i];
Data[i] = Data[i+1];
Data[i+1] = Tmp;
}
int HeaderLength = InsertPesHeader (PesHeader, call->len, MPEG_AUDIO_PES_START_CODE/*PRIVATE_STREAM_1_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);
free(Data);
dts_printf(10, "< len %d\n", len);
return len;
}
/* ***************************** */
/* Writer Definition */
/* ***************************** */
static WriterCaps_t caps = {
"dts",
eAudio,
"A_DTS",
AUDIO_ENCODING_DTS,
};
struct Writer_s WriterAudioDTS = {
&reset,
&writeData,
NULL,
&caps,
};

View File

@@ -0,0 +1,151 @@
/*
* 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 */
/* ***************************** */
#define FLAC_DEBUG
#ifdef FLAC_DEBUG
static short debug_level = 1;
#define flac_printf(level, fmt, x...) do { \
if (debug_level >= level) printf("[%s:%s] " fmt, __FILE__, __FUNCTION__, ## x); } while (0)
#else
#define flac_printf(level, fmt, x...)
#endif
#ifndef FLAC_SILENT
#define flac_err(fmt, x...) do { printf("[%s:%s] " fmt, __FILE__, __FUNCTION__, ## x); } while (0)
#else
#define flac_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];
flac_printf(10, "\n");
if (call == NULL)
{
flac_err("call data is NULL...\n");
return 0;
}
flac_printf(10, "AudioPts %lld\n", call->Pts);
if ((call->data == NULL) || (call->len <= 0))
{
flac_err("parsing NULL Data. ignoring...\n");
return 0;
}
if (call->fd < 0)
{
flac_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);
flac_printf(10, "flac_Write-< len=%d\n", len);
return len;
}
/* ***************************** */
/* Writer Definition */
/* ***************************** */
static WriterCaps_t caps_flac = {
"flac",
eAudio,
"A_FLAC",
AUDIO_ENCODING_LPCM, //AUDIO_ENCODING_FLAC,
};
struct Writer_s WriterAudioFLAC = {
&reset,
&writeData,
NULL,
&caps_flac,
};

View File

@@ -0,0 +1,196 @@
/*
* framebuffer output/writer handling.
*
* This is a hacky implementation of a framebuffer output for the subtitling.
* This is ment as a POV, later this should be implemented in enigma2 and
* neutrino.
*
* 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 <memory.h>
#include <asm/types.h>
#include <pthread.h>
#include <errno.h>
#include <sys/mman.h>
#include "common.h"
#include "output.h"
#include "debug.h"
#include "misc.h"
#include "writer.h"
/* ***************************** */
/* Makros/Constants */
/* ***************************** */
#define FB_DEBUG
#ifdef FB_DEBUG
static short debug_level = 10;
#define fb_printf(level, fmt, x...) do { \
if (debug_level >= level) printf("[%s:%s] " fmt, __FILE__, __FUNCTION__, ## x); } while (0)
#else
#define fb_printf(level, fmt, x...)
#endif
#ifndef FB_SILENT
#define fb_err(fmt, x...) do { printf("[%s:%s] " fmt, __FILE__, __FUNCTION__, ## x); } while (0)
#else
#define fb_err(fmt, x...)
#endif
#define _r(c) ((c)>>24)
#define _g(c) (((c)>>16)&0xFF)
#define _b(c) (((c)>>8)&0xFF)
#define _a(c) ((c)&0xFF)
/* ***************************** */
/* Types */
/* ***************************** */
/* ***************************** */
/* Varaibles */
/* ***************************** */
/* ***************************** */
/* Prototypes */
/* ***************************** */
/* ***************************** */
/* MISC Functions */
/* ***************************** */
/* ***************************** */
/* Writer Functions */
/* ***************************** */
static int reset()
{
return 0;
}
static int writeData(void* _call)
{
unsigned char r;
unsigned char g;
unsigned char b;
unsigned char a;
int x,y;
int res = 0;
unsigned char* dst;
WriterFBCallData_t* call = (WriterFBCallData_t*) _call;
fb_printf(100, "\n");
if (call == NULL)
{
fb_err("call data is NULL...\n");
return 0;
}
if (call->destination == NULL)
{
fb_err("file pointer < 0. ignoring ...\n");
return 0;
}
if (call->data != NULL)
{
unsigned int opacity = 255 - ((unsigned int)_a(call->color));
unsigned int r = (unsigned int)_r(call->color);
unsigned int g = (unsigned int)_g(call->color);
unsigned int b = (unsigned int) _b(call->color);
int src_stride = call->Stride;
int dst_stride = call->destStride;
int dst_delta = dst_stride - call->Width*4;
int x,y;
const unsigned char *src = call->data;
unsigned char *dst = call->destination + (call->y * dst_stride + call->x * 4);
unsigned int k,ck,t;
fb_printf(100, "x %d\n", call->x);
fb_printf(100, "y %d\n", call->y);
fb_printf(100, "width %d\n", call->Width);
fb_printf(100, "height %d\n", call->Height);
fb_printf(100, "stride %d\n", call->Stride);
fb_printf(100, "color %d\n", call->color);
fb_printf(100, "data %p\n", call->data);
fb_printf(100, "dest %p\n", call->destination);
fb_printf(100, "dest.stride %d\n", call->destStride);
fb_printf(100, "r 0x%hhx, g 0x%hhx, b 0x%hhx, a 0x%hhx, opacity %d\n", r, g, b, a, opacity);
for (y=0;y<call->Height;y++)
{
for (x = 0; x < call->Width; x++)
{
k = ((unsigned)src[x]) * opacity / 255;
ck = 255 - k;
t = *dst;
*dst++ = (k*b + ck*t) / 255;
t = *dst;
*dst++ = (k*g + ck*t) / 255;
t = *dst;
*dst++ = (k*r + ck*t) / 255;
*dst++ = 0;
}
dst += dst_delta;
src += src_stride;
}
} else
{
for (y = 0; y < call->Height; y++)
memset(call->destination + ((call->y + y) * call->destStride) + call->x * 4, 0, call->Width * 4);
}
fb_printf(100, "< %d\n", res);
return res;
}
/* ***************************** */
/* Writer Definition */
/* ***************************** */
static WriterCaps_t caps = {
"framebuffer",
eGfx,
"framebuffer",
0,
};
struct Writer_s WriterFramebuffer = {
&reset,
&writeData,
NULL,
&caps,
};

View File

@@ -0,0 +1,176 @@
/*
* 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 "common.h"
#include "output.h"
#include "debug.h"
#include "stm_ioctls.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 int reset()
{
return 0;
}
static int writeData(void* _call)
{
WriterAVCallData_t* call = (WriterAVCallData_t*) _call;
unsigned char PesHeader[PES_MAX_HEADER_SIZE];
unsigned char DataCopy[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;
unsigned char *PacketData = call->data - HeaderLength;
memcpy(DataCopy, PacketData, HeaderLength);
memcpy(PacketData, PesHeader, HeaderLength);
len = write(call->fd, PacketData, call->len + HeaderLength);
memcpy(PacketData, DataCopy, HeaderLength);
h263_printf(10, "< len %d\n", len);
return len;
}
/* ***************************** */
/* Writer Definition */
/* ***************************** */
static WriterCaps_t caps_h263 = {
"h263",
eVideo,
"V_H263",
VIDEO_ENCODING_H263,
};
struct Writer_s WriterVideoH263 = {
&reset,
&writeData,
NULL,
&caps_h263,
};
static WriterCaps_t caps_flv = {
"FLV",
eVideo,
"V_FLV",
VIDEO_ENCODING_FLV1,
};
struct Writer_s WriterVideoFLV = {
&reset,
&writeData,
NULL,
&caps_flv,
};

View File

@@ -0,0 +1,439 @@
/*
* 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 */
/* ***************************** */
#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 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 unsigned char Head[] = {0, 0, 0, 1};
static int initialHeader = 1;
static unsigned int NalLengthBytes = 1;
/* ***************************** */
/* Prototypes */
/* ***************************** */
/* ***************************** */
/* MISC Functions */
/* ***************************** */
static int reset()
{
initialHeader = 1;
return 0;
}
static int writeData(void* _call)
{
WriterAVCallData_t* call = (WriterAVCallData_t*) _call;
unsigned char* PacketStart = NULL;
unsigned int PacketStartSIZE = 0;
unsigned int HeaderLength;
unsigned char PesHeader[PES_MAX_HEADER_SIZE];
unsigned long long int VideoPts;
unsigned int TimeDelta;
unsigned int TimeScale;
int len = 0;
static int NoOtherBeginningFound = 1;
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;
}
if((call->data[0] == 0x00 && call->data[1] == 0x00 && call->data[2] == 0x00 && call->data[3] == 0x01) ||
(call->data[0] == 0x00 && call->data[1] == 0x00 && call->data[2] == 0x01 && NoOtherBeginningFound) ||
(call->data[0] == 0xff && call->data[1] == 0xff && call->data[2] == 0xff && call->data[3] == 0xff))
{
unsigned int FakeStartCode = (call->Version << 8) | PES_VERSION_FAKE_START_CODE;
unsigned int PrivateLength=0;
if(initialHeader)PrivateLength = call->private_size;
HeaderLength = InsertPesHeader(PesHeader, call->len,
MPEG_VIDEO_PES_START_CODE, call->Pts, FakeStartCode);
/*Hellmaster1024: some packets will only be accepted by the player if we send one byte more than
data is available. The content of this byte does not matter. It will be ignored
by the player */
unsigned char *PacketData = malloc(HeaderLength + call->len + PrivateLength + 1);
memcpy(PacketData, PesHeader, HeaderLength);
if(initialHeader){
memcpy (PacketData + HeaderLength, call->private_data, PrivateLength);
initialHeader=0;
}
memcpy (PacketData + HeaderLength + PrivateLength, call->data, call->len);
len = write(call->fd, PacketData, call->len + HeaderLength + PrivateLength + 1);
free(PacketData);
return len;
}
NoOtherBeginningFound = 0;
if (initialHeader)
{
unsigned char* HeaderData = malloc(BUFFER_SIZE+PADDING_LENGTH);
avcC_t* avcCHeader = (avcC_t*)call->private_data;
int i;
unsigned int ParamSets;
unsigned int ParamOffset;
unsigned int InitialHeaderLength = 0;
unsigned int ParametersLength;
if (avcCHeader == NULL)
{
h264_err("private_data NULL\n");
free(HeaderData);
return -1;
}
if (avcCHeader->Version != 1)
h264_err("Error unknown avcC version (%x). Expect problems.\n", avcCHeader->Version);
ParametersLength = 0;
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
HeaderLength = InsertPesHeader (PesHeader, ParametersLength, MPEG_VIDEO_PES_START_CODE, INVALID_PTS_VALUE, 0);
PacketStart = malloc(HeaderLength + ParametersLength);
PacketStartSIZE = HeaderLength + ParametersLength;
memcpy (PacketStart, PesHeader, HeaderLength);
memcpy (PacketStart + HeaderLength, HeaderData, ParametersLength);
len += write (call->fd, PacketStart, HeaderLength + ParametersLength);
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;
for (i = 0; i < ParamSets; i++) {
unsigned int PsLength = (avcCHeader->Params[ParamOffset] << 8) + avcCHeader->Params[ParamOffset+1];
h264_printf(20, " sps %d has length %d\n", i, PsLength);
if (HeaderLength + InitialHeaderLength + sizeof(Head) > PacketStartSIZE) {
PacketStart = realloc(PacketStart, HeaderLength + InitialHeaderLength + sizeof(Head));
PacketStartSIZE = HeaderLength + InitialHeaderLength + sizeof(Head);
}
memcpy (PacketStart + HeaderLength + InitialHeaderLength, Head, sizeof(Head));
InitialHeaderLength += sizeof(Head);
if (HeaderLength + InitialHeaderLength + PsLength > PacketStartSIZE) {
PacketStart = realloc(PacketStart, HeaderLength + InitialHeaderLength + PsLength);
PacketStartSIZE = HeaderLength + InitialHeaderLength + PsLength;
}
memcpy (PacketStart + HeaderLength + InitialHeaderLength, &avcCHeader->Params[ParamOffset+2], PsLength);
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);
if (HeaderLength + InitialHeaderLength + sizeof(Head) > PacketStartSIZE) {
PacketStart = realloc(PacketStart, HeaderLength + InitialHeaderLength + sizeof(Head));
PacketStartSIZE = HeaderLength + InitialHeaderLength + sizeof(Head);
}
memcpy (PacketStart + HeaderLength + InitialHeaderLength, Head, sizeof(Head));
InitialHeaderLength += sizeof(Head);
if (HeaderLength + InitialHeaderLength + PsLength > PacketStartSIZE) {
PacketStart = realloc(PacketStart, HeaderLength + InitialHeaderLength + PsLength);
PacketStartSIZE = HeaderLength + InitialHeaderLength + PsLength;
}
memcpy (PacketStart + HeaderLength + InitialHeaderLength, &avcCHeader->Params[ParamOffset+2], PsLength);
InitialHeaderLength += PsLength;
ParamOffset += PsLength+2;
}
HeaderLength = InsertPesHeader (PesHeader, InitialHeaderLength, MPEG_VIDEO_PES_START_CODE, INVALID_PTS_VALUE, 0);
memcpy (PacketStart, PesHeader, HeaderLength);
len += write (call->fd, PacketStart, HeaderLength + InitialHeaderLength);
initialHeader = 0;
free(PacketStart);
free(HeaderData);
}
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;
NalLength = (NalLengthBytes == 1) ? NalData[0] :
(NalLengthBytes == 2) ? (NalData[0] << 8) | NalData[1] :
(NalLengthBytes == 3) ? (NalData[0] << 16) | (NalData[1] << 8) | NalData[2] :
(NalData[0] << 24) | (NalData[1] << 16) | (NalData[2] << 8) | NalData[3];
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 + NalLengthBytes;
while (NalLength > 0) {
unsigned int PacketLength = (NalLength < BUFFER_SIZE) ? NalLength : BUFFER_SIZE;
int ExtraLength = 0;
unsigned char* PacketStart;
NalLength -= PacketLength;
if (NalPresent) {
PacketStart = malloc(sizeof(Head) + PacketLength);
memcpy (PacketStart + sizeof(Head), call->data + VideoPosition, PacketLength);
VideoPosition += PacketLength;
memcpy (PacketStart, Head, sizeof(Head));
ExtraLength = sizeof(Head);
} else {
PacketStart = malloc(PacketLength);
memcpy (PacketStart, call->data + VideoPosition, PacketLength);
VideoPosition += PacketLength;
}
PacketLength += ExtraLength;
h264_printf (20, " pts=%llu\n", VideoPts);
HeaderLength = InsertPesHeader (PesHeader, PacketLength, MPEG_VIDEO_PES_START_CODE, VideoPts, 0);
unsigned char* WritePacketStart = malloc(HeaderLength + PacketLength);
memcpy (WritePacketStart, PesHeader, HeaderLength);
memcpy (WritePacketStart+HeaderLength, PacketStart, PacketLength);
free(PacketStart);
PacketLength += HeaderLength;
len += write (call->fd, WritePacketStart, PacketLength);
free(WritePacketStart);
NalPresent = 0;
VideoPts = INVALID_PTS_VALUE;
}
}
} 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;
#ifndef old_reverse_playback
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;
#else
return 0;
#endif
}
/* ***************************** */
/* Writer Definition */
/* ***************************** */
static WriterCaps_t caps = {
"h264",
eVideo,
"V_MPEG4/ISO/AVC",
VIDEO_ENCODING_H264,
};
struct Writer_s WriterVideoH264 = {
&reset,
&writeData,
&writeReverseData,
&caps,
};

View File

@@ -0,0 +1,126 @@
/*
* 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 "common.h"
#include "output.h"
#include "debug.h"
#include "stm_ioctls.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;
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,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 <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 */
/* ***************************** */
#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];
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;
}
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);
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,
};

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 <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 */
/* ***************************** */
#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;
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(1) {
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);
int HeaderLength = InsertPesHeader (PesHeader, PacketLength, 0xe0, call->Pts, 0);
unsigned char* PacketStart = malloc(PacketLength + 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;
if (Position == call->len)
break;
}
mpeg2_printf(10, "< len %d\n", len);
return len;
}
/* ***************************** */
/* Writer Definition */
/* ***************************** */
static WriterCaps_t caps = {
"mpeg2",
eVideo,
"V_MPEG2",
VIDEO_ENCODING_AUTO,
};
struct Writer_s WriterVideoMPEG2 = {
&reset,
&writeData,
NULL,
&caps,
};
static WriterCaps_t h264_caps = {
"mpges_h264",
eVideo,
"V_MPEG2/H264",
VIDEO_ENCODING_H264,
};
struct Writer_s WriterVideoMPEGH264 = {
&reset,
&writeData,
NULL,
&h264_caps,
};

View File

@@ -0,0 +1,345 @@
/*
* 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"
#include "pcm.h"
/* ***************************** */
/* Makros/Constants */
/* ***************************** */
#define PCM_DEBUG
#ifdef PCM_DEBUG
static short debug_level = 1;
#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 int initialHeader = 1;
static unsigned int SubFrameLen = 0;
static unsigned int SubFramesPerPES = 0;
static const unsigned char clpcm_pes[18] = { 0x00, 0x00, 0x01, 0xBD, //start code
0x07, 0xF1, //pes length
0x81, 0x81, 0x09, //fixed
0x21, 0x00, 0x01, 0x00, 0x01, //PTS marker bits
0x1E, 0x60, 0x0A, //first pes only, 0xFF after
0xFF
};
static const unsigned char 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 unsigned char lpcm_pes[18];
static unsigned char lpcm_prv[14];
static unsigned char breakBuffer[8192];
static unsigned int breakBufferFillSize = 0;
/* ***************************** */
/* Prototypes */
/* ***************************** */
/* ***************************** */
/* MISC Functions */
/* ***************************** */
static int prepareClipPlay(int uNoOfChannels, int uSampleRate, int uBitsPerSample, int bLittleEndian)
{
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_pes, clpcm_pes, sizeof(lpcm_pes));
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
SubFramesPerPES = ((2048-sizeof(lpcm_pes))-sizeof(lpcm_prv))/SubFrameLen;
SubFrameLen *= SubFramesPerPES;
lpcm_pes[4] = ((SubFrameLen+(sizeof(lpcm_pes)-6)+sizeof(lpcm_prv))>>8) & 0xFF;
lpcm_pes[5] = (SubFrameLen+(sizeof(lpcm_pes)-6)+sizeof(lpcm_prv)) & 0xFF;
//set number of channels
lpcm_prv[10] = uNoOfChannels - 1;
switch(uBitsPerSample) {
case 16: break;
case 24: lpcm_prv[7] |= 0x20;
break;
default: printf("inappropriate bits per sample (%d) - must be 16 or 24\n",uBitsPerSample);
return 1;
}
return 0;
}
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];
pcm_printf(10, "\n");
if (call == NULL)
{
pcm_err("call data is NULL...\n");
return 0;
}
pcm_printf(10, "AudioPts %lld\n", call->Pts);
if ((call->data == NULL) || (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)
{
initialHeader = 0;
prepareClipPlay(pcmPrivateData->uNoOfChannels, pcmPrivateData->uSampleRate,
pcmPrivateData->uBitsPerSample, pcmPrivateData->bLittleEndian);
}
unsigned char * buffer = call->data;
int size = call->len;
//printf("PCM %d size SubFrameLen=%d\n", size, SubFrameLen);
unsigned int qty;
unsigned int n;
unsigned int injectBufferSize = sizeof(lpcm_pes) + sizeof(lpcm_prv) + SubFrameLen;
unsigned char * injectBuffer = (unsigned char *)malloc(sizeof(unsigned char)*injectBufferSize);
unsigned char * injectBufferDataPointer = &injectBuffer[sizeof(lpcm_pes)+sizeof(lpcm_prv)];
int 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(unsigned char) * breakBufferFillSize);
//printf("PCM %s - Unplayed=%d\n", __FUNCTION__, breakBufferFillSize);
break;
}
//get first PES's worth
if(breakBufferFillSize > 0)
{
memcpy(injectBufferDataPointer, breakBuffer, sizeof(unsigned char)*breakBufferFillSize);
memcpy(&injectBufferDataPointer[breakBufferFillSize], &buffer[pos], sizeof(unsigned char)*(SubFrameLen - breakBufferFillSize));
pos += (SubFrameLen - breakBufferFillSize);
breakBufferFillSize = 0;
} else
{
memcpy(injectBufferDataPointer, &buffer[pos], sizeof(unsigned char)*SubFrameLen);
pos += SubFrameLen;
}
//write the PES header
memcpy(injectBuffer, lpcm_pes, sizeof(lpcm_pes));
//write the private data area
memcpy(&injectBuffer[sizeof(lpcm_pes)], lpcm_prv, sizeof(lpcm_prv));
//write the PCM data
if(pcmPrivateData->uBitsPerSample == 16) {
for(n=0; n<SubFrameLen; n+=2) {
unsigned char tmp;
tmp=injectBufferDataPointer[n];
injectBufferDataPointer[n]=injectBufferDataPointer[n+1];
injectBufferDataPointer[n+1]=tmp;
}
} else {
//A1cA1bA1a-B1cB1bB1a-A2cA2bA2a-B2cB2bB2a to A1aA1bB1aB1b.A2aA2bB2aB2b-A1cB1cA2cB2c
for(n=0; n<SubFrameLen; n+=12) {
unsigned char tmp[12];
tmp[ 0]=injectBufferDataPointer[n+2];
tmp[ 1]=injectBufferDataPointer[n+1];
tmp[ 8]=injectBufferDataPointer[n+0];
tmp[ 2]=injectBufferDataPointer[n+5];
tmp[ 3]=injectBufferDataPointer[n+4];
tmp[ 9]=injectBufferDataPointer[n+3];
tmp[ 4]=injectBufferDataPointer[n+8];
tmp[ 5]=injectBufferDataPointer[n+7];
tmp[10]=injectBufferDataPointer[n+6];
tmp[ 7]=injectBufferDataPointer[n+11];
tmp[ 8]=injectBufferDataPointer[n+10];
tmp[11]=injectBufferDataPointer[n+9];
memcpy(&injectBufferDataPointer[n],tmp,12);
}
}
//increment err... subframe count?
lpcm_prv[1] = ((lpcm_prv[1]+SubFramesPerPES) & 0x1F);
//disable PES to save calculating correct values
lpcm_pes[7] = 0x01;
//kill off first A_PKT only fields in PES header
lpcm_pes[14] = 0xFF;
lpcm_pes[15] = 0xFF;
lpcm_pes[16] = 0xFF;
write(call->fd, injectBuffer, injectBufferSize);
//printf("PCM %d bytes injected\n", injectBufferSize);
//Hexdump(injectBuffer, 126);
}
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,156 @@
/*
* 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 */
/* ***************************** */
/* ***************************** */
/* 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)
printf("%s: Packet bigger than 63.9K eeeekkkkk\n",__FUNCTION__);
PutBits(&ld2,0x0 ,8);
PutBits(&ld2,0x0 ,8);
PutBits(&ld2,0x1 ,8); // Start Code
PutBits(&ld2,stream_id ,8); // Stream_id = Audio Stream
//4
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,292 @@
/*
* 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 */
/* ***************************** */
#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
#define VC1_DEBUG
#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 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;
}
vc1_printf(10, "VideoPts %lld\n", call->Pts);
vc1_printf(10, "Got Private Size %d\n", call->private_size);
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;
}
if (initialHeader) {
unsigned char PesPacket[PES_MIN_HEADER_SIZE+128];
unsigned char* PesPtr;
unsigned int MetadataLength;
unsigned int crazyFramerate = 0;
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);
{
PesPtr = &PesPacket[PES_MIN_HEADER_SIZE];
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;
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);
}
{
int i;
/* For VC1 the codec private data is a standard vc1 sequence header so we just copy it to the output */
memcpy (&PesPacket[PES_MIN_HEADER_SIZE], call->private_data, call->private_size);
vc1_printf(10, "Private Data:\n");
for (i = 0; i < call->private_size; i++)
vc1_printf(10, "%02x ", PesPacket[PES_MIN_HEADER_SIZE+i]);
vc1_printf(10, "\n");
int HeaderLength = InsertPesHeader (PesPacket, call->private_size, VC1_VIDEO_PES_START_CODE, INVALID_PTS_VALUE, 0);
len = write(call->fd, PesPacket, call->private_size + HeaderLength);
}
initialHeader = 0;
}
if(call->len > 0 && call->data) {
int Position = 0;
unsigned char insertSampleHeader = 1;
while(1) {
int PacketLength = (call->len - Position) <= MAX_PES_PACKET_SIZE ?
(call->len - Position) : MAX_PES_PACKET_SIZE;
int Remaining = call->len - Position - PacketLength;
vc1_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) {
const unsigned char Vc1FrameStartCode[] = {0, 0, 1, VC1_FRAME_START_CODE};
/*
vc1_printf(10, "Data Start: {00 00 01 0d} - ");
int i;
for (i = 0; i < 4; i++) vc1_printf(10, "%02x ", call->data[i]);
vc1_printf(10, "\n");
*/
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;
}
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;
if (Position == call->len)
break;
}
}
vc1_printf(10, "< %d\n", len);
return len;
}
/* ***************************** */
/* Writer Definition */
/* ***************************** */
static WriterCaps_t caps = {
"vc1",
eVideo,
"V_VC1",
VIDEO_ENCODING_VC1
};
struct Writer_s WriterVideoVC1 = {
&reset,
&writeData,
NULL,
&caps
};

View File

@@ -0,0 +1,151 @@
/*
* 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 */
/* ***************************** */
#define VORBIS_DEBUG
#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,
};
struct Writer_s WriterAudioVORBIS = {
&reset,
&writeData,
NULL,
&caps_vorbis,
};

View File

@@ -0,0 +1,183 @@
/*
* 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 */
/* ***************************** */
#define WMA_DEBUG
#ifdef WMA_DEBUG
static short debug_level = 10;
#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];
int HeaderLength;
if ((call->private_size <= 0) || (call->private_data == NULL))
{
wma_err("private NULL.\n");
return -1;
}
HeaderLength = InsertPesHeader (PesHeader, call->private_size, MPEG_AUDIO_PES_START_CODE, 0, 0);
unsigned char* PacketStart = malloc(call->private_size + HeaderLength);
memcpy (PacketStart, PesHeader, HeaderLength);
memcpy (PacketStart + HeaderLength, call->private_data, call->private_size);
len = write(call->fd, PacketStart, call->private_size + HeaderLength);
free(PacketStart);
initialHeader = 0;
}
if (call->len > 0 && call->data)
{
unsigned char PesHeader[PES_MAX_HEADER_SIZE];
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);
len = write(call->fd, PacketStart, call->len + HeaderLength);
free(PacketStart);
}
wma_printf(10, "wma < %d\n", len);
return len;
}
/* ***************************** */
/* Writer Definition */
/* ***************************** */
static WriterCaps_t caps = {
"wma",
eAudio,
"A_WMA",
AUDIO_ENCODING_WMA
};
struct Writer_s WriterAudioWMA = {
&reset,
&writeData,
NULL,
&caps
};

View File

@@ -0,0 +1,280 @@
/*
* 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 */
/* ***************************** */
#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 WMV_DEBUG
#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 */
/* ***************************** */
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 = (awmv_t *)malloc(sizeof(awmv_t));
int len = 0;
wmv_printf(10, "\n");
if (call == NULL) {
wmv_err("call data is NULL...\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;
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;
}
if (initialHeader) {
unsigned char PesPacket[PES_MIN_HEADER_SIZE+128];
unsigned char* PesPtr;
unsigned int MetadataLength;
unsigned int crazyFramerate = 0;
if (private_data == NULL) {
wmv_err("private_data NULL\n");
return -1;
}
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) {
int Position = 0;
unsigned char insertSampleHeader = 1;
while(1) {
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;
if (Position == call->len)
break;
}
}
wmv_printf(10, "< %d\n", len);
return len;
}
/* ***************************** */
/* Writer Definition */
/* ***************************** */
static WriterCaps_t caps = {
"wmv",
eVideo,
"V_WMV",
VIDEO_ENCODING_WMV
};
struct Writer_s WriterVideoWMV = {
&reset,
&writeData,
NULL,
&caps
};

View File

@@ -0,0 +1,141 @@
/*
* 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 */
/* ***************************** */
#define WRITER_DEBUG
#ifdef WRITER_DEBUG
static short debug_level = 0;
#define writer_printf(level, x...) do { \
if (debug_level >= level) printf(x); } while (0)
#else
#define writer_printf(level, x...)
#endif
#ifndef WRITER_SILENT
#define writer_err(x...) do { printf(x); } while (0)
#else
#define writer_err(x...)
#endif
/* ***************************** */
/* Types */
/* ***************************** */
/* ***************************** */
/* Varaibles */
/* ***************************** */
/* ***************************** */
/* Prototypes */
/* ***************************** */
/* ***************************** */
/* Functions */
/* ***************************** */
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;
}
Writer_t* getDefaultFramebufferWriter()
{
int i;
for (i = 0; AvailableWriter[i] != NULL; i++)
{
writer_printf(10, "%s\n", AvailableWriter[i]->caps->textEncoding);
if (strcmp(AvailableWriter[i]->caps->textEncoding, "framebuffer") == 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;
}