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

29
libeplayer3/Makefile.am Normal file
View File

@@ -0,0 +1,29 @@
lib_LTLIBRARIES = libeplayer3.la
CXXFLAGS = -Wall
INCLUDES = \
-Iinclude
libeplayer3_la_SOURCES = \
container/container.c container/container_ffmpeg.c container/text_srt.c \
container/text_ssa.c container/container_ass.c \
manager/audio.c manager/manager.c manager/subtitle.c manager/video.c \
output/output_subtitle.c output/linuxdvb.c output/output.c \
playback/playback.c output/writer/writer.c output/writer/aac.c output/writer/wmv.c \
output/writer/ac3.c output/writer/divx.c output/writer/wma.c output/writer/pes.c \
output/writer/dts.c output/writer/mpeg2.c output/writer/mp3.c output/writer/misc.c \
output/writer/h264.c output/writer/h263.c output/writer/vc1.c output/writer/framebuffer.c \
output/writer/vorbis.c output/writer/flac.c output/writer/pcm.c
AM_CFLAGS = -Wall -D_LARGEFILE_SOURCE -D_FILE_OFFSET_BITS=64 \
-D_LARGEFILE64_SOURCE
libeplayer3_la_LIBADD = -lpthread -lavformat -lavcodec -lavutil -lz -lass -lm -lpng
bin_PROGRAMS = eplayer3 meta
eplayer3_SOURCES = tools/eplayer2.c
eplayer3_LDADD = -leplayer3 -lpthread -lass -lm -lpng
meta_SOURCES = tools/meta.c
meta_LDADD = -leplayer3 -lpthread -lass -lm -lpng

72
libeplayer3/README Normal file
View File

@@ -0,0 +1,72 @@
/*
* SCOPE:
* -------
*
* libeplayer3 was developed to create a cleaner and more stable
* version of the libeplayer2.
* Currently the lib supports only one container, which handle all
* files by using the ffmpeg library.
*
* FEATURES:
* -----------------------
*
* - more stable than libeplayer2.
* - more multimedia files are supported than libeplayer2.
* - mms stream support.
* - new videocodec support:
* - wmv and vc1 (sti7109 & sti7111 & sti7105 only).
* - flv.
* - improved http streaming support
* - subtitle rendering (ssa / ass) by using libass
*
* STYLE GUIDELINES:
* ------------------
*
* If you decide to add some lines of code please ensure the following:
* - do not use a windows editor.
* - a tab must be emulated by 4 spaces (most editors support this).
* If you accidental break this rule use astyle to reorganize indentation,
* and dos2unix to remove windows style.
*
* Programming GUIDLINES:
* -----------------------
*
* - the compiler is intentionally set to Wall, it would be nice if all
* programmer looks for warnings and solve them.
* - make sanity checks where ever you can.
* - freeing memory is an act of solidarity, but it also increases uptime
* of your receiver. ;)
* - if you detect stuff which may be generic, then make it generic.
* - commenting code is not a bad idea.
*
* KNOWN BUGS / PROBLEMS:
* ----------------------
*
* - reverse playback needs improvement
* - some formats makes problems ?
* - getting stream info currently leads to a memory leak in e2. this is
* not a problem of this implementation its also exists in libeplayer2.
* e2 delivers a strdupped variable which is overwritten by what the container
* delivers. this is very hacky ;) -> (see comment in container_ffmpeg_get_info)
*
* License:
* --------
*
* Copyright (C) 2010 crow, schischu, hellmaster1024 and konfetti.
*
*
* 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
*
*/

View File

@@ -0,0 +1,125 @@
/*
* Main Container 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
*
*/
#include <stdio.h>
#include <string.h>
#include "common.h"
#define CONTAINER_DEBUG
#ifdef CONTAINER_DEBUG
static short debug_level = 10;
#define container_printf(level, x...) do { \
if (debug_level >= level) printf(x); } while (0)
#else
#define container_printf(level, x...)
#endif
#ifndef CONTAINER_SILENT
#define container_err(x...) do { printf(x); } while (0)
#else
#define container_err(x...)
#endif
static const char FILENAME[] = __FILE__;
static void printContainerCapabilities() {
int i, j;
container_printf(10, "%s::%s\n", FILENAME, __FUNCTION__);
container_printf(10, "Capabilities: ");
for (i = 0; AvailableContainer[i] != NULL; i++)
for (j = 0; AvailableContainer[i]->Capabilities[j] != NULL; j++)
container_printf(10, "%s ", AvailableContainer[i]->Capabilities[j]);
container_printf(10, "\n");
}
static int selectContainer(Context_t *context, char * extension) {
int i, j;
int ret = -1;
container_printf(10, "%s::%s\n", FILENAME, __FUNCTION__);
for (i = 0; AvailableContainer[i] != NULL; i++)
{
for (j = 0; AvailableContainer[i]->Capabilities[j] != NULL; j++)
if (!strcasecmp(AvailableContainer[i]->Capabilities[j], extension)) {
context->container->selectedContainer = AvailableContainer[i];
container_printf(10, "Selected Container: %s\n", context->container->selectedContainer->Name);
ret = 0;
break;
}
if (ret == 0)
break;
}
if (ret != 0) {
container_err("No Container found :-(\n");
}
return ret;
}
static int Command(void *_context, ContainerCmd_t command, void * argument) {
Context_t* context = (Context_t*) _context;
int ret = 0;
container_printf(10, "%s::%s\n", FILENAME, __FUNCTION__);
switch(command) {
case CONTAINER_ADD: {
ret = selectContainer(context, (char*) argument);
break;
}
case CONTAINER_CAPABILITIES: {
printContainerCapabilities();
break;
}
case CONTAINER_DEL: {
context->container->selectedContainer = NULL;
break;
}
default:
container_err("%s::%s ContainerCmd %d not supported!\n", FILENAME, __FUNCTION__, command);
break;
}
return ret;
}
extern Container_t SrtContainer;
extern Container_t SsaContainer;
extern Container_t ASSContainer;
ContainerHandler_t ContainerHandler = {
"Output",
NULL,
&SrtContainer,
&SsaContainer,
&ASSContainer,
Command,
};

View File

@@ -0,0 +1,817 @@
/*
* Container handling for subtitles handled by libass
* konfetti 2010; based on code from crow
*
* The subtitle handling as container is not a very proper solution, in
* a proper architecture this should be handled as subcontainer or something
* like that. But we dont want to make more effort as necessary here ;)
*
* 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 <stdlib.h>
#include <sys/ioctl.h>
#include <fcntl.h>
#include <unistd.h>
#include <memory.h>
#include <string.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <errno.h>
#include <sys/poll.h>
#include <pthread.h>
#include <ass/ass.h>
#include "common.h"
#include "misc.h"
#include "subtitle.h"
#include "writer.h"
/* ***************************** */
/* Makros/Constants */
/* ***************************** */
#define ASS_DEBUG
#ifdef ASS_DEBUG
static short debug_level = 10;
#define ass_printf(level, fmt, x...) do { \
if (debug_level >= level) printf("[%s:%s] " fmt, __FILE__, __FUNCTION__, ## x); } while (0)
#else
#define ass_printf(level, fmt, x...)
#endif
#ifndef ASS_SILENT
#define ass_err(fmt, x...) do { printf("[%s:%s] " fmt, __FILE__, __FUNCTION__, ## x); } while (0)
#else
#define ass_err(fmt, x...)
#endif
/* Error Constants */
#define cERR_CONTAINER_ASS_NO_ERROR 0
#define cERR_CONTAINER_ASS_ERROR -1
#define ASS_RING_SIZE 5
#define ASS_FONT "/usr/share/fonts/FreeSans.ttf"
/* ***************************** */
/* Types */
/* ***************************** */
typedef struct ass_s {
unsigned char* data;
int len;
unsigned char* extradata;
int extralen;
long long int pts;
float duration;
} ass_t;
typedef struct region_s
{
unsigned int x;
unsigned int y;
unsigned int w;
unsigned int h;
time_t undisplay;
struct region_s* next;
} region_t;
/* ***************************** */
/* Varaibles */
/* ***************************** */
static pthread_mutex_t mutex;
static pthread_t PlayThread;
static int hasPlayThreadStarted = 0;
static unsigned char isContainerRunning = 0;
static ASS_Library *ass_library;
static ASS_Renderer *ass_renderer;
static float ass_font_scale = 0.7;
static float ass_line_spacing = 0.7;
static unsigned int screen_width = 0;
static unsigned int screen_height = 0;
static int shareFramebuffer = 0;
static int framebufferFD = -1;
static unsigned char* destination = NULL;
static int destStride = 0;
static int threeDMode =0;
static ASS_Track* ass_track = NULL;
static region_t* firstRegion = NULL;
/* ***************************** */
/* Prototypes */
/* ***************************** */
/* ***************************** */
/* MISC Functions */
/* ***************************** */
void ass_msg_callback(int level, const char *format, va_list va, void *ctx)
{
int n;
char *str;
va_list dst;
va_copy(dst, va);
n = vsnprintf(NULL, 0, format, va);
if (n > 0 && (str = malloc(n + 1))) {
vsnprintf(str, n + 1, format, dst);
ass_printf(100, "%s\n", str);
free(str);
}
}
static void getMutex(int line) {
ass_printf(150, "%d requesting mutex\n", line);
pthread_mutex_lock(&mutex);
ass_printf(150, "%d received mutex\n", line);
}
static void releaseMutex(int line) {
pthread_mutex_unlock(&mutex);
ass_printf(150, "%d released mutex\n", line);
}
/* ********************************* */
/* Region Undisplay handling */
/* ********************************* */
/* release and undisplay all saved regions
*/
void releaseRegions()
{
region_t* next, *old;
Writer_t* writer;
if (firstRegion == NULL)
return;
writer = getDefaultFramebufferWriter();
if (writer == NULL)
{
ass_err("no framebuffer writer found!\n");
}
next = firstRegion;
while (next != NULL)
{
if (writer)
{
WriterFBCallData_t out;
ass_printf(100, "release: w %d h %d x %d y %d\n",
next->w, next->h, next->x, next->y);
out.fd = framebufferFD;
out.data = NULL;
out.Width = next->w;
out.Height = next->h;
out.x = next->x;
out.y = next->y;
out.Screen_Width = screen_width;
out.Screen_Height = screen_height;
out.destination = destination;
out.destStride = destStride;
writer->writeData(&out);
if(threeDMode == 1){
out.x = screen_width/2 + next->x;
writer->writeData(&out);
}else if(threeDMode == 2){
out.y = screen_height/2 + next->y;
writer->writeData(&out);
}
}
old = next;
next = next->next;
free(old);
}
firstRegion = NULL;
}
/* check for regions which should be undisplayed.
* we are very tolerant on time here, because
* regions are also released when new regions are
* detected (see ETSI EN 300 743 Chapter Page Composition)
*/
void checkRegions()
{
#define cDeltaTime 2
region_t* next, *old, *prev;
Writer_t* writer;
time_t now = time(NULL);
if (firstRegion == NULL)
return;
writer = getDefaultFramebufferWriter();
if (writer == NULL)
{
ass_err("no framebuffer writer found!\n");
}
prev = next = firstRegion;
while (next != NULL)
{
if (now > next->undisplay + cDeltaTime)
{
ass_printf(100, "undisplay: %ld > %ld\n", now, next->undisplay + cDeltaTime);
if (writer)
{
WriterFBCallData_t out;
ass_printf(100, "release: w %d h %d x %d y %d\n",
next->w, next->h, next->x, next->y);
out.fd = framebufferFD;
out.data = NULL;
out.Width = next->w;
out.Height = next->h;
out.x = next->x;
out.y = next->y;
out.Screen_Width = screen_width;
out.Screen_Height = screen_height;
out.destination = destination;
out.destStride = destStride;
writer->writeData(&out);
if(threeDMode == 1){
out.x = screen_width/2 + next->x;
writer->writeData(&out);
}else if(threeDMode == 2){
out.y = screen_height/2 + next->y;
writer->writeData(&out);
}
}
old = next;
next = prev->next = next->next;
if (old == firstRegion)
firstRegion = next;
free(old);
} else
{
prev = next;
next = next->next;
}
}
}
/* store a display region for later release */
void storeRegion(unsigned int x, unsigned int y, unsigned int w, unsigned int h, time_t undisplay)
{
region_t* new;
ass_printf(100, "%d %d %d %d %ld\n", x, y, w, h, undisplay);
if (firstRegion == NULL)
{
firstRegion = malloc(sizeof(region_t));
new = firstRegion;
} else
{
new = firstRegion;
while (new->next != NULL)
new = new->next;
new->next = malloc(sizeof(region_t));
new = new->next;
}
new->next = NULL;
new->x = x;
new->y = y;
new->w = w;
new->h = h;
new->undisplay = undisplay;
}
/* **************************** */
/* Worker Thread */
/* **************************** */
static void ASSThread(Context_t *context) {
Writer_t* writer;
ass_printf(10, "\n");
while ( context->playback->isCreationPhase )
{
ass_err("Thread waiting for end of init phase...\n");
usleep(1000);
}
ass_printf(10, "Running!\n");
writer = getDefaultFramebufferWriter();
if (writer == NULL)
{
ass_err("no framebuffer writer found!\n");
}
while ( context && context->playback && context->playback->isPlaying ) {
//IF MOVIE IS PAUSED, WAIT
if (context->playback->isPaused) {
ass_printf(20, "paused\n");
usleep(100000);
continue;
}
if (context->playback->isSeeking) {
ass_printf(10, "seeking\n");
usleep(100000);
continue;
}
if ((isContainerRunning) && (ass_track))
{
ASS_Image * img = NULL;
int change = 0;
unsigned long int playPts;
if (context && context->playback)
{
if (context->playback->Command(context, PLAYBACK_PTS, &playPts) < 0)
continue;
}
getMutex(__LINE__);
//FIXME: durch den sleep bleibt die cpu usage zw. 5 und 13%, ohne
// steigt sie bei Verwendung von subtiteln bis auf 95%.
// ich hoffe dadurch gehen keine subtitle verloren, wenn die playPts
// durch den sleep verschlafen wird. Besser w<>re es den n<>chsten
// subtitel zeitpunkt zu bestimmen und solange zu schlafen.
usleep(1000);
img = ass_render_frame(ass_renderer, ass_track, playPts / 90.0, &change);
ass_printf(150, "img %p pts %lu %f\n", img, playPts, playPts / 90.0);
if(img != NULL && ass_renderer && ass_track)
{
/* the spec says, that if a new set of regions is present
* the complete display switches to the new state. So lets
* release the old regions on display.
*/
if (change != 0)
releaseRegions();
while (context && context->playback && context->playback->isPlaying &&
(img) && (change != 0))
{
WriterFBCallData_t out;
time_t now = time(NULL);
time_t undisplay = now + 10;
if (ass_track && ass_track->events)
{
undisplay = now + ass_track->events->Duration / 1000 + 0.5;
}
ass_printf(100, "w %d h %d s %d x %d y %d c %d chg %d now %ld und %ld\n",
img->w, img->h, img->stride,
img->dst_x, img->dst_y, img->color,
change, now, undisplay);
/* api docu said w and h can be zero which
* means image should not be rendered
*/
if ((img->w != 0) && (img->h != 0) && (writer))
{
out.fd = framebufferFD;
out.data = img->bitmap;
out.Width = img->w;
out.Height = img->h;
out.Stride = img->stride;
out.x = img->dst_x;
out.y = img->dst_y;
out.color = img->color;
out.Screen_Width = screen_width;
out.Screen_Height = screen_height;
out.destination = destination;
out.destStride = destStride;
storeRegion(img->dst_x, img->dst_y,
img->w, img->h, undisplay);
if (shareFramebuffer)
{
if(context && context->playback && context->playback->isPlaying && writer){
writer->writeData(&out);
if(threeDMode == 1){
out.x = screen_width/2 + img->dst_x;
writer->writeData(&out);
}else if(threeDMode == 2){
out.y = screen_height/2 + img->dst_y;
writer->writeData(&out);
}
}
}
else
{
/* application does not want to share framebuffer,
* so there is hopefully installed an output callback
* in the subtitle output!
*/
SubtitleOut_t out;
out.type = eSub_Gfx;
if (ass_track->events)
{
/* fixme: check values */
out.pts = ass_track->events->Start * 90.0;
out.duration = ass_track->events->Duration / 1000.0;
} else
{
out.pts = playPts;
out.duration = 10.0;
}
out.u.gfx.data = img->bitmap;
out.u.gfx.Width = img->w;
out.u.gfx.Height = img->h;
out.u.gfx.x = img->dst_x;
out.u.gfx.y = img->dst_y;
if(context && context->playback && context->playback->isPlaying &&
context->output && context->output->subtitle)
context->output->subtitle->Write(context, &out);
}
}
/* Next image */
img = img->next;
}
}
else
{
/* noop */
}
releaseMutex(__LINE__);
} else
{
usleep(1000);
}
/* cleanup no longer used but not overwritten regions */
checkRegions();
} /* while */
hasPlayThreadStarted = 0;
ass_printf(10, "terminating\n");
}
/* **************************** */
/* Container part for ass */
/* **************************** */
int container_ass_init(Context_t *context)
{
int modefd;
char buf[16];
SubtitleOutputDef_t output;
ass_printf(10, ">\n");
ass_library = ass_library_init();
if (!ass_library) {
ass_err("ass_library_init failed!\n");
return cERR_CONTAINER_ASS_ERROR;
}
if (debug_level >= 100)
ass_set_message_cb(ass_library, ass_msg_callback, NULL);
ass_set_extract_fonts( ass_library, 1 );
ass_set_style_overrides( ass_library, NULL );
ass_renderer = ass_renderer_init(ass_library);
if (!ass_renderer) {
ass_err("ass_renderer_init failed!\n");
if (ass_library)
ass_library_done(ass_library);
ass_library = NULL;
return cERR_CONTAINER_ASS_ERROR;
}
context->output->subtitle->Command(context, OUTPUT_GET_SUBTITLE_OUTPUT, &output);
modefd=open("/proc/stb/video/3d_mode", O_RDWR);
if(modefd > 0){
read(modefd, buf, 15);
buf[15]='\0';
close(modefd);
}else threeDMode = 0;
if(strncmp(buf,"sbs",3)==0)threeDMode = 1;
else if(strncmp(buf,"tab",3)==0)threeDMode = 2;
else threeDMode = 0;
screen_width = output.screen_width;
screen_height = output.screen_height;
shareFramebuffer = output.shareFramebuffer;
framebufferFD = output.framebufferFD;
destination = output.destination;
destStride = output.destStride;
ass_printf(10, "width %d, height %d, share %d, fd %d, 3D %d\n",
screen_width, screen_height, shareFramebuffer, framebufferFD, threeDMode);
if(threeDMode == 0){
ass_set_frame_size(ass_renderer, screen_width, screen_height);
ass_set_margins(ass_renderer, (int)(0.03 * screen_height), (int)(0.03 * screen_height) ,
(int)(0.03 * screen_width ), (int)(0.03 * screen_width ) );
}else if(threeDMode == 1){
ass_set_frame_size(ass_renderer, screen_width/2, screen_height);
ass_set_margins(ass_renderer, (int)(0.03 * screen_height), (int)(0.03 * screen_height) ,
(int)(0.03 * screen_width/2 ), (int)(0.03 * screen_width/2 ) );
}else if(threeDMode == 2){
ass_set_frame_size(ass_renderer, screen_width, screen_height/2);
ass_set_margins(ass_renderer, (int)(0.03 * screen_height/2), (int)(0.03 * screen_height/2) ,
(int)(0.03 * screen_width ), (int)(0.03 * screen_width ) );
}
ass_set_use_margins(ass_renderer, 0 );
ass_set_font_scale(ass_renderer, ass_font_scale);
ass_set_hinting(ass_renderer, ASS_HINTING_LIGHT);
ass_set_line_spacing(ass_renderer, ass_line_spacing);
ass_set_fonts(ass_renderer, ASS_FONT, "Arial", 0, NULL, 1);
if(threeDMode == 0){
ass_set_aspect_ratio( ass_renderer, 1.0, 1.0);
}else if(threeDMode == 1){
ass_set_aspect_ratio( ass_renderer, 0.5, 1.0);
}else if(threeDMode == 2){
ass_set_aspect_ratio( ass_renderer, 1.0, 0.5);
}
isContainerRunning = 1;
return cERR_CONTAINER_ASS_NO_ERROR;
}
int container_ass_process_data(Context_t *context, SubtitleData_t* data)
{
int first_kiss;
ass_printf(20, ">\n");
if (!isContainerRunning)
{
ass_err("Container not running\n");
return cERR_CONTAINER_ASS_ERROR;
}
if (ass_track == NULL)
{
first_kiss = 1;
ass_track = ass_new_track(ass_library);
if (ass_track == NULL)
{
ass_err("error creating ass_track\n");
return cERR_CONTAINER_ASS_ERROR;
}
}
if ((data->extradata) && (first_kiss))
{
ass_printf(30,"processing private %d bytes\n",data->extralen);
ass_process_codec_private(ass_track, (char*) data->extradata, data->extralen);
ass_printf(30,"processing private done\n");
}
if (data->data)
{
ass_printf(30,"processing data %d bytes\n",data->len);
ass_process_data(ass_track, (char*) data->data, data->len);
ass_printf(30,"processing data done\n");
}
return cERR_CONTAINER_ASS_NO_ERROR;
}
static int container_ass_stop(Context_t *context) {
int ret = cERR_CONTAINER_ASS_NO_ERROR;
int wait_time = 20;
Writer_t* writer;
ass_printf(10, "\n");
if (!isContainerRunning)
{
ass_err("Container not running\n");
return cERR_CONTAINER_ASS_ERROR;
}
while ( (hasPlayThreadStarted != 0) && (--wait_time) > 0 ) {
ass_printf(10, "Waiting for ass thread to terminate itself, will try another %d times\n", wait_time);
usleep(100000);
}
if (wait_time == 0) {
ass_err( "Timeout waiting for thread!\n");
ret = cERR_CONTAINER_ASS_ERROR;
}
getMutex(__LINE__);
releaseRegions();
if (ass_track)
ass_free_track(ass_track);
ass_track = NULL;
if (ass_renderer)
ass_renderer_done(ass_renderer);
ass_renderer = NULL;
if (ass_library)
ass_library_done(ass_library);
ass_library = NULL;
isContainerRunning = 0;
hasPlayThreadStarted = 0;
writer = getDefaultFramebufferWriter();
if (writer != NULL)
{
writer->reset();
}
releaseMutex(__LINE__);
ass_printf(10, "ret %d\n", ret);
return ret;
}
static int container_ass_switch_subtitle(Context_t* context, int* arg)
{
int error;
int ret = cERR_CONTAINER_ASS_NO_ERROR;
pthread_attr_t attr;
ass_printf(10, "\n");
if (!isContainerRunning)
{
ass_err("Container not running\n");
return cERR_CONTAINER_ASS_ERROR;
}
if ( context && context->playback && context->playback->isPlaying ) {
ass_printf(10, "is Playing\n");
}
else {
ass_printf(10, "is NOT Playing\n");
}
if (hasPlayThreadStarted == 0) {
pthread_attr_init(&attr);
pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
if((error = pthread_create(&PlayThread, &attr, (void *)&ASSThread, context)) != 0) {
ass_printf(10, "Error creating thread, error:%d:%s\n", error,strerror(error));
hasPlayThreadStarted = 0;
ret = cERR_CONTAINER_ASS_ERROR;
}
else {
ass_printf(10, "Created thread\n");
hasPlayThreadStarted = 1;
}
}
else {
ass_printf(10, "A thread already exists!\n");
ret = cERR_CONTAINER_ASS_ERROR;
}
getMutex(__LINE__);
releaseRegions();
/* free the track so extradata will be written next time
* process_data is called.
*/
if (ass_track)
ass_free_track(ass_track);
ass_track = NULL;
releaseMutex(__LINE__);
ass_printf(10, "exiting with value %d\n", ret);
return ret;
}
static int Command(void *_context, ContainerCmd_t command, void * argument)
{
Context_t *context = (Context_t*) _context;
int ret = cERR_CONTAINER_ASS_NO_ERROR;
ass_printf(50, "Command %d\n", command);
switch(command)
{
case CONTAINER_INIT: {
ret = container_ass_init(context);
break;
}
case CONTAINER_STOP: {
ret = container_ass_stop(context);
break;
}
case CONTAINER_SWITCH_SUBTITLE: {
ret = container_ass_switch_subtitle(context, (int*) argument);
break;
}
case CONTAINER_DATA: {
SubtitleData_t* data = (SubtitleData_t*) argument;
ret = container_ass_process_data(context, data);
break;
}
default:
ass_err("ContainerCmd %d not supported!\n", command);
ret = cERR_CONTAINER_ASS_ERROR;
break;
}
ass_printf(50, "exiting with value %d\n", ret);
return ret;
}
static char *ASS_Capabilities[] = {"ass", NULL };
Container_t ASSContainer = {
"ASS",
&Command,
ASS_Capabilities,
};

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,490 @@
/*
* subtitle handling for srt files.
*
* 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 <sys/stat.h>
#include <fcntl.h>
#include <stdlib.h>
#include <sys/socket.h>
#include <netdb.h>
#include <sys/types.h>
#include <dirent.h>
#include <pthread.h>
#include <errno.h>
#include <unistd.h>
#include <limits.h>
#include "common.h"
#include "misc.h"
#include "subtitle.h"
/* ***************************** */
/* Makros/Constants */
/* ***************************** */
#define SRT_DEBUG
#ifdef SRT_DEBUG
static short debug_level = 10;
#define srt_printf(level, fmt, x...) do { \
if (debug_level >= level) printf("[%s:%s] " fmt, __FILE__, __FUNCTION__, ## x); } while (0)
#else
#define srt_printf(level, fmt, x...)
#endif
#ifndef SRT_SILENT
#define srt_err(fmt, x...) do { printf("[%s:%s] " fmt, __FILE__, __FUNCTION__, ## x); } while (0)
#else
#define srt_err(fmt, x...)
#endif
/* Error Constants */
#define cERR_SRT_NO_ERROR 0
#define cERR_SRT_ERROR -1
#define TRACKWRAP 20
#define MAXLINELENGTH 80
static const char FILENAME[] = __FILE__;
/* ***************************** */
/* Types */
/* ***************************** */
typedef struct {
char * File;
int Id;
} SrtTrack_t;
static pthread_t thread_sub;
/* ***************************** */
/* Varaibles */
/* ***************************** */
static SrtTrack_t * Tracks;
static int TrackCount = 0;
static int CurrentTrack = -1; //no as default.
FILE * fsub = NULL;
static int hasThreadStarted = 0;
/* ***************************** */
/* Prototypes */
/* ***************************** */
/* ***************************** */
/* MISC Functions */
/* ***************************** */
void data_to_manager(Context_t *context, char* Text, unsigned long long int Pts, double Duration)
{
srt_printf(20, "--> Text= \"%s\"\n", Text);
if( context &&
context->playback &&
context->playback->isPlaying){
int sl = strlen(Text)-1;
while(sl && (Text[sl]=='\n' || Text[sl]=='\r')) Text[sl--]='\0'; /*Delete last \n or \r */
unsigned char* line = text_to_ass(Text, Pts, Duration);
srt_printf(50,"Sub text is %s\n",Text);
srt_printf(50,"Sub line is %s\n",line);
SubtitleData_t data;
data.data = line;
data.len = strlen((char*)line);
data.extradata = DEFAULT_ASS_HEAD;
data.extralen = strlen(DEFAULT_ASS_HEAD);
data.pts = Pts*90;
data.duration = Duration;
context->container->assContainer->Command(context, CONTAINER_DATA, &data);
free(line);
}
srt_printf(20, "<-- Text= \"%s\"\n", Text);
}
/* ***************************** */
/* Worker Thread */
/* ***************************** */
static void* SrtSubtitleThread(void *data) {
int pos = 0;
char Data[MAXLINELENGTH];
unsigned long long int Pts = 0;
double Duration = 0;
char * Text = NULL;
Context_t *context = (Context_t*) data;
srt_printf(10, "\n");
while(context && context->playback && context->playback->isPlaying && fsub && fgets(Data, MAXLINELENGTH, fsub)) {
srt_printf(20, "pos=%d\n", pos);
if(pos == 0)
{
if(Data[0] == '\n' || Data[0] == '\0' || Data[0] == 13 /* ^M */)
continue; /* Empty line not allowed here */
pos++;
} else if(pos == 1)
{
int ret, horIni, minIni, secIni, milIni, horFim, minFim, secFim, milFim;
ret = sscanf(Data, "%d:%d:%d,%d --> %d:%d:%d,%d", &horIni, &minIni, &secIni, &milIni, &horFim, &minFim, &secFim, &milFim);
if (ret!=8) continue; /* Data is not in correct format */
Pts = (horIni*3600 + minIni*60 + secIni)*1000 + milIni;
Duration = ((horFim*3600 + minFim*60 + secFim) * 1000 + milFim - Pts) / 1000.0;
pos++;
} else if(pos == 2) {
srt_printf(20, "Data[0] = %d \'%c\'\n", Data[0], Data[0]);
if(Data[0] == '\n' || Data[0] == '\0' || Data[0] == 13 /* ^M */) {
if(Text == NULL)
Text = strdup(" \n"); /* better to display at least one character */
/*Hellmaster 1024 since we have waited, we have to check if we are still paying */
data_to_manager(context, Text, Pts, Duration);
free(Text);
Text = NULL;
pos = 0;
continue;
}
if(!Text) {
Text = strdup(Data);
} else {
int length = strlen(Text) /* \0 -> \n */ + strlen(Data) + 2 /* \0 */;
char * tmpText = strdup(Text);
free(Text);
Text = (char*)malloc(length);
strcpy(Text, tmpText);
strcat(Text, Data);
free(tmpText);
}
}
} /* while */
hasThreadStarted = 0;
if(Text) {
data_to_manager(context, Text, Pts, Duration);
free(Text);
Text = NULL;
}
srt_printf(0, "thread has ended\n");
return NULL;
}
/* ***************************** */
/* Functions */
/* ***************************** */
static void SrtManagerAdd(Context_t *context, SrtTrack_t track) {
srt_printf(10, "%s %d\n",track.File, track.Id);
if (Tracks == NULL) {
Tracks = malloc(sizeof(SrtTrack_t) * TRACKWRAP);
}
if (TrackCount < TRACKWRAP) {
Tracks[TrackCount].File = strdup(track.File);
Tracks[TrackCount].Id = track.Id;
TrackCount++;
}
}
static char ** SrtManagerList(Context_t *context) {
char ** tracklist = NULL;
srt_printf(10, "\n");
if (Tracks != NULL) {
char help[256];
int i = 0, j = 0;
tracklist = malloc(sizeof(char *) * ((TrackCount*2) + 1));
for (i = 0, j = 0; i < TrackCount; i++, j+=2) {
sprintf(help, "%d", Tracks[i].Id);
tracklist[j] = strdup(help);
tracklist[j+1] = strdup(Tracks[i].File);
}
tracklist[j] = NULL;
}
return tracklist;
}
static void SrtManagerDel(Context_t * context) {
int i = 0;
srt_printf(10, "\n");
if(Tracks != NULL) {
for (i = 0; i < TrackCount; i++) {
if (Tracks[i].File != NULL)
free(Tracks[i].File);
Tracks[i].File = NULL;
}
free(Tracks);
Tracks = NULL;
}
TrackCount = 0;
CurrentTrack = -1;
}
static int SrtGetSubtitle(Context_t *context, char * Filename) {
struct dirent *dirzeiger;
DIR * dir;
int i = TEXTSRTOFFSET;
char * copyFilename = NULL;
char * FilenameExtension = NULL;
char * FilenameFolder = NULL;
char * FilenameShort = NULL;
srt_printf(10, "\n");
if (Filename == NULL)
{
srt_err("Filename NULL\n");
return cERR_SRT_ERROR;
}
srt_printf(10, "file: %s\n", Filename);
copyFilename = strdup(Filename);
FilenameFolder = dirname(copyFilename);
if (FilenameFolder == NULL)
{
srt_err("FilenameFolder NULL\n");
return cERR_SRT_ERROR;
}
srt_printf(10, "folder: %s\n", FilenameFolder);
getExtension(copyFilename, &FilenameExtension);
if (FilenameExtension == NULL)
{
srt_err("FilenameExtension NULL\n");
free(FilenameFolder);
return cERR_SRT_ERROR;
}
srt_printf(10, "ext: %s\n", FilenameExtension);
FilenameShort = basename(copyFilename);
/* cut extension */
FilenameShort[strlen(FilenameShort) - strlen(FilenameExtension) - 1] = '\0';
srt_printf(10, "basename: %s\n", FilenameShort);
srt_printf(10, "%s\n%s | %s | %s\n", copyFilename, FilenameFolder, FilenameShort, FilenameExtension);
if((dir = opendir(FilenameFolder)) != NULL) {
while((dirzeiger = readdir(dir)) != NULL) {
char subtitleFilename[PATH_MAX];
char *subtitleExtension = NULL;
srt_printf(20, "%s\n",(*dirzeiger).d_name);
strcpy(subtitleFilename, (*dirzeiger).d_name);
// Extension of Relativ Subtitle File Name
getExtension(subtitleFilename, &subtitleExtension);
if (subtitleExtension == NULL)
continue;
if (strcmp(subtitleExtension, "srt") != 0)
{
free(subtitleExtension);
continue;
}
/* cut extension */
subtitleFilename[strlen(subtitleFilename) - strlen(subtitleExtension) - 1] = '\0';
srt_printf(10, "%s %s\n", FilenameShort, subtitleFilename);
if (strncmp(FilenameShort, subtitleFilename,strlen(FilenameShort)) == 0)
{
char absSubtitleFileName[PATH_MAX];
/* found something of interest, so now make an absolut path name */
sprintf(absSubtitleFileName, "%s/%s.%s", FilenameFolder, subtitleFilename, subtitleExtension);
srt_printf(10, "SRT: %s [%s]\n", subtitleExtension, subtitleFilename);
srt_printf(10, "\t->%s\n", absSubtitleFileName);
SrtTrack_t SrtSubtitle = {
absSubtitleFileName,
i,
};
SrtManagerAdd(context, SrtSubtitle);
Track_t Subtitle = {
subtitleExtension,
"S_TEXT/SRT",
i++,
};
context->manager->subtitle->Command(context, MANAGER_ADD, &Subtitle);
}
free(subtitleExtension);
} /* while */
closedir(dir);
} /* if dir */
free(FilenameExtension);
free(copyFilename);
srt_printf(10, "<\n");
return cERR_SRT_NO_ERROR;
}
static int SrtOpenSubtitle(Context_t *context, int trackid) {
srt_printf(10, "\n");
if(trackid < TEXTSRTOFFSET || (trackid % TEXTSRTOFFSET) >= TrackCount) {
srt_err("trackid not for us\n");
return cERR_SRT_ERROR;
}
trackid %= TEXTSRTOFFSET;
srt_printf(10, "%s\n", Tracks[trackid].File);
fsub = fopen(Tracks[trackid].File, "rb");
srt_printf(10, "%s\n", fsub ? "fsub!=NULL" : "fsub==NULL");
if(!fsub)
{
srt_err("cannot open file %s\n", Tracks[trackid].File);
return cERR_SRT_ERROR;
}
return cERR_SRT_NO_ERROR;
}
static int SrtCloseSubtitle(Context_t *context) {
srt_printf(10, "\n");
if(fsub)
fclose(fsub);
/* this closes the thread! */
fsub = NULL;
hasThreadStarted = 0;
return cERR_SRT_NO_ERROR;
}
static int SrtSwitchSubtitle(Context_t *context, int* arg) {
int ret = cERR_SRT_NO_ERROR;
srt_printf(10, "arg:%d\n", *arg);
ret = SrtCloseSubtitle(context);
if (( (ret |= SrtOpenSubtitle(context, *arg)) == cERR_SRT_NO_ERROR) && (!hasThreadStarted))
{
pthread_attr_t attr;
pthread_attr_init(&attr);
pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
pthread_create (&thread_sub, &attr, &SrtSubtitleThread, context);
hasThreadStarted = 1;
}
return ret;
}
static int SrtDel(Context_t *context) {
int ret = cERR_SRT_NO_ERROR;
srt_printf(10, "\n");
ret = SrtCloseSubtitle(context);
SrtManagerDel(context);
return ret;
}
static int Command(void *_context, ContainerCmd_t command, void * argument) {
Context_t *context = (Context_t*) _context;
int ret = cERR_SRT_NO_ERROR;
srt_printf(10, "\n");
switch(command) {
case CONTAINER_INIT: {
char * filename = (char *)argument;
ret = SrtGetSubtitle(context, filename);
break;
}
case CONTAINER_DEL: {
ret = SrtDel(context);
break;
}
case CONTAINER_SWITCH_SUBTITLE: {
ret = SrtSwitchSubtitle(context, (int*) argument);
break;
}
default:
srt_err("ConatinerCmd not supported! %d\n", command);
break;
}
srt_printf(10, "ret = %d\n", ret);
return 0;
}
static char *SrtCapabilities[] = { "srt", NULL };
Container_t SrtContainer = {
"SRT",
&Command,
SrtCapabilities,
};

View File

@@ -0,0 +1,492 @@
/*
* subtitle handling for ssa files.
*
*
* 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 <stdio.h>
#include <string.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <sys/socket.h>
#include <netdb.h>
#include <sys/types.h>
#include <dirent.h>
#include <pthread.h>
#include <errno.h>
#include <unistd.h>
#include "common.h"
#include "misc.h"
#include "subtitle.h"
/* ***************************** */
/* Makros/Constants */
/* ***************************** */
#define SSA_DEBUG
#ifdef SSA_DEBUG
static short debug_level = 10;
#define ssa_printf(level, fmt, x...) do { \
if (debug_level >= level) printf("[%s:%s] " fmt, __FILE__, __FUNCTION__, ## x); } while (0)
#else
#define ssa_printf(level, fmt, x...)
#endif
#ifndef SSA_SILENT
#define ssa_err(fmt, x...) do { printf("[%s:%s] " fmt, __FILE__, __FUNCTION__, ## x); } while (0)
#else
#define ssa_err(fmt, x...)
#endif
/* Error Constants */
#define cERR_SSA_NO_ERROR 0
#define cERR_SSA_ERROR -1
#define TRACKWRAP 20
#define MAXLINELENGTH 1000
//Buffer size used in getLine function. Do not set to value less than 1 !!!
#define SSA_BUFFER_SIZE 14
static const char FILENAME[] = __FILE__;
/* ***************************** */
/* Types */
/* ***************************** */
typedef struct {
char * File;
int Id;
} SsaTrack_t;
/* ***************************** */
/* Varaibles */
/* ***************************** */
static pthread_t thread_sub;
static SsaTrack_t * Tracks;
static int TrackCount = 0;
FILE * fssa = NULL;
static int hasThreadStarted = 0;
/* ***************************** */
/* Prototypes */
/* ***************************** */
/* ***************************** */
/* MISC Functions */
/* ***************************** */
char *SSAgetLine()
{
char *strAux = NULL, *strInput;
char c[SSA_BUFFER_SIZE], ch;
int k, tam, tamAux;
k = tamAux = 0;
if(SSA_BUFFER_SIZE>0)
{
strInput = (char*)malloc(1*sizeof(char));
strInput[0]='\0';
while(tamAux!=1)
{
if((ch = fgetc(fssa))!=EOF)
{
ungetc(ch , fssa);
fgets(c, SSA_BUFFER_SIZE, fssa);
strAux = (char*)strchr(c,'\n');
tam = strlen(c);
if(strAux != NULL)
{
tamAux = strlen(strAux);
tam--;
}
k = k + tam;
strInput = (char*)realloc(strInput, (k+1)*sizeof(char));
if(k!=tam)
strncat(strInput, c, tam);
else
strncpy(strInput, c, tam);
strInput[k] = '\0';
}
else {
tamAux = 1;
fclose(fssa);
fssa = NULL;
}
}
}
return strInput;
}
/* ***************************** */
/* Worker Thread */
/* ***************************** */
static void* SsaSubtitleThread(void *data) {
Context_t *context = (Context_t*) data;
char * head =malloc(sizeof(char)*1);
ssa_printf(10, "\n");
head[0]='\0';
while ( context && context->playback && context->playback->isPlaying && fssa ) {
char *line = NULL;
do
{
line = SSAgetLine();
if(strncmp(line,"Dialogue: ",10)) {
int head_len = strlen(head);
int line_len = strlen(line);
head = realloc(head, line_len + head_len +2);
memcpy(head + head_len, line, sizeof(char)*line_len+1);
head[head_len + line_len] = '\n';
head[head_len + line_len + 1] = '\0';
}
} while (strncmp(line,"Dialogue: ",10)!=0 && fssa);
/*Hellmaster 1024 since we have waited, we have to check if we are still paying */
if( context &&
context->playback &&
context->playback->isPlaying) {
SubtitleData_t data;
data.data = (unsigned char*) line;
data.len = strlen(line);
data.extradata = (unsigned char*) head;
data.extralen = strlen(head);
data.pts = 0;
data.duration = 0.0;
context->container->assContainer->Command(context, CONTAINER_DATA, &data);
}
free(line);
line = NULL;
continue;
}
hasThreadStarted = 0;
if(head) {
free(head);
head = NULL;
}
ssa_printf(0, "thread has ended\n");
return NULL;
}
/* ***************************** */
/* Functions */
/* ***************************** */
static void SsaManagerAdd(Context_t *context, SsaTrack_t track) {
ssa_printf(10, "%s %d\n", track.File, track.Id);
if (Tracks == NULL) {
Tracks = malloc(sizeof(SsaTrack_t) * TRACKWRAP);
}
if (TrackCount < TRACKWRAP) {
Tracks[TrackCount].File = strdup(track.File);
Tracks[TrackCount].Id = track.Id;
TrackCount++;
}
}
static char ** SsaManagerList(Context_t *context) {
char ** tracklist = NULL;
ssa_printf(10, "\n");
if (Tracks != NULL) {
char help[256];
int i = 0, j = 0;
tracklist = malloc(sizeof(char *) * ((TrackCount*2) + 1));
for (i = 0, j = 0; i < TrackCount; i++, j+=2) {
sprintf(help, "%d", Tracks[i].Id);
tracklist[j] = strdup(help);
tracklist[j+1] = strdup(Tracks[i].File);
}
tracklist[j] = NULL;
}
return tracklist;
}
static void SsaManagerDel(Context_t * context) {
int i = 0;
ssa_printf(10, "\n");
if(Tracks != NULL) {
for (i = 0; i < TrackCount; i++) {
if (Tracks[i].File != NULL)
free(Tracks[i].File);
Tracks[i].File = NULL;
}
free(Tracks);
Tracks = NULL;
}
TrackCount = 0;
}
static int SsaGetSubtitle(Context_t *context, char * Filename) {
struct dirent *dirzeiger;
DIR * dir;
int i = TEXTSSAOFFSET;
char * copyFilename = NULL;
char * FilenameExtension = NULL;
char * FilenameFolder = NULL;
char * FilenameShort = NULL;
ssa_printf(10, "\n");
if (Filename == NULL)
{
ssa_err("Filename NULL\n");
return cERR_SSA_ERROR;
}
ssa_printf(10, "file: %s\n", Filename);
copyFilename = strdup(Filename);
FilenameFolder = dirname(copyFilename);
if (FilenameFolder == NULL)
{
ssa_err("FilenameFolder NULL\n");
return cERR_SSA_ERROR;
}
ssa_printf(10, "folder: %s\n", FilenameFolder);
getExtension(copyFilename, &FilenameExtension);
if (FilenameExtension == NULL)
{
ssa_err("FilenameExtension NULL\n");
free(FilenameFolder);
return cERR_SSA_ERROR;
}
ssa_printf(10, "ext: %s\n", FilenameExtension);
FilenameShort = basename(copyFilename);
/* cut extension */
FilenameShort[strlen(FilenameShort) - strlen(FilenameExtension) - 1] = '\0';
ssa_printf(10, "basename: %s\n", FilenameShort);
ssa_printf(10, "%s\n%s | %s | %s\n", copyFilename, FilenameFolder, FilenameShort, FilenameExtension);
if((dir = opendir(FilenameFolder)) != NULL) {
while((dirzeiger = readdir(dir)) != NULL) {
char subtitleFilename[PATH_MAX];
char *subtitleExtension = NULL;
ssa_printf(20, "%s\n",(*dirzeiger).d_name);
strcpy(subtitleFilename, (*dirzeiger).d_name);
// Extension of Relativ Subtitle File Name
getExtension(subtitleFilename, &subtitleExtension);
if (subtitleExtension == NULL)
continue;
if ( strcmp(subtitleExtension, "ssa") != 0 && strcmp(subtitleExtension, "ass") != 0 )
{
free(subtitleExtension);
continue;
}
/* cut extension */
subtitleFilename[strlen(subtitleFilename) - strlen(subtitleExtension) - 1] = '\0';
ssa_printf(10, "%s %s\n", FilenameShort, subtitleFilename);
if (strncmp(FilenameShort, subtitleFilename,strlen(FilenameShort)) == 0)
{
char absSubtitleFileName[PATH_MAX];
/* found something of interest, so now make an absolut path name */
sprintf(absSubtitleFileName, "%s/%s.%s", FilenameFolder, subtitleFilename, subtitleExtension);
ssa_printf(10, "SSA: %s [%s]\n", subtitleExtension, subtitleFilename);
ssa_printf(10, "\t->%s\n", absSubtitleFileName);
SsaTrack_t SsaSubtitle = {
absSubtitleFileName,
i,
};
SsaManagerAdd(context, SsaSubtitle);
Track_t Subtitle = {
subtitleExtension,
"S_TEXT/SSA",
i++,
};
context->manager->subtitle->Command(context, MANAGER_ADD, &Subtitle);
}
free(subtitleExtension);
} /* while */
closedir(dir);
} /* if dir */
free(FilenameExtension);
free(copyFilename);
ssa_printf(10, "<\n");
return cERR_SSA_NO_ERROR;
}
static int SsaOpenSubtitle(Context_t *context, int trackid) {
ssa_printf(10, "\n");
if(trackid < TEXTSSAOFFSET || (trackid % TEXTSSAOFFSET) >= TrackCount ) {
ssa_err("trackid not for us\n");
return cERR_SSA_ERROR;
}
trackid %= TEXTSSAOFFSET;
ssa_printf(10, "%s\n", Tracks[trackid].File);
fssa = fopen(Tracks[trackid].File, "rb");
ssa_printf(10, "%s\n", fssa ? "fssa!=NULL" : "fssa==NULL");
if (!fssa)
{
ssa_err("cannot open file %s\n", Tracks[trackid].File);
return cERR_SSA_ERROR;
}
return cERR_SSA_NO_ERROR;
}
static int SsaCloseSubtitle(Context_t *context) {
ssa_printf(10, "\n");
if(fssa)
fclose(fssa);
/* this closes the thread! */
fssa = NULL;
hasThreadStarted = 0;
return cERR_SSA_NO_ERROR;
}
static int SsaSwitchSubtitle(Context_t *context, int* arg) {
int ret = cERR_SSA_NO_ERROR;
ssa_printf(10, "\n");
ret = SsaCloseSubtitle(context);
if (((ret |= SsaOpenSubtitle(context, *arg)) == cERR_SSA_NO_ERROR) && (!hasThreadStarted))
{
pthread_attr_t attr;
pthread_attr_init(&attr);
pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
pthread_create (&thread_sub, &attr, &SsaSubtitleThread, context);
hasThreadStarted = 1;
}
return ret;
}
static int SsaDel(Context_t *context) {
int ret = cERR_SSA_NO_ERROR;
ssa_printf(10, "\n");
ret = SsaCloseSubtitle(context);
SsaManagerDel(context);
return ret;
}
static int Command(void *_context, ContainerCmd_t command, void * argument) {
Context_t *context = (Context_t*) _context;
int ret = cERR_SSA_NO_ERROR;
ssa_printf(10, "\n");
switch(command) {
case CONTAINER_INIT: {
char * filename = (char *)argument;
ret = SsaGetSubtitle(context, filename);
break;
}
case CONTAINER_DEL: {
ret = SsaDel(context);
break;
}
case CONTAINER_SWITCH_SUBTITLE: {
ret = SsaSwitchSubtitle(context, (int*) argument);
break;
}
default:
ssa_err("ConatinerCmd not supported! %d\n", command);
break;
}
ssa_printf(10, "ret = %d\n", ret);
return 0;
}
static char *SsaCapabilities[] = { "ssa", NULL };
Container_t SsaContainer = {
"SSA",
&Command,
SsaCapabilities,
};

57
libeplayer3/include/aac.h Normal file
View File

@@ -0,0 +1,57 @@
/*
* aac helper
*
* 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
*
*/
#ifndef acc_123
#define acc_123
#define AAC_HEADER_LENGTH 7
static inline int aac_get_sample_rate_index (uint32_t sample_rate)
{
if (96000 <= sample_rate)
return 0;
else if (88200 <= sample_rate)
return 1;
else if (64000 <= sample_rate)
return 2;
else if (48000 <= sample_rate)
return 3;
else if (44100 <= sample_rate)
return 4;
else if (32000 <= sample_rate)
return 5;
else if (24000 <= sample_rate)
return 6;
else if (22050 <= sample_rate)
return 7;
else if (16000 <= sample_rate)
return 8;
else if (12000 <= sample_rate)
return 9;
else if (11025 <= sample_rate)
return 10;
else if (8000 <= sample_rate)
return 11;
else if (7350 <= sample_rate)
return 12;
else
return 13;
}
#endif

View File

@@ -0,0 +1,17 @@
#ifndef COMMON_H_
#define COMMON_H_
#include "container.h"
#include "output.h"
#include "manager.h"
#include "playback.h"
#include <pthread.h>
typedef struct Context_s {
PlaybackHandler_t * playback;
ContainerHandler_t * container;
OutputHandler_t * output;
ManagerHandler_t * manager;
} Context_t;
#endif

View File

@@ -0,0 +1,48 @@
#ifndef CONTAINER_H_
#define CONTAINER_H_
#include <stdio.h>
typedef enum {
CONTAINER_INIT,
CONTAINER_ADD,
CONTAINER_CAPABILITIES,
CONTAINER_PLAY,
CONTAINER_STOP,
CONTAINER_SEEK,
CONTAINER_LENGTH,
CONTAINER_DEL,
CONTAINER_SWITCH_AUDIO,
CONTAINER_SWITCH_SUBTITLE,
CONTAINER_INFO,
CONTAINER_STATUS,
CONTAINER_LAST_PTS,
CONTAINER_DATA
} ContainerCmd_t;
typedef struct Container_s {
char * Name;
int (* Command) (/*Context_t*/void *, ContainerCmd_t, void *);
char ** Capabilities;
} Container_t;
extern Container_t FFMPEGContainer;
static Container_t * AvailableContainer[] = {
&FFMPEGContainer,
NULL
};
typedef struct ContainerHandler_s {
char * Name;
Container_t * selectedContainer;
Container_t * textSrtContainer;
Container_t * textSsaContainer;
Container_t * assContainer;
int (* Command) (/*Context_t*/void *, ContainerCmd_t, void *);
} ContainerHandler_t;
#endif

View File

@@ -0,0 +1,21 @@
#ifndef debug_123
#define debug_123
#include <stdio.h>
#include <errno.h>
static inline void Hexdump(unsigned char *Data, int length)
{
int k;
for (k = 0; k < length; k++)
{
printf("%02x ", Data[k]);
if (((k+1)&31)==0)
printf("\n");
}
printf("\n");
}
#endif

View File

@@ -0,0 +1,45 @@
#ifndef _ffmpeg_metadata_123
#define _ffmpeg_metadata_123
/* these file contains a list of metadata tags which can be used by applications
* to stream specific information. it maps the tags to ffmpeg specific tags.
*
* fixme: if we add other container for some resons later (maybe some other libs
* support better demuxing or something like this), then we should think on a
* more generic mechanism!
*/
/* metatdata map list:
*/
char* metadata_map[] =
{
/* our tags ffmpeg tag / id3v2 */
"Title", "TIT2",
"Title", "TT2",
"Artist", "TPE1",
"Artist", "TP1",
"AlbumArtist", "TPE2",
"AlbumArtist", "TP2",
"Album", "TALB",
"Album", "TAL",
"Year", "TDRL", /* fixme */
"Year", "TDRC", /* fixme */
"Comment", "unknown",
"Track", "TRCK",
"Track", "TRK",
"Copyright", "TCOP",
"Composer", "TCOM",
"Genre", "TCON",
"Genre", "TCO",
"EncodedBy", "TENC",
"EncodedBy", "TEN",
"Language", "TLAN",
"Performer", "TPE3",
"Performer", "TP3",
"Publisher", "TPUB",
"Encoder", "TSSE",
"Disc", "TPOS",
NULL
};
#endif

View File

@@ -0,0 +1,77 @@
#ifndef MANAGER_H_
#define MANAGER_H_
#include <stdio.h>
#include <stdint.h>
typedef enum {
MANAGER_ADD,
MANAGER_LIST,
MANAGER_GET,
MANAGER_GETNAME,
MANAGER_SET,
MANAGER_GETENCODING,
MANAGER_DEL,
MANAGER_GET_TRACK,
} ManagerCmd_t;
typedef enum {
eTypeES,
eTypePES
} eTrackTypeEplayer;
typedef struct Track_s {
char * Name;
char * Encoding;
int Id;
/* new field for ffmpeg - add at the end so no problem
* can occur with not changed srt saa container
*/
char* language;
/* length of track */
long long int duration;
unsigned int frame_rate;
unsigned int TimeScale;
int version;
long long int pts;
/* for later use: */
eTrackTypeEplayer type;
int width;
int height;
/* stream from ffmpeg */
void * stream;
/* codec extra data (header or some other stuff) */
void * extraData;
int extraSize;
uint8_t* aacbuf;
unsigned int aacbuflen;
int have_aacheader;
/* If player2 or the elf do not support decoding of audio codec set this.
* AVCodec is than used for softdecoding and stream will be injected as PCM */
int inject_as_pcm;
} Track_t;
typedef struct Manager_s {
char * Name;
int (* Command) (/*Context_t*/void *, ManagerCmd_t, void *);
char ** Capabilities;
} Manager_t;
typedef struct ManagerHandler_s {
char * Name;
Manager_t * audio;
Manager_t * video;
Manager_t * subtitle;
} ManagerHandler_t;
void freeTrack(Track_t* track);
void copyTrack(Track_t* to, Track_t* from);
#endif

136
libeplayer3/include/misc.h Normal file
View File

@@ -0,0 +1,136 @@
#ifndef misc_123
#define misc_123
#include <dirent.h>
/* some useful things needed by many files ... */
/* ***************************** */
/* Types */
/* ***************************** */
typedef struct BitPacker_s
{
unsigned char* Ptr; /* write pointer */
unsigned int BitBuffer; /* bitreader shifter */
int Remaining; /* number of remaining in the shifter */
} BitPacker_t;
/* ***************************** */
/* Makros/Constants */
/* ***************************** */
#define INVALID_PTS_VALUE 0x200000000ull
/*#define BIG_READS*/
#if defined (BIG_READS)
#define BLOCK_COUNT 8
#else
#define BLOCK_COUNT 1
#endif
#define TP_PACKET_SIZE 188
#define BD_TP_PACKET_SIZE 192
#define NUMBER_PACKETS (199*BLOCK_COUNT)
#define BUFFER_SIZE (TP_PACKET_SIZE*NUMBER_PACKETS)
#define PADDING_LENGTH (1024*BLOCK_COUNT)
/* subtitle hacks ->for file subtitles */
#define TEXTSRTOFFSET 100
#define TEXTSSAOFFSET 200
/* ***************************** */
/* Prototypes */
/* ***************************** */
void PutBits(BitPacker_t * ld, unsigned int code, unsigned int length);
void FlushBits(BitPacker_t * ld);
/* ***************************** */
/* MISC Functions */
/* ***************************** */
static inline void getExtension(char * FILENAMEname, char ** extension) {
int i = 0;
int stringlength;
if (extension == NULL)
return;
*extension = NULL;
if (FILENAMEname == NULL)
return;
stringlength = (int) strlen(FILENAMEname);
for (i = 0; stringlength - i > 0; i++) {
if (FILENAMEname[stringlength - i - 1] == '.') {
*extension = strdup(FILENAMEname+(stringlength - i));
break;
}
}
}
static inline void getUPNPExtension(char * FILENAMEname, char ** extension) {
char* str;
if (extension == NULL)
return;
*extension = NULL;
if (FILENAMEname == NULL)
return;
str = strstr(FILENAMEname, "ext=");
if (str != NULL)
{
*extension = strdup(str + strlen("ext=") + 1);
return;
}
*extension = NULL;
}
/* the function returns the base name */
static inline char * basename(char * name)
{
int i = 0;
int pos = 0;
while(name[i] != 0)
{
if(name[i] == '/')
pos = i;
i++;
}
if(name[pos] == '/')
pos++;
return name + pos;
}
/* the function returns the directry name */
static inline char * dirname(char * name)
{
static char path[100];
int i = 0;
int pos = 0;
while((name[i] != 0) && (i < sizeof(path)))
{
if(name[i] == '/')
pos = i;
path[i] = name[i];
i++;
}
path[i] = 0;
path[pos] = 0;
return path;
}
#endif

View File

@@ -0,0 +1,79 @@
#ifndef OUTPUT_H_
#define OUTPUT_H_
#include <stdio.h>
typedef enum {
OUTPUT_INIT,
OUTPUT_ADD,
OUTPUT_DEL,
OUTPUT_CAPABILITIES,
OUTPUT_PLAY,
OUTPUT_STOP,
OUTPUT_PAUSE,
OUTPUT_OPEN,
OUTPUT_CLOSE,
OUTPUT_FLUSH,
OUTPUT_CONTINUE,
OUTPUT_FASTFORWARD,
OUTPUT_AVSYNC,
OUTPUT_CLEAR,
OUTPUT_PTS,
OUTPUT_SWITCH,
OUTPUT_SLOWMOTION,
OUTPUT_AUDIOMUTE,
OUTPUT_REVERSE,
OUTPUT_DISCONTINUITY_REVERSE,
OUTPUT_GET_FRAME_COUNT,
/* fixme: e2 */
OUTPUT_SUBTITLE_REGISTER_FUNCTION = 222,
OUTPUT_SUBTITLE_REGISTER_BUFFER = 223,
OUTPUT_GET_SUBTITLE_OUTPUT,
OUTPUT_SET_SUBTITLE_OUTPUT,
} OutputCmd_t;
typedef struct
{
unsigned char* data;
unsigned int len;
unsigned char* extradata;
unsigned int extralen;
unsigned long long int pts;
float frameRate;
unsigned int timeScale;
unsigned int width;
unsigned int height;
char* type;
} AudioVideoOut_t;
typedef struct Output_s {
char * Name;
int (* Command) (/*Context_t*/void *, OutputCmd_t, void *);
int (* Write) (/*Context_t*/void *, void* privateData);
char ** Capabilities;
} Output_t;
extern Output_t LinuxDvbOutput;
extern Output_t SubtitleOutput;
static Output_t * AvailableOutput[] = {
&LinuxDvbOutput,
&SubtitleOutput,
NULL
};
typedef struct OutputHandler_s {
char * Name;
Output_t * audio;
Output_t * video;
Output_t * subtitle;
int (* Command) (/*Context_t*/void *, OutputCmd_t, void *);
} OutputHandler_t;
#endif

30
libeplayer3/include/pcm.h Normal file
View File

@@ -0,0 +1,30 @@
/*
* pcm helper
*
* 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
*
*/
#ifndef pcm_h_
#define pcm_h_
typedef struct pcmPrivateData_s
{
int uNoOfChannels;
int uSampleRate;
int uBitsPerSample;
int bLittleEndian;
} pcmPrivateData_t;
#endif

33
libeplayer3/include/pes.h Normal file
View File

@@ -0,0 +1,33 @@
#ifndef pes_123
#define pes_123
#define PES_MAX_HEADER_SIZE 64
#define PES_PRIVATE_DATA_FLAG 0x80
#define PES_PRIVATE_DATA_LENGTH 8
#define PES_LENGTH_BYTE_0 5
#define PES_LENGTH_BYTE_1 4
#define PES_FLAGS_BYTE 7
#define PES_EXTENSION_DATA_PRESENT 0x01
#define PES_HEADER_DATA_LENGTH_BYTE 8
#define PES_MIN_HEADER_SIZE 9
#define PES_START_CODE_RESERVED_4 0xfd
#define PES_VERSION_FAKE_START_CODE 0x31
#define MAX_PES_PACKET_SIZE 65400
/* start codes */
#define PCM_PES_START_CODE 0xbd
#define PRIVATE_STREAM_1_PES_START_CODE 0xbd
#define H263_VIDEO_PES_START_CODE 0xfe
#define H264_VIDEO_PES_START_CODE 0xe2
#define MPEG_VIDEO_PES_START_CODE 0xe0
#define MPEG_AUDIO_PES_START_CODE 0xc0
#define VC1_VIDEO_PES_START_CODE 0xfd
#define AAC_AUDIO_PES_START_CODE 0xcf
int InsertPesHeader (unsigned char *data, int size, unsigned char stream_id, unsigned long long int pts, int pic_start_code);
int InsertVideoPrivateDataHeader(unsigned char *data, int payload_size);
#endif

View File

@@ -0,0 +1,36 @@
#ifndef PLAYBACK_H_
#define PLAYBACK_H_
#include <sys/types.h>
typedef enum {PLAYBACK_OPEN, PLAYBACK_CLOSE, PLAYBACK_PLAY, PLAYBACK_STOP, PLAYBACK_PAUSE, PLAYBACK_CONTINUE, PLAYBACK_FLUSH, PLAYBACK_TERM, PLAYBACK_FASTFORWARD, PLAYBACK_SEEK, PLAYBACK_PTS, PLAYBACK_LENGTH, PLAYBACK_SWITCH_AUDIO, PLAYBACK_SWITCH_SUBTITLE, PLAYBACK_INFO, PLAYBACK_SLOWMOTION, PLAYBACK_FASTBACKWARD, PLAYBACK_GET_FRAME_COUNT} PlaybackCmd_t;
typedef struct PlaybackHandler_s {
char * Name;
int fd;
unsigned char isFile;
unsigned char isHttp;
unsigned char isUPNP;
unsigned char isPlaying;
unsigned char isPaused;
unsigned char isForwarding;
unsigned char isSeeking;
unsigned char isCreationPhase;
float BackWard;
int SlowMotion;
int Speed;
int AVSync;
unsigned char isVideo;
unsigned char isAudio;
unsigned char isSubtitle;
int (* Command) (/*Context_t*/void *, PlaybackCmd_t, void *);
char * uri;
off_t size;
} PlaybackHandler_t;
#endif

View File

@@ -0,0 +1,325 @@
/*
* stm_ioctls.h
*
* Copyright (C) STMicroelectronics Limited 2005. All rights reserved.
*
* Extensions to the LinuxDVB API (v3) implemented by the Havana implemenation.
*/
#ifndef H_STM_IOCTLS
#define H_STM_IOCTLS
/*
* Whenever a sequence of values is extended (define or enum) always add the new values
* So that old values are unchange to maintain binary compatibility.
*/
#define DVB_SPEED_NORMAL_PLAY 1000
#define DVB_SPEED_STOPPED 0
#define DVB_SPEED_REVERSE_STOPPED 0x80000000
#define DVB_FRAME_RATE_MULTIPLIER 1000
#define VIDEO_FULL_SCREEN (VIDEO_CENTER_CUT_OUT+1)
#define DMX_FILTER_BY_PRIORITY_LOW 0x00010000 /* These flags tell the transport pes filter whether to filter */
#define DMX_FILTER_BY_PRIORITY_HIGH 0x00020000 /* using the ts priority bit and, if so, whether to filter on */
#define DMX_FILTER_BY_PRIORITY_MASK 0x00030000 /* bit set or bit clear */
/*
* Extra events
*/
#define VIDEO_EVENT_FIRST_FRAME_ON_DISPLAY 5 /*(VIDEO_EVENT_VSYNC+1)*/
#define VIDEO_EVENT_FRAME_DECODED_LATE (VIDEO_EVENT_FIRST_FRAME_ON_DISPLAY+1)
#define VIDEO_EVENT_DATA_DELIVERED_LATE (VIDEO_EVENT_FRAME_DECODED_LATE+1)
#define VIDEO_EVENT_STREAM_UNPLAYABLE (VIDEO_EVENT_DATA_DELIVERED_LATE+1)
#define VIDEO_EVENT_TRICK_MODE_CHANGE (VIDEO_EVENT_STREAM_UNPLAYABLE+1)
#define VIDEO_EVENT_VSYNC_OFFSET_MEASURED (VIDEO_EVENT_TRICK_MODE_CHANGE+1)
#define VIDEO_EVENT_FATAL_ERROR (VIDEO_EVENT_VSYNC_OFFSET_MEASURED+1)
#define VIDEO_EVENT_OUTPUT_SIZE_CHANGED (VIDEO_EVENT_FATAL_ERROR+1)
#define VIDEO_EVENT_FATAL_HARDWARE_FAILURE (VIDEO_EVENT_OUTPUT_SIZE_CHANGED+1)
/*
* List of possible container types - used to select demux.. If stream_source is VIDEO_SOURCE_DEMUX
* then default is TRANSPORT, if stream_source is VIDEO_SOURCE_MEMORY then default is PES
*/
typedef enum {
STREAM_TYPE_NONE, /* Deprecated */
STREAM_TYPE_TRANSPORT,/* Use latest PTI driver so it can be Deprecated */
STREAM_TYPE_PES,
STREAM_TYPE_ES, /* Deprecated */
STREAM_TYPE_PROGRAM, /* Deprecated */
STREAM_TYPE_SYSTEM, /* Deprecated */
STREAM_TYPE_SPU, /* Deprecated */
STREAM_TYPE_NAVI, /* Deprecated */
STREAM_TYPE_CSS, /* Deprecated */
STREAM_TYPE_AVI, /* Deprecated */
STREAM_TYPE_MP3, /* Deprecated */
STREAM_TYPE_H264, /* Deprecated */
STREAM_TYPE_ASF, /* Needs work so it can be deprecated */
STREAM_TYPE_MP4, /* Deprecated */
STREAM_TYPE_RAW, /* Deprecated */
} stream_type_t;
/*
* List of possible video encodings - used to select frame parser and codec.
*/
typedef enum {
VIDEO_ENCODING_AUTO,
VIDEO_ENCODING_MPEG1,
VIDEO_ENCODING_MPEG2,
VIDEO_ENCODING_MJPEG,
VIDEO_ENCODING_DIVX3,
VIDEO_ENCODING_DIVX4,
VIDEO_ENCODING_DIVX5,
VIDEO_ENCODING_MPEG4P2,
VIDEO_ENCODING_H264,
VIDEO_ENCODING_WMV,
VIDEO_ENCODING_VC1,
VIDEO_ENCODING_RAW,
VIDEO_ENCODING_H263,
VIDEO_ENCODING_FLV1,
VIDEO_ENCODING_VP6,
VIDEO_ENCODING_RMV,
VIDEO_ENCODING_DIVXHD,
VIDEO_ENCODING_AVS,
VIDEO_ENCODING_VP3,
VIDEO_ENCODING_THEORA,
VIDEO_ENCODING_COMPOCAP,
VIDEO_ENCODING_NONE,
VIDEO_ENCODING_PRIVATE
} video_encoding_t;
/*
* List of possible audio encodings - used to select frame parser and codec.
*/
typedef enum {
AUDIO_ENCODING_AUTO,
AUDIO_ENCODING_PCM,
AUDIO_ENCODING_LPCM,
AUDIO_ENCODING_MPEG1,
AUDIO_ENCODING_MPEG2,
AUDIO_ENCODING_MP3,
AUDIO_ENCODING_AC3,
AUDIO_ENCODING_DTS,
AUDIO_ENCODING_AAC,
AUDIO_ENCODING_WMA,
AUDIO_ENCODING_RAW,
AUDIO_ENCODING_LPCMA,
AUDIO_ENCODING_LPCMH,
AUDIO_ENCODING_LPCMB,
AUDIO_ENCODING_SPDIF, /*<! Data coming through SPDIF link :: compressed or PCM data */
AUDIO_ENCODING_DTS_LBR,
AUDIO_ENCODING_MLP,
AUDIO_ENCODING_RMA,
AUDIO_ENCODING_AVS,
AUDIO_ENCODING_VORBIS,
AUDIO_ENCODING_NONE,
AUDIO_ENCODING_PRIVATE
} audio_encoding_t;
/*
* List of possible sources for SP/DIF output.
*/
typedef enum audio_spdif_source {
AUDIO_SPDIF_SOURCE_PP, /*<! normal decoder output */
AUDIO_SPDIF_SOURCE_DEC, /*<! decoder output w/o post-proc */
AUDIO_SPDIF_SOURCE_ES, /*<! raw elementary stream data */
} audio_spdif_source_t;
typedef struct {
int x;
int y;
int width;
int height;
} video_window_t;
typedef enum
{
DVB_DISCONTINUITY_SKIP = 0x01,
DVB_DISCONTINUITY_CONTINUOUS_REVERSE = 0x02,
DVB_DISCONTINUITY_SURPLUS_DATA = 0x04
} dvb_discontinuity_t;
/*
* audio discontinuity
*/
typedef enum {
AUDIO_DISCONTINUITY_SKIP = DVB_DISCONTINUITY_SKIP,
AUDIO_DISCONTINUITY_CONTINUOUS_REVERSE = DVB_DISCONTINUITY_CONTINUOUS_REVERSE,
AUDIO_DISCONTINUITY_SURPLUS_DATA = DVB_DISCONTINUITY_SURPLUS_DATA,
} audio_discontinuity_t;
/*
* video discontinuity
*/
typedef enum {
VIDEO_DISCONTINUITY_SKIP = DVB_DISCONTINUITY_SKIP,
VIDEO_DISCONTINUITY_CONTINUOUS_REVERSE = DVB_DISCONTINUITY_CONTINUOUS_REVERSE,
VIDEO_DISCONTINUITY_SURPLUS_DATA = DVB_DISCONTINUITY_SURPLUS_DATA,
} video_discontinuity_t;
#define DVB_TIME_NOT_BOUNDED 0xfedcba9876543210ULL
typedef struct dvb_play_interval_s {
unsigned long long start;
unsigned long long end;
}dvb_play_interval_t;
typedef dvb_play_interval_t video_play_interval_t;
typedef dvb_play_interval_t audio_play_interval_t;
typedef struct dvb_play_time_s {
unsigned long long system_time;
unsigned long long presentation_time;
unsigned long long pts;
}dvb_play_time_t;
typedef dvb_play_time_t video_play_time_t;
typedef dvb_play_time_t audio_play_time_t;
typedef struct dvb_play_info_s {
unsigned long long system_time;
unsigned long long presentation_time;
unsigned long long pts;
unsigned long long frame_count;
}dvb_play_info_t;
typedef dvb_play_info_t video_play_info_t;
typedef dvb_play_info_t audio_play_info_t;
typedef enum {
#define DVB_OPTION_VALUE_DISABLE 0
#define DVB_OPTION_VALUE_ENABLE 1
DVB_OPTION_TRICK_MODE_AUDIO = 0,
DVB_OPTION_PLAY_24FPS_VIDEO_AT_25FPS = 1,
#define DVB_OPTION_VALUE_VIDEO_CLOCK_MASTER 0
#define DVB_OPTION_VALUE_AUDIO_CLOCK_MASTER 1
#define DVB_OPTION_VALUE_SYSTEM_CLOCK_MASTER 2
DVB_OPTION_MASTER_CLOCK = 2,
DVB_OPTION_EXTERNAL_TIME_MAPPING = 3,
DVB_OPTION_EXTERNAL_TIME_MAPPING_VSYNC_LOCKED = 31,
DVB_OPTION_AV_SYNC = 4,
DVB_OPTION_DISPLAY_FIRST_FRAME_EARLY = 5,
DVB_OPTION_VIDEO_BLANK = 6,
DVB_OPTION_STREAM_ONLY_KEY_FRAMES = 7,
DVB_OPTION_STREAM_SINGLE_GROUP_BETWEEN_DISCONTINUITIES = 8,
DVB_OPTION_CLAMP_PLAYBACK_INTERVAL_ON_PLAYBACK_DIRECTION_CHANGE = 9,
#define DVB_OPTION_VALUE_PLAYOUT 0
#define DVB_OPTION_VALUE_DISCARD 1
DVB_OPTION_PLAYOUT_ON_TERMINATE = 10,
DVB_OPTION_PLAYOUT_ON_SWITCH = 11,
DVB_OPTION_PLAYOUT_ON_DRAIN = 12,
DVB_OPTION_VIDEO_ASPECT_RATIO = 13,
DVB_OPTION_VIDEO_DISPLAY_FORMAT = 14,
#define DVB_OPTION_VALUE_TRICK_MODE_AUTO 0
#define DVB_OPTION_VALUE_TRICK_MODE_DECODE_ALL 1
#define DVB_OPTION_VALUE_TRICK_MODE_DECODE_ALL_DEGRADE_NON_REFERENCE_FRAMES 2
#define DVB_OPTION_VALUE_TRICK_MODE_START_DISCARDING_NON_REFERENCE_FRAMES 3
#define DVB_OPTION_VALUE_TRICK_MODE_DECODE_REFERENCE_FRAMES_DEGRADE_NON_KEY_FRAMES 4
#define DVB_OPTION_VALUE_TRICK_MODE_DECODE_KEY_FRAMES 5
#define DVB_OPTION_VALUE_TRICK_MODE_DISCONTINUOUS_KEY_FRAMES 6
DVB_OPTION_TRICK_MODE_DOMAIN = 15,
#define DVB_OPTION_VALUE_DISCARD_LATE_FRAMES_NEVER 0
#define DVB_OPTION_VALUE_DISCARD_LATE_FRAMES_ALWAYS 1
#define DVB_OPTION_VALUE_DISCARD_LATE_FRAMES_AFTER_SYNCHRONIZE 2
DVB_OPTION_DISCARD_LATE_FRAMES = 16,
DVB_OPTION_VIDEO_START_IMMEDIATE = 17,
DVB_OPTION_REBASE_ON_DATA_DELIVERY_LATE = 18,
DVB_OPTION_REBASE_ON_FRAME_DECODE_LATE = 19,
DVB_OPTION_LOWER_CODEC_DECODE_LIMITS_ON_FRAME_DECODE_LATE = 20,
DVB_OPTION_H264_ALLOW_NON_IDR_RESYNCHRONIZATION = 21,
DVB_OPTION_MPEG2_IGNORE_PROGESSIVE_FRAME_FLAG = 22,
DVB_OPTION_AUDIO_SPDIF_SOURCE = 23,
DVB_OPTION_H264_ALLOW_BAD_PREPROCESSED_FRAMES = 24,
DVB_OPTION_CLOCK_RATE_ADJUSTMENT_LIMIT_2_TO_THE_N_PARTS_PER_MILLION = 25, /* Value = N */
DVB_OPTION_LIMIT_INPUT_INJECT_AHEAD = 26,
#define DVB_OPTION_VALUE_MPEG2_APPLICATION_MPEG2 0
#define DVB_OPTION_VALUE_MPEG2_APPLICATION_ATSC 1
#define DVB_OPTION_VALUE_MPEG2_APPLICATION_DVB 2
DVB_OPTION_MPEG2_APPLICATION_TYPE = 27,
#define DVB_OPTION_VALUE_DECIMATE_DECODER_OUTPUT_DISABLED 0
#define DVB_OPTION_VALUE_DECIMATE_DECODER_OUTPUT_HALF 1
#define DVB_OPTION_VALUE_DECIMATE_DECODER_OUTPUT_QUARTER 2
DVB_OPTION_DECIMATE_DECODER_OUTPUT = 28,
DVB_OPTION_PTS_FORWARD_JUMP_DETECTION_THRESHOLD = 29,
DVB_OPTION_H264_TREAT_DUPLICATE_DPB_AS_NON_REFERENCE_FRAME_FIRST = 30,
DVB_OPTION_PIXEL_ASPECT_RATIO_CORRECTION = 32,
DVB_OPTION_H264_FORCE_PIC_ORDER_CNT_IGNORE_DPB_DISPLAY_FRAME_ORDERING = 33,
DVB_OPTION_PTS_SYMMETRIC_JUMP_DETECTION = 34,
DVB_OPTION_ALLOW_FRAME_DISCARD_AT_NORMAL_SPEED = 35,
/* OPTION_MAX must always be one greater than largest option - currently DVB_OPTION_ALLOW_FRAME_DISCARD_AT_NORMAL_SPEED */
DVB_OPTION_MAX = 35
} dvb_option_t;
// Legacy typo correction
#define DVP_OPTION_H264_FORCE_PIC_ORDER_CNT_IGNORE_DPB_DISPLAY_FRAME_ORDERING DVB_OPTION_H264_FORCE_PIC_ORDER_CNT_IGNORE_DPB_DISPLAY_FRAME_ORDERING
typedef dvb_option_t video_option_t;
/* Decoder commands */
#define VIDEO_CMD_PLAY (0)
#define VIDEO_CMD_STOP (1)
#define VIDEO_CMD_FREEZE (2)
#define VIDEO_CMD_CONTINUE (3)
#define VIDEO_CMD_SET_OPTION (4)
#define VIDEO_CMD_GET_OPTION (5)
/* Flags for VIDEO_CMD_FREEZE */
#define VIDEO_CMD_FREEZE_TO_BLACK (1 << 0)
/* Flags for VIDEO_CMD_STOP */
#define VIDEO_CMD_STOP_TO_BLACK (1 << 0)
#define VIDEO_CMD_STOP_IMMEDIATELY (1 << 1)
/* Play input formats: */
/* The decoder has no special format requirements */
#define VIDEO_PLAY_FMT_NONE (0)
/* The decoder requires full GOPs */
#define VIDEO_PLAY_FMT_GOP (1)
/* ST specific video ioctls */
#define VIDEO_SET_ENCODING _IO('o', 81)
#define VIDEO_FLUSH _IO('o', 82)
#define VIDEO_SET_SPEED _IO('o', 83)
#define VIDEO_DISCONTINUITY _IO('o', 84)
#define VIDEO_STEP _IO('o', 85)
#define VIDEO_SET_PLAY_INTERVAL _IOW('o', 86, video_play_interval_t)
#define VIDEO_SET_SYNC_GROUP _IO('o', 87)
#define VIDEO_GET_PLAY_TIME _IOR('o', 88, video_play_time_t)
#define VIDEO_GET_PLAY_INFO _IOR('o', 89, video_play_info_t)
/* ST specific audio ioctls */
#define AUDIO_SET_ENCODING _IO('o', 70)
#define AUDIO_FLUSH _IO('o', 71)
#define AUDIO_SET_SPDIF_SOURCE _IO('o', 72)
#define AUDIO_SET_SPEED _IO('o', 73)
#define AUDIO_DISCONTINUITY _IO('o', 74)
#define AUDIO_SET_PLAY_INTERVAL _IOW('o', 75, audio_play_interval_t)
#define AUDIO_SET_SYNC_GROUP _IO('o', 76)
#define AUDIO_GET_PLAY_TIME _IOR('o', 77, audio_play_time_t)
#define AUDIO_GET_PLAY_INFO _IOR('o', 78, audio_play_info_t)
#endif /* H_DVB_STM_H */

View File

@@ -0,0 +1,126 @@
#ifndef _subtitle_123
#define _subtitle_123
/*
* Interface File for subtitle handling (container input and output).
*
*
* 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
*
*/
#define DEFAULT_ASS_HEAD "[Script Info]\n\
Original Script: (c) 2008\n\
ScriptType: v4.00\n\
Synch Point: Side 1 0m00s\n\
Collisions: Normal\n\
Timer: 100.0000\n\n\
[V4 Styles]\n\
Format: Name, Fontname, Fontsize, PrimaryColour, SecondaryColour, TertiaryColour, BackColour, Bold, Italic, BorderStyle, Outline, Shadow, Alignment, MarginL, MarginR, MarginV, AlphaLevel, Encoding\n\
Style: Default,Arial,26,16777215,0,16777215,0,0,0,2,2,2,2,20,20,10,0\n\n\
[Events]\n\
Format: Marked, Start, End, Style, Name, MarginL, MarginR, MarginV, Effect, Text\n\n\n"
static inline unsigned char* text_to_ass(char *text, long long int pts, double duration)
{
char buf[1024];
int x,pos=0;
for(x=0;x<strlen(text);x++){
if(text[x]=='\n'){
buf[pos++]='\\';
buf[pos++]='N';
}else if(text[x]!='\r')buf[pos++]=text[x];
}
buf[pos++]='\0';
int len = 80 + strlen(buf);
long long int end_pts = pts + (duration * 1000.0);
char* line = (char*)malloc( sizeof(char) * len );
int sc = pts / 10;
int ec = end_pts / 10;
int sh, sm, ss, eh, em, es;
sh = sc/360000; sc -= 360000*sh;
sm = sc/ 6000; sc -= 6000*sm;
ss = sc/ 100; sc -= 100*ss;
eh = ec/360000; ec -= 360000*eh;
em = ec/ 6000; ec -= 6000*em;
es = ec/ 100; ec -= 100*es;
snprintf(line,len,"Dialogue: Marked=0,%d:%02d:%02d.%02d,%d:%02d:%02d.%02d,Default,NTP,0000,0000,0000,!Effect,%s\n",
sh, sm, ss, sc, eh, em, es, ec, buf);
return (unsigned char*)line;
}
typedef enum
{
eSub_Gfx,
eSub_Txt
} SubType_t;
typedef struct
{
unsigned char* data;
int len;
} SubText_t;
typedef struct
{
unsigned char* data;
unsigned int Width;
unsigned int Height;
unsigned int Stride;
unsigned int x;
unsigned int y;
unsigned int color;
} SubGfx_t;
typedef struct
{
SubType_t type;
long long int pts;
float duration;
union
{
SubText_t text;
SubGfx_t gfx;
} u;
} SubtitleOut_t;
typedef struct
{
unsigned char* data;
int len;
unsigned char* extradata;
int extralen;
long long int pts;
float duration;
} SubtitleData_t;
typedef struct
{
unsigned char* destination;
unsigned int screen_width;
unsigned int screen_height;
unsigned int destStride;
int shareFramebuffer;
int framebufferFD;
} SubtitleOutputDef_t;
#endif

View File

@@ -0,0 +1,108 @@
#ifndef WRITER_H_
#define WRITER_H_
#include <stdio.h>
typedef enum { eNone, eAudio, eVideo, eGfx} eWriterType_t;
typedef struct {
int fd;
unsigned char* data;
unsigned int len;
unsigned long long int Pts;
unsigned char* private_data;
unsigned int private_size;
unsigned int FrameRate;
unsigned int FrameScale;
unsigned int Width;
unsigned int Height;
unsigned char Version;
} WriterAVCallData_t;
typedef struct {
unsigned char* data;
unsigned int Width;
unsigned int Height;
unsigned int Stride;
unsigned int color;
unsigned int x; /* dst x ->given by ass */
unsigned int y; /* dst y ->given by ass */
/* destination values if we use a shared framebuffer */
int fd;
unsigned int Screen_Width;
unsigned int Screen_Height;
unsigned char* destination;
unsigned int destStride;
} WriterFBCallData_t;
typedef struct WriterCaps_s {
char* name;
eWriterType_t type;
char* textEncoding;
/* fixme: revise if this is an enum! */
int dvbEncoding;
} WriterCaps_t;
typedef struct Writer_s {
int (* reset) ();
int (* writeData) (void*);
int (* writeReverseData) (void*);
WriterCaps_t *caps;
} Writer_t;
extern Writer_t WriterAudioIPCM;
extern Writer_t WriterAudioMP3;
extern Writer_t WriterAudioMPEGL3;
extern Writer_t WriterAudioAC3;
extern Writer_t WriterAudioAAC;
extern Writer_t WriterAudioDTS;
extern Writer_t WriterAudioWMA;
extern Writer_t WriterAudioFLAC;
extern Writer_t WriterAudioVORBIS;
extern Writer_t WriterVideoMPEG2;
extern Writer_t WriterVideoMPEGH264;
extern Writer_t WriterVideoH264;
extern Writer_t WriterVideoWMV;
extern Writer_t WriterVideoDIVX;
extern Writer_t WriterVideoFOURCC;
extern Writer_t WriterVideoMSCOMP;
extern Writer_t WriterVideoH263;
extern Writer_t WriterVideoFLV;
extern Writer_t WriterVideoVC1;
extern Writer_t WriterFramebuffer;
static Writer_t * AvailableWriter[] = {
&WriterAudioIPCM,
&WriterAudioMP3,
&WriterAudioMPEGL3,
&WriterAudioAC3,
&WriterAudioAAC,
&WriterAudioDTS,
&WriterAudioWMA,
&WriterAudioFLAC,
&WriterAudioVORBIS,
&WriterVideoMPEG2,
&WriterVideoMPEGH264,
&WriterVideoH264,
&WriterVideoDIVX,
&WriterVideoFOURCC,
&WriterVideoMSCOMP,
&WriterVideoWMV,
&WriterVideoH263,
&WriterVideoFLV,
&WriterVideoVC1,
&WriterFramebuffer,
NULL
};
Writer_t* getWriter(char* encoding);
Writer_t* getDefaultVideoWriter();
Writer_t* getDefaultAudioWriter();
Writer_t* getDefaultFramebufferWriter();
#endif

249
libeplayer3/manager/audio.c Normal file
View File

@@ -0,0 +1,249 @@
/*
* audio manager 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 <stdlib.h>
#include <string.h>
#include "manager.h"
#include "common.h"
/* ***************************** */
/* Makros/Constants */
/* ***************************** */
#define TRACKWRAP 20
#define AUDIO_MGR_DEBUG
#ifdef AUDIO_MGR_DEBUG
static short debug_level = 0;
#define audio_mgr_printf(level, x...) do { \
if (debug_level >= level) printf(x); } while (0)
#else
#define audio_mgr_printf(level, x...)
#endif
#ifndef AUDIO_MGR_SILENT
#define audio_mgr_err(x...) do { printf(x); } while (0)
#else
#define audio_mgr_err(x...)
#endif
/* Error Constants */
#define cERR_AUDIO_MGR_NO_ERROR 0
#define cERR_AUDIO_MGR_ERROR -1
static const char FILENAME[] = __FILE__;
/* ***************************** */
/* Types */
/* ***************************** */
/* ***************************** */
/* Varaibles */
/* ***************************** */
static Track_t * Tracks;
static int TrackCount = 0;
static int CurrentTrack = 0; //TRACK[0] as default.
/* ***************************** */
/* Prototypes */
/* ***************************** */
/* ***************************** */
/* Functions */
/* ***************************** */
static int ManagerAdd(Context_t *context, Track_t track) {
audio_mgr_printf(10, "%s::%s name=\"%s\" encoding=\"%s\" id=%d\n", FILENAME, __FUNCTION__, track.Name, track.Encoding, track.Id);
if (Tracks == NULL) {
Tracks = malloc(sizeof(Track_t) * TRACKWRAP);
}
if (Tracks == NULL)
{
audio_mgr_err("%s:%s malloc failed\n", FILENAME, __FUNCTION__);
return cERR_AUDIO_MGR_ERROR;
}
if (TrackCount < TRACKWRAP) {
copyTrack(&Tracks[TrackCount], &track);
TrackCount++;
} else {
audio_mgr_err("%s:%s TrackCount out if range %d - %d\n", FILENAME, __FUNCTION__, TrackCount, TRACKWRAP);
return cERR_AUDIO_MGR_ERROR;
}
if (TrackCount > 0)
context->playback->isAudio = 1;
audio_mgr_printf(10, "%s::%s\n", FILENAME, __FUNCTION__);
return cERR_AUDIO_MGR_NO_ERROR;
}
static char ** ManagerList(Context_t *context) {
int i = 0, j = 0;
char ** tracklist = NULL;
audio_mgr_printf(10, "%s::%s\n", FILENAME, __FUNCTION__);
if (Tracks != NULL) {
tracklist = malloc(sizeof(char *) * ((TrackCount*2) + 1));
if (tracklist == NULL)
{
audio_mgr_err("%s:%s malloc failed\n", FILENAME, __FUNCTION__);
return NULL;
}
for (i = 0, j = 0; i < TrackCount; i++, j+=2) {
tracklist[j] = strdup(Tracks[i].Name);
tracklist[j+1] = strdup(Tracks[i].Encoding);
}
tracklist[j] = NULL;
}
audio_mgr_printf(10, "%s::%s return %p (%d - %d)\n", FILENAME, __FUNCTION__, tracklist, j, TrackCount);
return tracklist;
}
static int ManagerDel(Context_t * context) {
int i = 0;
audio_mgr_printf(10, "%s::%s\n", FILENAME, __FUNCTION__);
if(Tracks != NULL) {
for (i = 0; i < TrackCount; i++) {
freeTrack(&Tracks[i]);
}
free(Tracks);
Tracks = NULL;
} else
{
audio_mgr_err("%s::%s nothing to delete!\n", FILENAME, __FUNCTION__);
return cERR_AUDIO_MGR_ERROR;
}
TrackCount = 0;
CurrentTrack = 0;
context->playback->isAudio = 0;
audio_mgr_printf(10, "%s::%s return no error\n", FILENAME, __FUNCTION__);
return cERR_AUDIO_MGR_NO_ERROR;
}
static int Command(void *_context, ManagerCmd_t command, void * argument) {
Context_t *context = (Context_t*) _context;
int ret = cERR_AUDIO_MGR_NO_ERROR;
audio_mgr_printf(10, "%s::%s\n", FILENAME, __FUNCTION__);
switch(command) {
case MANAGER_ADD: {
Track_t * track = argument;
ret = ManagerAdd(context, *track);
break;
}
case MANAGER_LIST: {
*((char***)argument) = (char **)ManagerList(context);
break;
}
case MANAGER_GET: {
audio_mgr_printf(20, "%s::%s MANAGER_GET\n", FILENAME, __FUNCTION__);
if ((TrackCount > 0) && (CurrentTrack >=0))
*((int*)argument) = (int)Tracks[CurrentTrack].Id;
else
*((int*)argument) = (int)-1;
break;
}
case MANAGER_GET_TRACK: {
audio_mgr_printf(20, "%s::%s MANAGER_GET_TRACK\n", FILENAME, __FUNCTION__);
if ((TrackCount > 0) && (CurrentTrack >=0))
*((Track_t**)argument) = (Track_t*) &Tracks[CurrentTrack];
else
*((Track_t**)argument) = NULL;
break;
}
case MANAGER_GETENCODING: {
if ((TrackCount > 0) && (CurrentTrack >=0))
*((char**)argument) = (char *)strdup(Tracks[CurrentTrack].Encoding);
else
*((char**)argument) = (char *)strdup("");
break;
}
case MANAGER_GETNAME: {
if ((TrackCount > 0) && (CurrentTrack >=0))
*((char**)argument) = (char *)strdup(Tracks[CurrentTrack].Name);
else
*((char**)argument) = (char *)strdup("");
break;
}
case MANAGER_SET: {
int id = *((int*)argument);
audio_mgr_printf(20, "%s::%s MANAGER_SET id=%d\n", FILENAME, __FUNCTION__, id);
if (id < TrackCount)
CurrentTrack = id;
else
{
audio_mgr_err("%s::%s track id out of range (%d - %d)\n", FILENAME, __FUNCTION__, id, TrackCount);
ret = cERR_AUDIO_MGR_ERROR;
}
break;
}
case MANAGER_DEL: {
ret = ManagerDel(context);
break;
}
default:
audio_mgr_err("%s::%s ContainerCmd %d not supported!\n", FILENAME, __FUNCTION__, command);
ret = cERR_AUDIO_MGR_ERROR;
break;
}
audio_mgr_printf(10, "%s:%s: returning %d\n", FILENAME, __FUNCTION__,ret);
return ret;
}
struct Manager_s AudioManager = {
"Audio",
&Command,
NULL,
};

View File

@@ -0,0 +1,93 @@
/*
* manager 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 <stdlib.h>
#include <string.h>
#include "manager.h"
/* ***************************** */
/* Makros/Constants */
/* ***************************** */
/* ***************************** */
/* Types */
/* ***************************** */
/* ***************************** */
/* Varaibles */
/* ***************************** */
extern Manager_t AudioManager;
extern Manager_t VideoManager;
extern Manager_t SubtitleManager;
ManagerHandler_t ManagerHandler = {
"ManagerHandler",
&AudioManager,
&VideoManager,
&SubtitleManager,
};
/* ***************************** */
/* Prototypes */
/* ***************************** */
/* ***************************** */
/* Functions */
/* ***************************** */
void copyTrack(Track_t* to, Track_t* from)
{
*to = *from;
if (from->Name != NULL)
to->Name = strdup(from->Name);
else
to->Name = strdup("Unknown");
if (from->Encoding != NULL)
to->Encoding = strdup(from->Encoding);
else
to->Encoding = strdup("Unknown");
if (from->language != NULL)
to->language = strdup(from->language);
else
to->language = strdup("Unknown");
}
void freeTrack(Track_t* track)
{
if (track->Name != NULL)
free(track->Name);
if (track->Encoding != NULL)
free(track->Encoding);
if (track->language != NULL)
free(track->language);
if (track->aacbuf != NULL)
free(track->aacbuf);
}

View File

@@ -0,0 +1,253 @@
/*
* subtitle manager 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 <stdlib.h>
#include <string.h>
#include "manager.h"
#include "common.h"
/* ***************************** */
/* Makros/Constants */
/* ***************************** */
#define TRACKWRAP 20
#define SUBTITLE_MGR_DEBUG
#ifdef SUBTITLE_MGR_DEBUG
static short debug_level = 10;
#define subtitle_mgr_printf(level, x...) do { \
if (debug_level >= level) printf(x); } while (0)
#else
#define subtitle_mgr_printf(level, x...)
#endif
#ifndef SUBTITLE_MGR_SILENT
#define subtitle_mgr_err(x...) do { printf(x); } while (0)
#else
#define subtitle_mgr_err(x...)
#endif
/* Error Constants */
#define cERR_SUBTITLE_MGR_NO_ERROR 0
#define cERR_SUBTITLE_MGR_ERROR -1
static const char FILENAME[] = __FILE__;
/* ***************************** */
/* Types */
/* ***************************** */
/* ***************************** */
/* Varaibles */
/* ***************************** */
static Track_t * Tracks;
static int TrackCount = 0;
static int CurrentTrack = -1; //no as default.
/* ***************************** */
/* Prototypes */
/* ***************************** */
/* ***************************** */
/* Functions */
/* ***************************** */
static int ManagerAdd(Context_t *context, Track_t track) {
subtitle_mgr_printf(10, "%s::%s %s %s %d\n", FILENAME, __FUNCTION__, track.Name, track.Encoding, track.Id);
if (Tracks == NULL) {
Tracks = malloc(sizeof(Track_t) * TRACKWRAP);
}
if (Tracks == NULL)
{
subtitle_mgr_err("%s:%s malloc failed\n", FILENAME, __FUNCTION__);
return cERR_SUBTITLE_MGR_ERROR;
}
if (TrackCount < TRACKWRAP) {
copyTrack(&Tracks[TrackCount], &track);
TrackCount++;
} else {
subtitle_mgr_err("%s:%s TrackCount out if range %d - %d\n", FILENAME, __FUNCTION__, TrackCount, TRACKWRAP);
return cERR_SUBTITLE_MGR_ERROR;
}
if (TrackCount > 0)
context->playback->isSubtitle = 1;
subtitle_mgr_printf(10, "%s::%s\n", FILENAME, __FUNCTION__);
return cERR_SUBTITLE_MGR_NO_ERROR;
}
static char ** ManagerList(Context_t *context) {
char ** tracklist = NULL;
int i = 0, j = 0;
subtitle_mgr_printf(10, "%s::%s\n", FILENAME, __FUNCTION__);
if (Tracks != NULL) {
tracklist = malloc(sizeof(char *) * ((TrackCount*2) + 1));
if (tracklist == NULL)
{
subtitle_mgr_err("%s:%s malloc failed\n", FILENAME, __FUNCTION__);
return NULL;
}
for (i = 0, j = 0; i < TrackCount; i++, j+=2) {
tracklist[j] = strdup(Tracks[i].Name);
tracklist[j+1] = strdup(Tracks[i].Encoding);
}
tracklist[j] = NULL;
}
subtitle_mgr_printf(10, "%s::%s return %p (%d - %d)\n", FILENAME, __FUNCTION__, tracklist, j, TrackCount);
return tracklist;
}
static int ManagerDel(Context_t * context) {
int i = 0;
subtitle_mgr_printf(10, "%s::%s\n", FILENAME, __FUNCTION__);
if(Tracks != NULL) {
for (i = 0; i < TrackCount; i++) {
freeTrack(&Tracks[i]);
}
free(Tracks);
Tracks = NULL;
} else
{
subtitle_mgr_err("%s::%s nothing to delete!\n", FILENAME, __FUNCTION__);
return cERR_SUBTITLE_MGR_ERROR;
}
TrackCount = 0;
CurrentTrack = -1;
context->playback->isSubtitle = 0;
subtitle_mgr_printf(10, "%s::%s return no error\n", FILENAME, __FUNCTION__);
return cERR_SUBTITLE_MGR_NO_ERROR;
}
static int Command(void *_context, ManagerCmd_t command, void * argument) {
Context_t *context = (Context_t*) _context;
int ret = cERR_SUBTITLE_MGR_NO_ERROR;
subtitle_mgr_printf(50, "%s::%s %d\n", FILENAME, __FUNCTION__, command);
switch(command) {
case MANAGER_ADD: {
Track_t * track = argument;
ret = ManagerAdd(context, *track);
break;
}
case MANAGER_LIST: {
*((char***)argument) = (char **)ManagerList(context);
break;
}
case MANAGER_GET: {
if (TrackCount > 0 && CurrentTrack >= 0)
*((int*)argument) = (int)Tracks[CurrentTrack].Id;
else
*((int*)argument) = (int)-1;
break;
}
case MANAGER_GET_TRACK: {
subtitle_mgr_printf(20, "%s::%s MANAGER_GET_TRACK\n", FILENAME, __FUNCTION__);
if ((TrackCount > 0) && (CurrentTrack >=0))
{
subtitle_mgr_printf(120, "return %d, %p\n", CurrentTrack, &Tracks[CurrentTrack]);
*((Track_t**)argument) = (Track_t*) &Tracks[CurrentTrack];
}
else
{
subtitle_mgr_printf(20, "return NULL\n");
*((Track_t**)argument) = NULL;
}
break;
}
case MANAGER_GETENCODING: {
if (TrackCount > 0 && CurrentTrack >= 0)
*((char**)argument) = (char *)strdup(Tracks[CurrentTrack].Encoding);
else
*((char**)argument) = (char *)strdup("");
break;
}
case MANAGER_GETNAME: {
if (TrackCount > 0 && CurrentTrack >= 0)
*((char**)argument) = (char *)strdup(Tracks[CurrentTrack].Name);
else
*((char**)argument) = (char *)strdup("");
break;
}
case MANAGER_SET: {
int id = *((int*)argument);
subtitle_mgr_printf(20, "%s::%s MANAGER_SET id=%d\n", FILENAME, __FUNCTION__, id);
if (id < TrackCount)
CurrentTrack = id;
else
{
subtitle_mgr_err("%s::%s track id out of range (%d - %d)\n", FILENAME, __FUNCTION__, id, TrackCount);
ret = cERR_SUBTITLE_MGR_ERROR;
}
break;
}
case MANAGER_DEL: {
ret = ManagerDel(context);
break;
}
default:
subtitle_mgr_err("%s:%s: ConatinerCmd not supported!", FILENAME, __FUNCTION__);
ret = cERR_SUBTITLE_MGR_ERROR;
break;
}
subtitle_mgr_printf(50, "%s:%s: returning %d\n", FILENAME, __FUNCTION__,ret);
return ret;
}
struct Manager_s SubtitleManager = {
"Subtitle",
&Command,
NULL,
};

242
libeplayer3/manager/video.c Normal file
View File

@@ -0,0 +1,242 @@
/*
* video manager 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 <stdlib.h>
#include <string.h>
#include "manager.h"
#include "common.h"
/* ***************************** */
/* Makros/Constants */
/* ***************************** */
#define TRACKWRAP 4
#define VIDEO_MGR_DEBUG
#ifdef VIDEO_MGR_DEBUG
static short debug_level = 0;
#define video_mgr_printf(level, x...) do { \
if (debug_level >= level) printf(x); } while (0)
#else
#define video_mgr_printf(level, x...)
#endif
#ifndef VIDEO_MGR_SILENT
#define video_mgr_err(x...) do { printf(x); } while (0)
#else
#define video_mgr_err(x...)
#endif
/* Error Constants */
#define cERR_VIDEO_MGR_NO_ERROR 0
#define cERR_VIDEO_MGR_ERROR -1
static const char FILENAME[] = __FILE__;
/* ***************************** */
/* Types */
/* ***************************** */
/* ***************************** */
/* Varaibles */
/* ***************************** */
static Track_t * Tracks;
static int TrackCount = 0;
static int CurrentTrack = 0; //TRACK[0] as default.
/* ***************************** */
/* Prototypes */
/* ***************************** */
/* ***************************** */
/* Functions */
/* ***************************** */
static int ManagerAdd(Context_t *context, Track_t track) {
video_mgr_printf(10, "%s::%s\n", FILENAME, __FUNCTION__);
if (Tracks == NULL) {
Tracks = malloc(sizeof(Track_t) * TRACKWRAP);
}
if (Tracks == NULL)
{
video_mgr_err("%s:%s malloc failed\n", FILENAME, __FUNCTION__);
return cERR_VIDEO_MGR_ERROR;
}
if (TrackCount < TRACKWRAP) {
copyTrack(&Tracks[TrackCount], &track);
TrackCount++;
} else {
video_mgr_err("%s:%s TrackCount out if range %d - %d\n", FILENAME, __FUNCTION__, TrackCount, TRACKWRAP);
return cERR_VIDEO_MGR_ERROR;
}
if (TrackCount > 0)
context->playback->isVideo = 1;
video_mgr_printf(10, "%s::%s\n", FILENAME, __FUNCTION__);
return cERR_VIDEO_MGR_NO_ERROR;
}
static char ** ManagerList(Context_t *context) {
int i = 0, j = 0;
char ** tracklist = NULL;
video_mgr_printf(10, "%s::%s\n", FILENAME, __FUNCTION__);
if (Tracks != NULL) {
tracklist = malloc(sizeof(char *) * ((TrackCount*2) + 1));
if (tracklist == NULL)
{
video_mgr_err("%s:%s malloc failed\n", FILENAME, __FUNCTION__);
return NULL;
}
for (i = 0, j = 0; i < TrackCount; i++, j+=2) {
tracklist[j] = strdup(Tracks[i].Name);
tracklist[j+1] = strdup(Tracks[i].Encoding);
}
tracklist[j] = NULL;
}
video_mgr_printf(10, "%s::%s return %p (%d - %d)\n", FILENAME, __FUNCTION__, tracklist, j, TrackCount);
return tracklist;
}
static int ManagerDel(Context_t * context) {
int i = 0;
video_mgr_printf(10, "%s::%s\n", FILENAME, __FUNCTION__);
if(Tracks != NULL) {
for (i = 0; i < TrackCount; i++) {
freeTrack(&Tracks[i]);
}
free(Tracks);
Tracks = NULL;
} else
{
video_mgr_err("%s::%s nothing to delete!\n", FILENAME, __FUNCTION__);
return cERR_VIDEO_MGR_ERROR;
}
TrackCount = 0;
CurrentTrack = 0;
context->playback->isVideo = 0;
video_mgr_printf(10, "%s::%s return no error\n", FILENAME, __FUNCTION__);
return cERR_VIDEO_MGR_NO_ERROR;
}
static int Command(void *_context, ManagerCmd_t command, void * argument) {
Context_t *context = (Context_t*) _context;
int ret = cERR_VIDEO_MGR_NO_ERROR;
video_mgr_printf(10, "%s::%s\n", FILENAME, __FUNCTION__);
switch(command) {
case MANAGER_ADD: {
Track_t * track = argument;
ret = ManagerAdd(context, *track);
break;
}
case MANAGER_LIST: {
*((char***)argument) = (char **)ManagerList(context);
break;
}
case MANAGER_GET: {
if ((TrackCount > 0) && (CurrentTrack >=0))
*((int*)argument) = (int)Tracks[CurrentTrack].Id;
else
*((int*)argument) = (int)-1;
break;
}
case MANAGER_GET_TRACK: {
video_mgr_printf(20, "%s::%s MANAGER_GET_TRACK\n", FILENAME, __FUNCTION__);
if ((TrackCount > 0) && (CurrentTrack >=0))
*((Track_t**)argument) = (Track_t*) &Tracks[CurrentTrack];
else
*((Track_t**)argument) = NULL;
break;
}
case MANAGER_GETENCODING: {
if ((TrackCount > 0) && (CurrentTrack >=0))
*((char**)argument) = (char *)strdup(Tracks[CurrentTrack].Encoding);
else
*((char**)argument) = (char *)strdup("");
break;
}
case MANAGER_GETNAME: {
if ((TrackCount > 0) && (CurrentTrack >=0))
*((char**)argument) = (char *)strdup(Tracks[CurrentTrack].Name);
else
*((char**)argument) = (char *)strdup("");
break;
}
case MANAGER_SET: {
int id = (int) argument;
if (id < TrackCount)
CurrentTrack = id;
else
{
video_mgr_err("%s::%s track id out of range (%d - %d)\n", FILENAME, __FUNCTION__, id, TrackCount);
ret = cERR_VIDEO_MGR_ERROR;
}
break;
}
case MANAGER_DEL: {
ret = ManagerDel(context);
break;
}
default:
video_mgr_err("%s::%s ContainerCmd %d not supported!\n", FILENAME, __FUNCTION__, command);
ret = cERR_VIDEO_MGR_ERROR;
break;
}
video_mgr_printf(10, "%s:%s: returning %d\n", FILENAME, __FUNCTION__,ret);
return ret;
}
struct Manager_s VideoManager = {
"Video",
&Command,
NULL,
};

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

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,612 @@
/*
* eplayer3: command line playback using libeplayer3
*
* 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
*
*/
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <linux/fb.h>
#include <sys/ioctl.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <sys/mman.h>
#include "common.h"
#include "subtitle.h"
extern OutputHandler_t OutputHandler;
extern PlaybackHandler_t PlaybackHandler;
extern ContainerHandler_t ContainerHandler;
extern ManagerHandler_t ManagerHandler;
Context_t * player = NULL;
/* ******************************************** */
/* Framebuffer for subtitle */
/* ******************************************** */
static int fd = -1;
static unsigned char* lfb = NULL;
struct fb_fix_screeninfo fix;
struct fb_var_screeninfo screeninfo, oldscreen;
static int stride = 0;
static int xRes = 0;
static int yRes = 0;
static int bpp = 0;
int kbhit(void) {
struct timeval tv;
fd_set read_fd;
tv.tv_sec=1;
tv.tv_usec=0;
FD_ZERO(&read_fd);
FD_SET(0,&read_fd);
if(select(1, &read_fd, NULL, NULL, &tv) == -1)
return 0;
if(FD_ISSET(0,&read_fd))
return 1;
return 0;
}
void framebuffer_init()
{
int available = 0;
fd = open("/dev/fb0", O_RDWR);
if (fd < 0)
{
perror("/dev/fb0");
return;
}
if (ioctl(fd, FBIOGET_VSCREENINFO, &screeninfo) < 0)
{
perror("FBIOGET_VSCREENINFO");
return;
}
memcpy(&oldscreen, &screeninfo, sizeof(screeninfo));
ioctl(fd, FBIOGET_VSCREENINFO, &screeninfo);
printf("mode %d, %d, %d\n", screeninfo.xres, screeninfo.yres, screeninfo.bits_per_pixel);
if (ioctl(fd, FBIOGET_FSCREENINFO, &fix)<0)
{
perror("FBIOGET_FSCREENINFO");
printf("fb failed\n");
}
stride = fix.line_length;
xRes = screeninfo.xres;
yRes = screeninfo.yres;
bpp = screeninfo.bits_per_pixel;
printf("stride = %d, width %d\n", stride, xRes);
available = fix.smem_len;
printf("%dk video mem\n", available/1024);
lfb = (unsigned char*) mmap(0, available, PROT_WRITE|PROT_READ, MAP_SHARED, fd, 0);
if (lfb == NULL)
{
perror("mmap");
return;
}
memset(lfb, 0, available);
}
int main(int argc,char* argv[]) {
SubtitleOutputDef_t out;
int showInfos = 0, noinput = 0;
char file[255] = {""};
int speed = 0, speedmap = 0;
printf("%s >\n", __FILE__);
if (argc < 2)
{
printf("give me a filename please\n");
exit(1);
}
if (strstr(argv[1], "://") == NULL)
{
strcpy(file, "file://");
}
strcat(file, argv[1]);
/* debug helper */
if(argc == 3 && !strcmp(argv[2], "-d"))
{
showInfos = 1;
}
if(argc == 3 && !strcmp(argv[2], "-n"))
noinput = 1;
player = malloc(sizeof(Context_t));
player->playback = &PlaybackHandler;
player->output = &OutputHandler;
player->container = &ContainerHandler;
player->manager = &ManagerHandler;
printf("%s\n", player->output->Name);
//Registrating output devices
player->output->Command(player,OUTPUT_ADD, "audio");
player->output->Command(player,OUTPUT_ADD, "video");
player->output->Command(player,OUTPUT_ADD, "subtitle");
framebuffer_init();
/* for testing ass subtitles */
out.screen_width = xRes;
out.screen_height = yRes;
out.framebufferFD = fd;
out.destination = lfb;
out.destStride = stride;
out.shareFramebuffer = 1;
player->output->subtitle->Command(player, (OutputCmd_t)OUTPUT_SET_SUBTITLE_OUTPUT, (void*) &out);
if(player->playback->Command(player, PLAYBACK_OPEN, file) < 0)
return 10;
{
char ** TrackList = NULL;
player->manager->audio->Command(player, MANAGER_LIST, &TrackList);
if (TrackList != NULL) {
printf("AudioTrack List\n");
int i = 0;
for (i = 0; TrackList[i] != NULL; i+=2) {
printf("\t%s - %s\n", TrackList[i], TrackList[i+1]);
free(TrackList[i]);
free(TrackList[i+1]);
}
free(TrackList);
}
player->manager->video->Command(player, MANAGER_LIST, &TrackList);
if (TrackList != NULL) {
printf("VideoTrack List\n");
int i = 0;
for (i = 0; TrackList[i] != NULL; i+=2) {
printf("\t%s - %s\n", TrackList[i], TrackList[i+1]);
free(TrackList[i]);
free(TrackList[i+1]);
}
free(TrackList);
}
player->manager->subtitle->Command(player, MANAGER_LIST, &TrackList);
if (TrackList != NULL) {
printf("SubtitleTrack List\n");
int i = 0;
for (i = 0; TrackList[i] != NULL; i+=2) {
printf("\t%s - %s\n", TrackList[i], TrackList[i+1]);
free(TrackList[i]);
free(TrackList[i+1]);
}
free(TrackList);
}
}
{
int AudioTrackId = -1;
char * AudioTrackEncoding = NULL;
char * AudioTrackName = NULL;
player->manager->audio->Command(player, MANAGER_GET, &AudioTrackId);
player->manager->audio->Command(player, MANAGER_GETENCODING, &AudioTrackEncoding);
player->manager->audio->Command(player, MANAGER_GETNAME, &AudioTrackName);
printf("Current Audio Track : %d %s %s\n", AudioTrackId, AudioTrackEncoding, AudioTrackName);
free(AudioTrackEncoding);
free(AudioTrackName);
AudioTrackEncoding = NULL;
AudioTrackName = NULL;
player->manager->video->Command(player, MANAGER_GET, &AudioTrackId);
player->manager->video->Command(player, MANAGER_GETENCODING, &AudioTrackEncoding);
player->manager->video->Command(player, MANAGER_GETNAME, &AudioTrackName);
printf("Current Video Track : %d %s %s\n", AudioTrackId, AudioTrackEncoding, AudioTrackName);
free(AudioTrackEncoding);
free(AudioTrackName);
AudioTrackEncoding = NULL;
AudioTrackName = NULL;
player->manager->subtitle->Command(player, MANAGER_GET, &AudioTrackId);
player->manager->subtitle->Command(player, MANAGER_GETENCODING, &AudioTrackEncoding);
player->manager->subtitle->Command(player, MANAGER_GETNAME, &AudioTrackName);
printf("Current Subtitle Track : %d %s %s\n", AudioTrackId, AudioTrackEncoding, AudioTrackName);
free(AudioTrackEncoding);
free(AudioTrackName);
AudioTrackEncoding = NULL;
AudioTrackName = NULL;
/* player->manager->audio->Command(player, MANAGER_SET, 2);
player->manager->audio->Command(player, MANAGER_GET, &AudioTrackId);
player->manager->audio->Command(player, MANAGER_GETNAME, &AudioTrackName);
free(AudioTrackName);
AudioTrackName = NULL;*/
}
{
player->output->Command(player, OUTPUT_OPEN, NULL);
if (showInfos == 1)
{
char *tags[] =
{
"Title",
"Artist",
"Album",
"Year",
"Genre",
"Comment",
"Track",
"Copyright",
"TestLibEplayer",
NULL
};
int i = 0;
while (tags[i] != NULL)
{
char* tag = tags[i];
player->playback->Command(player, PLAYBACK_INFO, &tag);
#if !defined(VDR1722)
if (tag != NULL)
printf("\t%s:\t%s\n",tags[i], tag);
else
printf("\t%s:\tNULL\n",tags[i]);
#endif
i++;
}
player->output->Command(player, OUTPUT_CLOSE, NULL);
exit(1);
} else
player->playback->Command(player, PLAYBACK_PLAY, NULL);
/*{
int pid = 0;
player->playback->Command(player, PLAYBACK_SWITCH_SUBTITLE, (void*)&pid);
}*/
while(player->playback->isPlaying) {
int Key = 0;
if(kbhit())
if(noinput == 0)
Key = getchar();
if(!player->playback->isPlaying) {
break;
}
if(Key == 0)
continue;
switch (Key) {
case 'a': {
int Key2 = getchar();
switch (Key2) {
case 'l': {
char ** TrackList = NULL;
player->manager->audio->Command(player, MANAGER_LIST, &TrackList);
if (TrackList != NULL) {
printf("AudioTrack List\n");
int i = 0;
for (i = 0; TrackList[i] != NULL; i+=2) {
printf("\t%s - %s\n", TrackList[i], TrackList[i+1]);
free(TrackList[i]);
free(TrackList[i+1]);
}
free(TrackList);
}
break;
}
case 'c': {
int AudioTrackId = -1;
char * AudioTrackEncoding = NULL;
char * AudioTrackName = NULL;
player->manager->audio->Command(player, MANAGER_GET, &AudioTrackId);
player->manager->audio->Command(player, MANAGER_GETENCODING, &AudioTrackEncoding);
player->manager->audio->Command(player, MANAGER_GETNAME, &AudioTrackName);
printf("Current Audio Track : %d %s %s\n", AudioTrackId, AudioTrackEncoding, AudioTrackName);
free(AudioTrackEncoding);
free(AudioTrackName);
AudioTrackEncoding = NULL;
AudioTrackName = NULL;
break;
}
default: {
Key2 -= 0x30;
if(Key2 >= 0 && Key2 <= 9) {
player->playback->Command(player, PLAYBACK_SWITCH_AUDIO, (void*)&Key2);
}
}
}
break;
}
case 's': {
int Key2 = getchar();
switch (Key2) {
case 'l': {
char ** TrackList = NULL;
player->manager->subtitle->Command(player, MANAGER_LIST, &TrackList);
if (TrackList != NULL) {
printf("SubtitleTrack List\n");
int i = 0;
for (i = 0; TrackList[i] != NULL; i+=2) {
printf("\t%s - %s\n", TrackList[i], TrackList[i+1]);
free(TrackList[i]);
free(TrackList[i+1]);
}
free(TrackList);
}
break;
}
case 'c': {
int SubtitleTrackId = -1;
char * SubtitleTrackEncoding = NULL;
char * SubtitleTrackName = NULL;
player->manager->subtitle->Command(player, MANAGER_GET, &SubtitleTrackId);
player->manager->subtitle->Command(player, MANAGER_GETENCODING, &SubtitleTrackEncoding);
player->manager->subtitle->Command(player, MANAGER_GETNAME, &SubtitleTrackName);
printf("Current Subtitle Track : %d %s %s\n", SubtitleTrackId, SubtitleTrackEncoding, SubtitleTrackName);
free(SubtitleTrackEncoding);
free(SubtitleTrackName);
SubtitleTrackEncoding = NULL;
SubtitleTrackName = NULL;
break;
}
default: {
Key2 -= 0x30;
if(Key2 >= 0 && Key2 <= 9) {
player->playback->Command(player, PLAYBACK_SWITCH_SUBTITLE, (void*)&Key2);
}
}
}
break;
}
case 'q':
player->playback->Command(player, PLAYBACK_STOP, NULL);
break;
case 'c':
player->playback->Command(player, PLAYBACK_CONTINUE, NULL);
break;
case 'p':
player->playback->Command(player, PLAYBACK_PAUSE, NULL);
break;
case 'f': {
if (speed < 0)
speed = 0;
speed++;
if (speed > 7)
speed = 1;
switch(speed)
{
case 1: speedmap = 1; break;
case 2: speedmap = 3; break;
case 3: speedmap = 7; break;
case 4: speedmap = 15; break;
case 5: speedmap = 31; break;
case 6: speedmap = 63; break;
case 7: speedmap = 127; break;
}
player->playback->Command(player, PLAYBACK_FASTFORWARD, &speedmap);
break;
}
case 'b': {
if (speed > 0)
speed = 0;
speed--;
if (speed < -7)
speed = -1;
switch(speed)
{
case -1: speedmap = -5; break;
case -2: speedmap = -10; break;
case -3: speedmap = -20; break;
case -4: speedmap = -40; break;
case -5: speedmap = -80; break;
case -6: speedmap = -160; break;
case -7: speedmap = -320; break;
}
player->playback->Command(player, PLAYBACK_FASTBACKWARD, &speedmap);
break;
}
#if defined(VDR1722)
case 'g': {
char gotoString [256];
gets (gotoString);
int gotoPos = atoi(gotoString);
double length = 0;
float sec;
printf("gotoPos %i\n", gotoPos);
if (player->container && player->container->selectedContainer)
player->container->selectedContainer->Command(player, CONTAINER_LENGTH, &length);
if(gotoPos <= 0){
printf("kleiner als erlaubt\n");
sec = 0.0;
}else if(gotoPos >= ((int)length - 10)){
printf("laenger als erlaubt\n");
sec = (int)length - 10;
}else{
printf("normal action\n");
sec = gotoPos;
}
player->playback->Command(player, PLAYBACK_SEEK, (void*)&sec);
printf("goto postion (%i sec)\n", sec);
break;
}
#endif
case 'k': {
#if !defined(VDR1722)
int Key2 = getchar() - 48;
float sec=0.0;
printf("seconds %d \n", Key2);
switch (Key2) {
case 1: sec=-15.0;break;
case 4: sec=-60.0;break;
case 7: sec=-300.0;break;
case 3: sec= 15.0;break;
case 6: sec= 60.0;break;
case 9: sec= 300.0;break;
}
#else
char seek [256];
gets (seek);
unsigned int seekTo = atoi(seek);
double length = 0;
float sec;
unsigned long long int CurrentPTS = 0;
player->playback->Command(player, PLAYBACK_PTS, &CurrentPTS);
if (player->container && player->container->selectedContainer)
player->container->selectedContainer->Command(player, CONTAINER_LENGTH, &length);
int CurrentSec = CurrentPTS / 90000;
printf("CurrentSec = %i, seekTo = %i, abs(seekTo) = %i seekTo + CurrentSec %i\n", CurrentSec, seekTo, abs(seekTo), (seekTo + CurrentSec));
int ergSec = CurrentSec + seekTo;
if(ergSec < 0){
printf("kleiner als erlaubt\n");
sec = 0.0;
}else if((CurrentSec + seekTo) >= ((int)length - 10)){
printf("laenger als erlaubt\n");
sec = (int)length - 10;
}else{
printf("normal action\n");
sec = seekTo + CurrentSec;
}
printf("springe %i \n", (int)sec);
#endif
player->playback->Command(player, PLAYBACK_SEEK, (void*)&sec);
break;
}
case 'l': {
double length = 0;
if (player->container && player->container->selectedContainer)
player->container->selectedContainer->Command(player, CONTAINER_LENGTH, &length);
printf("Length = %02d:%02d:%02d (%.4f sec)\n", (int)((length/60)/60)%60, (int)(length/60)%60, (int)length%60, length);
break;
}
case 'j': {
unsigned long long int pts = 0;
player->playback->Command(player, PLAYBACK_PTS, &pts);
unsigned long long int sec = pts / 90000;
printf("Pts = %02d:%02d:%02d (%llu.0000 sec)\n", (int)((sec/60)/60)%60, (int)(sec/60)%60, (int)sec%60, sec);
break;
}
case 'i':
{
char *tags[] =
{
"Title",
"Artist",
"Album",
"Year",
"Genre",
"Comment",
"Track",
"Copyright",
"TestLibEplayer",
NULL
};
int i = 0;
while (tags[i] != NULL)
{
char* tag = tags[i];
player->playback->Command(player, PLAYBACK_INFO, &tag);
if (tag != NULL)
printf("\t%s:\t%s\n",tags[i], tag);
else
printf("\t%s:\tNULL\n",tags[i]);
i++;
}
break;
}
default: {
printf("Control:\n");
printf("al: List audio tracks\n");
printf("ac: List current audio track\n");
printf("a[id] Select audio track\n");
printf("sl: List subtitles\n");
printf("sc: List current subtitle\n");
printf("s[id] Select subtitles\n");
printf("q: Stop\n");
printf("c: Continue\n");
printf("p: Pause\n");
printf("f: Increase speed (Fast forward) (stepwise)\n");
printf("b: Decrease speed (Fast reverse) (stepwise)\n");
printf("l: Print duration\n");
printf("j: Print current PTS\n");
printf("k[1,4,7]: Jump back [15,60,300] seconds\n");
printf("k[3,6,9]: Jump forward [15,60,300] seconds\n");
printf("i: Print Info\n");
break;
}
}
}
player->output->Command(player, OUTPUT_CLOSE, NULL);
}
//printOutputCapabilities();
exit(0);
}

79
libeplayer3/tools/meta.c Normal file
View File

@@ -0,0 +1,79 @@
/* konfetti
* gpl
* 2010
*
* example utitility to show metatags with ffmpeg.
*/
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <libavutil/avutil.h>
#include <libavformat/avformat.h>
static AVFormatContext* avContext = NULL;
void dump_metadata()
{
AVMetadataTag *tag = NULL;
while ((tag = av_metadata_get(avContext->metadata, "", tag, AV_METADATA_IGNORE_SUFFIX)))
printf("%s: %s\n", tag->key, tag->value);
}
int main(int argc,char* argv[])
{
char file[255] = {""};
int err, i;
if (argc < 2)
{
printf("give me a filename please\n");
return -1;
}
if (strstr(argv[1], "://") == NULL)
{
strcpy(file, "file://");
}
strcat(file, argv[1]);
av_register_all();
if ((err = av_open_input_file(&avContext, file, NULL, 0, NULL)) != 0) {
char error[512];
printf("av_open_input_file failed %d (%s)\n", err, file);
av_strerror(err, error, 512);
printf("Cause: %s\n", error);
return -1;
}
if (av_find_stream_info(avContext) < 0)
{
printf("Error av_find_stream_info\n");
}
printf("\n***\n");
dump_metadata();
printf("\nstream specific metadata:\n");
for (i = 0; i < avContext->nb_streams; i++)
{
AVStream* stream = avContext->streams[i];
if (stream)
{
AVMetadataTag *tag = NULL;
if (stream->metadata != NULL)
while ((tag = av_metadata_get(stream->metadata, "", tag, AV_METADATA_IGNORE_SUFFIX)))
printf("%s: %s\n", tag->key, tag->value);
}
}
return 0;
}