mirror of
https://github.com/tuxbox-neutrino/libstb-hal.git
synced 2025-08-26 23:13:16 +02:00
lib cleanup and sync for mips vu support
This commit is contained in:
458
libeplayer3/output/linuxdvb_buffering.c
Normal file
458
libeplayer3/output/linuxdvb_buffering.c
Normal file
@@ -0,0 +1,458 @@
|
||||
/*
|
||||
* RAM write buffering utilities
|
||||
* samsamsam 2018
|
||||
*
|
||||
*
|
||||
* 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 <unistd.h>
|
||||
#include <fcntl.h>
|
||||
#include <memory.h>
|
||||
#include <string.h>
|
||||
#include <errno.h>
|
||||
#include <pthread.h>
|
||||
#include <stdint.h>
|
||||
#include <stdbool.h>
|
||||
#include <assert.h>
|
||||
#include <time.h>
|
||||
|
||||
#include "common.h"
|
||||
#include "debug.h"
|
||||
#include "misc.h"
|
||||
#include "writer.h"
|
||||
|
||||
/* ***************************** */
|
||||
/* Types */
|
||||
/* ***************************** */
|
||||
typedef enum OutputType_e
|
||||
{
|
||||
OUTPUT_UNK,
|
||||
OUTPUT_AUDIO,
|
||||
OUTPUT_VIDEO,
|
||||
} OutputType_t;
|
||||
|
||||
typedef struct BufferingNode_s
|
||||
{
|
||||
uint32_t dataSize;
|
||||
OutputType_t dataType;
|
||||
struct BufferingNode_s *next;
|
||||
} BufferingNode_t;
|
||||
|
||||
/* ***************************** */
|
||||
/* Makros/Constants */
|
||||
/* ***************************** */
|
||||
#define cERR_LINUX_DVB_BUFFERING_NO_ERROR 0
|
||||
#define cERR_LINUX_DVB_BUFFERING_ERROR -1
|
||||
|
||||
/* ***************************** */
|
||||
/* Variables */
|
||||
/* ***************************** */
|
||||
|
||||
static pthread_t bufferingThread;
|
||||
static pthread_mutex_t bufferingMtx;
|
||||
static pthread_cond_t bufferingExitCond;
|
||||
static pthread_cond_t bufferingDataConsumedCond;
|
||||
static pthread_cond_t bufferingdDataAddedCond;
|
||||
static bool hasBufferingThreadStarted = false;
|
||||
static BufferingNode_t *bufferingQueueHead = NULL;
|
||||
static BufferingNode_t *bufferingQueueTail = NULL;
|
||||
|
||||
static uint32_t maxBufferingDataSize = 0;
|
||||
static uint32_t bufferingDataSize = 0;
|
||||
|
||||
static int videofd = -1;
|
||||
static int audiofd = -1;
|
||||
static int g_pfd[2] = {-1, -1};
|
||||
|
||||
static pthread_mutex_t *g_pDVBMtx = NULL;
|
||||
|
||||
/* ***************************** */
|
||||
/* Prototypes */
|
||||
/* ***************************** */
|
||||
|
||||
/* ***************************** */
|
||||
/* MISC Functions */
|
||||
/* ***************************** */
|
||||
|
||||
static void WriteWakeUp()
|
||||
{
|
||||
int ret = write(g_pfd[1], "x", 1);
|
||||
if (ret != 1)
|
||||
{
|
||||
buff_printf(20, "WriteWakeUp write return %d\n", ret);
|
||||
}
|
||||
}
|
||||
|
||||
/* ***************************** */
|
||||
/* Worker Thread */
|
||||
/* ***************************** */
|
||||
|
||||
static void LinuxDvbBuffThread(Context_t *context)
|
||||
{
|
||||
int flags = 0;
|
||||
static BufferingNode_t *nodePtr = NULL;
|
||||
buff_printf(20, "ENTER\n");
|
||||
|
||||
if (pipe(g_pfd) == -1)
|
||||
{
|
||||
buff_err("critical error\n");
|
||||
}
|
||||
|
||||
/* Make read and write ends of pipe nonblocking */
|
||||
if ((flags = fcntl(g_pfd[0], F_GETFL)) == -1)
|
||||
{
|
||||
buff_err("critical error\n");
|
||||
}
|
||||
|
||||
/* Make read end nonblocking */
|
||||
flags |= O_NONBLOCK;
|
||||
if (fcntl(g_pfd[0], F_SETFL, flags) == -1)
|
||||
{
|
||||
buff_err("critical error\n");
|
||||
}
|
||||
|
||||
if ((flags = fcntl(g_pfd[1], F_GETFL)) == -1)
|
||||
{
|
||||
buff_err("critical error\n");
|
||||
}
|
||||
|
||||
/* Make write end nonblocking */
|
||||
flags |= O_NONBLOCK;
|
||||
if (fcntl(g_pfd[1], F_SETFL, flags) == -1)
|
||||
{
|
||||
buff_err("critical error\n");
|
||||
}
|
||||
|
||||
PlaybackDieNowRegisterCallback(WriteWakeUp);
|
||||
|
||||
while (0 == PlaybackDieNow(0))
|
||||
{
|
||||
pthread_mutex_lock(&bufferingMtx);
|
||||
if (nodePtr)
|
||||
{
|
||||
free(nodePtr);
|
||||
nodePtr = NULL;
|
||||
/* signal that we free some space in queue */
|
||||
pthread_cond_signal(&bufferingDataConsumedCond);
|
||||
}
|
||||
|
||||
if (!bufferingQueueHead)
|
||||
{
|
||||
assert(bufferingQueueTail == NULL);
|
||||
|
||||
/* Queue is empty we need to wait for data to be added */
|
||||
pthread_cond_wait(&bufferingdDataAddedCond, &bufferingMtx);
|
||||
pthread_mutex_unlock(&bufferingMtx);
|
||||
continue; /* To check PlaybackDieNow(0) */
|
||||
}
|
||||
else
|
||||
{
|
||||
nodePtr = bufferingQueueHead;
|
||||
bufferingQueueHead = bufferingQueueHead->next;
|
||||
if (bufferingQueueHead == NULL)
|
||||
{
|
||||
bufferingQueueTail = NULL;
|
||||
}
|
||||
|
||||
if (bufferingDataSize >= (nodePtr->dataSize + sizeof(BufferingNode_t)))
|
||||
{
|
||||
bufferingDataSize -= (nodePtr->dataSize + sizeof(BufferingNode_t));
|
||||
}
|
||||
else
|
||||
{
|
||||
assert(bufferingDataSize == 0);
|
||||
bufferingDataSize = 0;
|
||||
}
|
||||
}
|
||||
pthread_mutex_unlock(&bufferingMtx);
|
||||
|
||||
/* We will write data without mutex
|
||||
* this have some disadvantage because we can
|
||||
* write some portion of data after LinuxDvbBuffFlush,
|
||||
* for example after seek, this will be fixed later
|
||||
*/
|
||||
if (nodePtr && !context->playback->isSeeking)
|
||||
{
|
||||
/* Write data to valid output */
|
||||
uint8_t *dataPtr = (uint8_t *)nodePtr + sizeof(BufferingNode_t);
|
||||
int fd = nodePtr->dataType == OUTPUT_VIDEO ? videofd : audiofd;
|
||||
if (0 != WriteWithRetry(context, g_pfd[0], fd, g_pDVBMtx, dataPtr, nodePtr->dataSize))
|
||||
{
|
||||
buff_err("Something is WRONG\n");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pthread_mutex_lock(&bufferingMtx);
|
||||
pthread_cond_signal(&bufferingExitCond);
|
||||
pthread_mutex_unlock(&bufferingMtx);
|
||||
|
||||
buff_printf(20, "EXIT\n");
|
||||
hasBufferingThreadStarted = false;
|
||||
|
||||
close(g_pfd[0]);
|
||||
close(g_pfd[1]);
|
||||
g_pfd[0] = -1;
|
||||
g_pfd[1] = -1;
|
||||
}
|
||||
|
||||
int32_t LinuxDvbBuffSetSize(const uint32_t bufferSize)
|
||||
{
|
||||
maxBufferingDataSize = bufferSize;
|
||||
return cERR_LINUX_DVB_BUFFERING_NO_ERROR;
|
||||
}
|
||||
|
||||
uint32_t LinuxDvbBuffGetSize()
|
||||
{
|
||||
return maxBufferingDataSize;
|
||||
}
|
||||
|
||||
int32_t LinuxDvbBuffOpen(Context_t *context, char *type, int outfd, void *mtx)
|
||||
{
|
||||
int32_t error = 0;
|
||||
int32_t ret = cERR_LINUX_DVB_BUFFERING_NO_ERROR;
|
||||
|
||||
buff_printf(10, "\n");
|
||||
|
||||
if (!hasBufferingThreadStarted)
|
||||
{
|
||||
pthread_attr_t attr;
|
||||
pthread_attr_init(&attr);
|
||||
pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
|
||||
|
||||
g_pDVBMtx = mtx;
|
||||
|
||||
if ((error = pthread_create(&bufferingThread, &attr, (void *)&LinuxDvbBuffThread, context)) != 0)
|
||||
{
|
||||
buff_printf(10, "Creating thread, error:%d:%s\n", error, strerror(error));
|
||||
|
||||
hasBufferingThreadStarted = false;
|
||||
ret = cERR_LINUX_DVB_BUFFERING_ERROR;
|
||||
}
|
||||
else
|
||||
{
|
||||
buff_printf(10, "Created thread\n");
|
||||
hasBufferingThreadStarted = true;
|
||||
|
||||
/* init synchronization prymitives */
|
||||
pthread_mutex_init(&bufferingMtx, NULL);
|
||||
|
||||
pthread_cond_init(&bufferingExitCond, NULL);
|
||||
pthread_cond_init(&bufferingDataConsumedCond, NULL);
|
||||
pthread_cond_init(&bufferingdDataAddedCond, NULL);
|
||||
}
|
||||
}
|
||||
|
||||
if (!ret)
|
||||
{
|
||||
if (!strcmp("video", type) && -1 == videofd)
|
||||
{
|
||||
videofd = outfd;
|
||||
}
|
||||
else if (!strcmp("audio", type) && -1 == audiofd)
|
||||
{
|
||||
audiofd = outfd;
|
||||
}
|
||||
else
|
||||
{
|
||||
ret = cERR_LINUX_DVB_BUFFERING_ERROR;
|
||||
}
|
||||
}
|
||||
|
||||
buff_printf(10, "exiting with value %d\n", ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
int32_t LinuxDvbBuffClose(Context_t *context __attribute__((unused)))
|
||||
{
|
||||
int32_t ret = 0;
|
||||
|
||||
buff_printf(10, "\n");
|
||||
videofd = -1;
|
||||
audiofd = -1;
|
||||
|
||||
if (hasBufferingThreadStarted)
|
||||
{
|
||||
struct timespec max_wait = {0, 0};
|
||||
|
||||
/* WakeUp if we are waiting in the write */
|
||||
WriteWakeUp();
|
||||
|
||||
pthread_mutex_lock(&bufferingMtx);
|
||||
/* wake up if thread is waiting for data */
|
||||
pthread_cond_signal(&bufferingdDataAddedCond);
|
||||
|
||||
/* wait for thread end */
|
||||
#if 0
|
||||
/* This code couse symbol versioning of clock_gettime@GLIBC_2.17 */
|
||||
clock_gettime(CLOCK_REALTIME, &max_wait);
|
||||
max_wait.tv_sec += 1;
|
||||
#else
|
||||
max_wait.tv_sec = time(NULL) + 2;
|
||||
#endif
|
||||
pthread_cond_timedwait(&bufferingExitCond, &bufferingMtx, &max_wait);
|
||||
pthread_mutex_unlock(&bufferingMtx);
|
||||
|
||||
if (!hasBufferingThreadStarted)
|
||||
{
|
||||
/* destroy synchronization prymitives?
|
||||
* for a moment, we'll exit linux process,
|
||||
* so the system will do this for us
|
||||
*/
|
||||
/*
|
||||
pthread_mutex_destroy(&bufferingMtx);
|
||||
pthread_cond_destroy(&bufferingDataConsumedCond);
|
||||
pthread_cond_destroy(&bufferingdDataAddedCond);
|
||||
*/
|
||||
}
|
||||
}
|
||||
|
||||
ret = hasBufferingThreadStarted ? cERR_LINUX_DVB_BUFFERING_ERROR : cERR_LINUX_DVB_BUFFERING_NO_ERROR;
|
||||
|
||||
buff_printf(10, "exiting with value %d\n", ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
int32_t LinuxDvbBuffFlush(Context_t *context __attribute__((unused)))
|
||||
{
|
||||
static BufferingNode_t *nodePtr = NULL;
|
||||
buff_printf(40, "ENTER bufferingQueueHead[%p]\n", bufferingQueueHead);
|
||||
|
||||
/* signal if we are waiting for write to DVB decoders */
|
||||
WriteWakeUp();
|
||||
|
||||
pthread_mutex_lock(&bufferingMtx);
|
||||
while (bufferingQueueHead)
|
||||
{
|
||||
nodePtr = bufferingQueueHead;
|
||||
bufferingQueueHead = nodePtr->next;
|
||||
bufferingDataSize -= (nodePtr->dataSize + sizeof(BufferingNode_t));
|
||||
free(nodePtr);
|
||||
}
|
||||
bufferingQueueHead = NULL;
|
||||
bufferingQueueTail = NULL;
|
||||
buff_printf(40, "bufferingDataSize [%u]\n", bufferingDataSize);
|
||||
assert(bufferingDataSize == 0);
|
||||
bufferingDataSize = 0;
|
||||
|
||||
/* signal that queue is empty */
|
||||
pthread_cond_signal(&bufferingDataConsumedCond);
|
||||
pthread_mutex_unlock(&bufferingMtx);
|
||||
buff_printf(40, "EXIT\n");
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int32_t LinuxDvbBuffResume(Context_t *context __attribute__((unused)))
|
||||
{
|
||||
/* signal if we are waiting for write to DVB decoders
|
||||
*
|
||||
*/
|
||||
WriteWakeUp();
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
ssize_t BufferingWriteV(int fd, const struct iovec *iov, int ic)
|
||||
{
|
||||
OutputType_t dataType = OUTPUT_UNK;
|
||||
BufferingNode_t *nodePtr = NULL;
|
||||
uint8_t *dataPtr = NULL;
|
||||
uint32_t chunkSize = 0;
|
||||
int i = 0;
|
||||
|
||||
buff_printf(60, "ENTER\n");
|
||||
if (fd == videofd)
|
||||
{
|
||||
buff_printf(60, "VIDEO\n");
|
||||
dataType = OUTPUT_VIDEO;
|
||||
}
|
||||
else if (fd == audiofd)
|
||||
{
|
||||
buff_printf(60, "AUDIO\n");
|
||||
dataType = OUTPUT_AUDIO;
|
||||
}
|
||||
else
|
||||
{
|
||||
buff_err("Unknown output type\n");
|
||||
return cERR_LINUX_DVB_BUFFERING_ERROR;
|
||||
}
|
||||
|
||||
for (i = 0; i < ic; ++i)
|
||||
{
|
||||
chunkSize += iov[i].iov_len;
|
||||
}
|
||||
chunkSize += sizeof(BufferingNode_t);
|
||||
|
||||
/* Allocate memory for queue node + data */
|
||||
nodePtr = malloc(chunkSize);
|
||||
if (!nodePtr)
|
||||
{
|
||||
buff_err("OUT OF MEM\n");
|
||||
return cERR_LINUX_DVB_BUFFERING_ERROR;
|
||||
}
|
||||
|
||||
/* Copy data to new buffer */
|
||||
dataPtr = (uint8_t *)nodePtr + sizeof(BufferingNode_t);
|
||||
for (i = 0; i < ic; ++i)
|
||||
{
|
||||
memcpy(dataPtr, iov[i].iov_base, iov[i].iov_len);
|
||||
dataPtr += iov[i].iov_len;
|
||||
}
|
||||
|
||||
pthread_mutex_lock(&bufferingMtx);
|
||||
while (0 == PlaybackDieNow(0))
|
||||
{
|
||||
if (bufferingDataSize + chunkSize >= maxBufferingDataSize)
|
||||
{
|
||||
/* Buffering queue is full we need wait for space*/
|
||||
pthread_cond_wait(&bufferingDataConsumedCond, &bufferingMtx);
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Add chunk to buffering queue */
|
||||
if (bufferingQueueHead == NULL)
|
||||
{
|
||||
bufferingQueueHead = nodePtr;
|
||||
bufferingQueueTail = nodePtr;
|
||||
}
|
||||
else
|
||||
{
|
||||
bufferingQueueTail->next = nodePtr;
|
||||
bufferingQueueTail = nodePtr;
|
||||
}
|
||||
|
||||
bufferingDataSize += chunkSize;
|
||||
chunkSize -= sizeof(BufferingNode_t);
|
||||
nodePtr->dataSize = chunkSize;
|
||||
nodePtr->dataType = dataType;
|
||||
nodePtr->next = NULL;
|
||||
|
||||
/* signal that we added some data to queue */
|
||||
pthread_cond_signal(&bufferingdDataAddedCond);
|
||||
break;
|
||||
}
|
||||
}
|
||||
pthread_mutex_unlock(&bufferingMtx);
|
||||
buff_printf(60, "EXIT\n");
|
||||
return chunkSize;
|
||||
}
|
529
libeplayer3/output/linuxdvb_fake.c
Normal file
529
libeplayer3/output/linuxdvb_fake.c
Normal file
@@ -0,0 +1,529 @@
|
||||
/*
|
||||
* 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 <inttypes.h>
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
#include <unistd.h>
|
||||
#include <stdbool.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 <poll.h>
|
||||
|
||||
#include "common.h"
|
||||
#include "debug.h"
|
||||
#include "output.h"
|
||||
#include "writer.h"
|
||||
#include "misc.h"
|
||||
#include "pes.h"
|
||||
|
||||
/* ***************************** */
|
||||
/* Makros/Constants */
|
||||
/* ***************************** */
|
||||
|
||||
#define cERR_LINUXDVB_NO_ERROR 0
|
||||
#define cERR_LINUXDVB_ERROR -1
|
||||
|
||||
static const char VIDEODEV[] = "/tmp/e2i_video0";
|
||||
static const char AUDIODEV[] = "/tmp/e2i_audio0";
|
||||
|
||||
static int videofd = -1;
|
||||
static int audiofd = -1;
|
||||
|
||||
struct DVBApiVideoInfo_s
|
||||
{
|
||||
int aspect_ratio;
|
||||
int progressive;
|
||||
int frame_rate;
|
||||
int width, height;
|
||||
};
|
||||
static struct DVBApiVideoInfo_s videoInfo = {-1, -1, -1, -1, -1};
|
||||
|
||||
unsigned long long int sCURRENT_PTS = 0;
|
||||
bool isBufferedOutput = false;
|
||||
|
||||
pthread_mutex_t LinuxDVBmutex;
|
||||
|
||||
/* ***************************** */
|
||||
/* Prototypes */
|
||||
/* ***************************** */
|
||||
int32_t LinuxDvbBuffOpen(Context_t *context, char *type, int outfd);
|
||||
int32_t LinuxDvbBuffClose(Context_t *context);
|
||||
int32_t LinuxDvbBuffFlush(Context_t *context);
|
||||
int32_t LinuxDvbBuffResume(Context_t *context);
|
||||
|
||||
ssize_t BufferingWriteV(int fd, const struct iovec *iov, int ic);
|
||||
int32_t LinuxDvbBuffSetSize(const uint32_t bufferSize);
|
||||
uint32_t LinuxDvbBuffGetSize();
|
||||
|
||||
int LinuxDvbStop(Context_t *context, char *type);
|
||||
|
||||
/* ***************************** */
|
||||
/* MISC Functions */
|
||||
/* ***************************** */
|
||||
|
||||
#define getLinuxDVBMutex() pthread_mutex_lock(&LinuxDVBmutex)
|
||||
#define releaseLinuxDVBMutex() pthread_mutex_unlock(&LinuxDVBmutex)
|
||||
|
||||
|
||||
int LinuxDvbOpen(Context_t *context __attribute__((unused)), char *type)
|
||||
{
|
||||
uint8_t video = !strcmp("video", type);
|
||||
uint8_t audio = !strcmp("audio", type);
|
||||
|
||||
linuxdvb_printf(10, "v%d a%d\n", video, audio);
|
||||
|
||||
if (video && videofd < 0)
|
||||
{
|
||||
videofd = open(VIDEODEV, O_CREAT | O_TRUNC | O_WRONLY | S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH, 0666);
|
||||
}
|
||||
|
||||
if (audio && audiofd < 0)
|
||||
{
|
||||
audiofd = open(AUDIODEV, O_CREAT | O_TRUNC | O_WRONLY | S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH, 0666);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int LinuxDvbClose(Context_t *context __attribute__((unused)), char *type __attribute__((unused)))
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
int LinuxDvbPlay(Context_t *context __attribute__((unused)), char *type __attribute__((unused)))
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
int LinuxDvbStop(Context_t *context __attribute__((unused)), char *type __attribute__((unused)))
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
int LinuxDvbPause(Context_t *context __attribute__((unused)), char *type __attribute__((unused)))
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
int LinuxDvbContinue(Context_t *context __attribute__((unused)), char *type)
|
||||
{
|
||||
int32_t ret = cERR_LINUXDVB_NO_ERROR;
|
||||
uint8_t video = !strcmp("video", type);
|
||||
uint8_t audio = !strcmp("audio", type);
|
||||
|
||||
linuxdvb_printf(10, "v%d a%d\n", video, audio);
|
||||
|
||||
if (video && videofd != -1)
|
||||
{
|
||||
if (ioctl(videofd, VIDEO_CONTINUE, NULL) == -1)
|
||||
{
|
||||
linuxdvb_err("VIDEO_CONTINUE: ERROR %d, %s\n", errno, strerror(errno));
|
||||
ret = cERR_LINUXDVB_ERROR;
|
||||
}
|
||||
}
|
||||
|
||||
if (audio && audiofd != -1)
|
||||
{
|
||||
if (ioctl(audiofd, AUDIO_CONTINUE, NULL) == -1)
|
||||
{
|
||||
linuxdvb_err("AUDIO_CONTINUE: ERROR %d, %s\n", errno, strerror(errno));
|
||||
ret = cERR_LINUXDVB_ERROR;
|
||||
}
|
||||
}
|
||||
|
||||
if (isBufferedOutput)
|
||||
LinuxDvbBuffResume(context);
|
||||
|
||||
linuxdvb_printf(10, "exiting\n");
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
int LinuxDvbAudioMute(Context_t *context __attribute__((unused)), char *flag __attribute__((unused)))
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
int LinuxDvbFlush(Context_t *context __attribute__((unused)), char *type __attribute__((unused)))
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
int LinuxDvbSlowMotion(Context_t *context __attribute__((unused)), char *type __attribute__((unused)))
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
int LinuxDvbAVSync(Context_t *context __attribute__((unused)), char *type __attribute__((unused)))
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
int LinuxDvbClear(Context_t *context __attribute__((unused)), char *type __attribute__((unused)))
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
int LinuxDvbPts(Context_t *context __attribute__((unused)), unsigned long long int *pts)
|
||||
{
|
||||
*((unsigned long long int *)pts) = (unsigned long long int)0;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int LinuxDvbGetFrameCount(Context_t *context __attribute__((unused)), unsigned long long int *frameCount __attribute__((unused)))
|
||||
{
|
||||
return cERR_LINUXDVB_NO_ERROR;
|
||||
}
|
||||
|
||||
int LinuxDvbSwitch(Context_t *context __attribute__((unused)), char *type __attribute__((unused)))
|
||||
{
|
||||
|
||||
return cERR_LINUXDVB_NO_ERROR;
|
||||
}
|
||||
|
||||
static int Write(Context_t *context, void *_out)
|
||||
{
|
||||
AudioVideoOut_t *out = (AudioVideoOut_t *) _out;
|
||||
int32_t ret = cERR_LINUXDVB_NO_ERROR;
|
||||
int32_t res = 0;
|
||||
uint8_t video = 0;
|
||||
uint8_t audio = 0;
|
||||
Writer_t *writer = NULL;
|
||||
WriterAVCallData_t call;
|
||||
|
||||
if (out == NULL)
|
||||
{
|
||||
linuxdvb_err("null pointer passed\n");
|
||||
return cERR_LINUXDVB_ERROR;
|
||||
}
|
||||
|
||||
video = !strcmp("video", out->type);
|
||||
audio = !strcmp("audio", out->type);
|
||||
|
||||
linuxdvb_printf(20, "DataLength=%u PrivateLength=%u Pts=%"PRIu64" FrameRate=%d\n",
|
||||
out->len, out->extralen, out->pts, out->frameRate);
|
||||
linuxdvb_printf(20, "v%d a%d\n", video, audio);
|
||||
|
||||
if (video)
|
||||
{
|
||||
char *Encoding = NULL;
|
||||
context->manager->video->Command(context, MANAGER_GETENCODING, &Encoding);
|
||||
|
||||
linuxdvb_printf(20, "Encoding = %s\n", Encoding);
|
||||
|
||||
writer = getWriter(Encoding);
|
||||
|
||||
if (writer == NULL)
|
||||
{
|
||||
linuxdvb_printf(20, "searching default writer ... %s\n", Encoding);
|
||||
writer = getDefaultVideoWriter();
|
||||
}
|
||||
|
||||
if (writer == NULL)
|
||||
{
|
||||
linuxdvb_err("unknown video codec and no default writer %s\n", Encoding);
|
||||
ret = cERR_LINUXDVB_ERROR;
|
||||
}
|
||||
else
|
||||
{
|
||||
struct pollfd pfd[1];
|
||||
pfd[0].fd = videofd;
|
||||
pfd[0].events = POLLPRI;
|
||||
int pollret = poll(pfd, 1, 0);
|
||||
if (pollret > 0 && pfd[0].revents & POLLPRI)
|
||||
{
|
||||
struct video_event evt;
|
||||
if (ioctl(videofd, VIDEO_GET_EVENT, &evt) == -1)
|
||||
{
|
||||
linuxdvb_err("ioctl failed with errno %d\n", errno);
|
||||
linuxdvb_err("VIDEO_GET_EVENT: %s\n", strerror(errno));
|
||||
}
|
||||
else
|
||||
{
|
||||
if (evt.type == VIDEO_EVENT_SIZE_CHANGED)
|
||||
{
|
||||
linuxdvb_printf(10, "VIDEO_EVENT_SIZE_CHANGED type: 0x%x\n", evt.type);
|
||||
linuxdvb_printf(10, "width : %d\n", evt.u.size.w);
|
||||
linuxdvb_printf(10, "height : %d\n", evt.u.size.h);
|
||||
linuxdvb_printf(10, "aspect : %d\n", evt.u.size.aspect_ratio);
|
||||
videoInfo.width = evt.u.size.w;
|
||||
videoInfo.height = evt.u.size.h;
|
||||
videoInfo.aspect_ratio = evt.u.size.aspect_ratio;
|
||||
}
|
||||
else if (evt.type == VIDEO_EVENT_FRAME_RATE_CHANGED)
|
||||
{
|
||||
linuxdvb_printf(10, "VIDEO_EVENT_FRAME_RATE_CHANGED type: 0x%x\n", evt.type);
|
||||
linuxdvb_printf(10, "framerate : %d\n", evt.u.frame_rate);
|
||||
videoInfo.frame_rate = evt.u.frame_rate;
|
||||
}
|
||||
else if (evt.type == 16 /*VIDEO_EVENT_PROGRESSIVE_CHANGED*/)
|
||||
{
|
||||
linuxdvb_printf(10, "VIDEO_EVENT_PROGRESSIVE_CHANGED type: 0x%x\n", evt.type);
|
||||
linuxdvb_printf(10, "progressive : %d\n", evt.u.frame_rate);
|
||||
videoInfo.progressive = evt.u.frame_rate;
|
||||
context->manager->video->Command(context, MANAGER_UPDATED_TRACK_INFO, NULL);
|
||||
}
|
||||
else
|
||||
{
|
||||
linuxdvb_err("unhandled DVBAPI Video Event %d\n", evt.type);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
call.fd = videofd;
|
||||
call.data = out->data;
|
||||
call.len = out->len;
|
||||
call.Pts = out->pts;
|
||||
call.Dts = out->dts;
|
||||
call.private_data = out->extradata;
|
||||
call.private_size = out->extralen;
|
||||
call.FrameRate = out->frameRate;
|
||||
call.FrameScale = out->timeScale;
|
||||
call.Width = out->width;
|
||||
call.Height = out->height;
|
||||
call.InfoFlags = out->infoFlags;
|
||||
call.Version = 0;
|
||||
call.WriteV = isBufferedOutput ? BufferingWriteV : writev_with_retry;
|
||||
|
||||
if (writer->writeData)
|
||||
{
|
||||
res = writer->writeData(&call);
|
||||
}
|
||||
|
||||
if (res < 0)
|
||||
{
|
||||
linuxdvb_err("failed to write data %d - %d\n", res, errno);
|
||||
linuxdvb_err("%s\n", strerror(errno));
|
||||
ret = cERR_LINUXDVB_ERROR;
|
||||
}
|
||||
}
|
||||
|
||||
free(Encoding);
|
||||
}
|
||||
else if (audio)
|
||||
{
|
||||
char *Encoding = NULL;
|
||||
context->manager->audio->Command(context, MANAGER_GETENCODING, &Encoding);
|
||||
|
||||
linuxdvb_printf(20, "Encoding = %s\n", Encoding);
|
||||
|
||||
writer = getWriter(Encoding);
|
||||
|
||||
if (writer == NULL)
|
||||
{
|
||||
linuxdvb_printf(20, "searching default writer ... %s\n", Encoding);
|
||||
writer = getDefaultAudioWriter();
|
||||
}
|
||||
|
||||
if (writer == NULL)
|
||||
{
|
||||
linuxdvb_err("unknown audio codec %s and no default writer\n", Encoding);
|
||||
ret = cERR_LINUXDVB_ERROR;
|
||||
}
|
||||
else
|
||||
{
|
||||
call.fd = audiofd;
|
||||
call.data = out->data;
|
||||
call.len = out->len;
|
||||
call.Pts = out->pts;
|
||||
call.Dts = out->dts;
|
||||
call.private_data = out->extradata;
|
||||
call.private_size = out->extralen;
|
||||
call.FrameRate = out->frameRate;
|
||||
call.FrameScale = out->timeScale;
|
||||
call.InfoFlags = out->infoFlags;
|
||||
call.Version = 0;
|
||||
call.WriteV = isBufferedOutput ? BufferingWriteV : writev_with_retry;
|
||||
|
||||
if (writer->writeData)
|
||||
{
|
||||
res = writer->writeData(&call);
|
||||
}
|
||||
|
||||
if (res < 0)
|
||||
{
|
||||
linuxdvb_err("failed to write data %d - %d\n", res, errno);
|
||||
linuxdvb_err("%s\n", strerror(errno));
|
||||
ret = cERR_LINUXDVB_ERROR;
|
||||
}
|
||||
}
|
||||
|
||||
free(Encoding);
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int reset(Context_t *context __attribute__((unused)))
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int Command(Context_t *context, OutputCmd_t command, void *argument)
|
||||
{
|
||||
int ret = cERR_LINUXDVB_NO_ERROR;
|
||||
|
||||
linuxdvb_printf(50, "Command %d\n", command);
|
||||
|
||||
switch (command)
|
||||
{
|
||||
case OUTPUT_OPEN:
|
||||
{
|
||||
ret = LinuxDvbOpen(context, (char *)argument);
|
||||
break;
|
||||
}
|
||||
case OUTPUT_CLOSE:
|
||||
{
|
||||
ret = LinuxDvbClose(context, (char *)argument);
|
||||
reset(context);
|
||||
sCURRENT_PTS = 0;
|
||||
break;
|
||||
}
|
||||
case OUTPUT_PLAY: // 4
|
||||
{
|
||||
sCURRENT_PTS = 0;
|
||||
ret = LinuxDvbPlay(context, (char *)argument);
|
||||
break;
|
||||
}
|
||||
case OUTPUT_STOP:
|
||||
{
|
||||
reset(context);
|
||||
ret = LinuxDvbStop(context, (char *)argument);
|
||||
sCURRENT_PTS = 0;
|
||||
break;
|
||||
}
|
||||
case OUTPUT_FLUSH:
|
||||
{
|
||||
ret = LinuxDvbFlush(context, (char *)argument);
|
||||
reset(context);
|
||||
sCURRENT_PTS = 0;
|
||||
break;
|
||||
}
|
||||
case OUTPUT_PAUSE:
|
||||
{
|
||||
ret = LinuxDvbPause(context, (char *)argument);
|
||||
break;
|
||||
}
|
||||
case OUTPUT_CONTINUE:
|
||||
{
|
||||
ret = LinuxDvbContinue(context, (char *)argument);
|
||||
break;
|
||||
}
|
||||
case OUTPUT_AVSYNC:
|
||||
{
|
||||
ret = LinuxDvbAVSync(context, (char *)argument);
|
||||
break;
|
||||
}
|
||||
case OUTPUT_CLEAR:
|
||||
{
|
||||
ret = LinuxDvbClear(context, (char *)argument);
|
||||
reset(context);
|
||||
sCURRENT_PTS = 0;
|
||||
break;
|
||||
}
|
||||
case OUTPUT_PTS:
|
||||
{
|
||||
unsigned long long int pts = 0;
|
||||
ret = LinuxDvbPts(context, &pts);
|
||||
*((unsigned long long int *)argument) = (unsigned long long int)pts;
|
||||
break;
|
||||
}
|
||||
case OUTPUT_SWITCH:
|
||||
{
|
||||
ret = LinuxDvbSwitch(context, (char *)argument);
|
||||
break;
|
||||
}
|
||||
case OUTPUT_SLOWMOTION:
|
||||
{
|
||||
return LinuxDvbSlowMotion(context, (char *)argument);
|
||||
break;
|
||||
}
|
||||
case OUTPUT_AUDIOMUTE:
|
||||
{
|
||||
return LinuxDvbAudioMute(context, (char *)argument);
|
||||
break;
|
||||
}
|
||||
case OUTPUT_GET_FRAME_COUNT:
|
||||
{
|
||||
unsigned long long int frameCount = 0;
|
||||
ret = LinuxDvbGetFrameCount(context, &frameCount);
|
||||
*((unsigned long long int *)argument) = (unsigned long long int)frameCount;
|
||||
break;
|
||||
}
|
||||
case OUTPUT_GET_PROGRESSIVE:
|
||||
{
|
||||
ret = cERR_LINUXDVB_NO_ERROR;
|
||||
*((int *)argument) = videoInfo.progressive;
|
||||
break;
|
||||
}
|
||||
case OUTPUT_SET_BUFFER_SIZE:
|
||||
{
|
||||
ret = cERR_LINUXDVB_ERROR;
|
||||
if (!isBufferedOutput)
|
||||
{
|
||||
uint32_t bufferSize = *((uint32_t *)argument);
|
||||
ret = cERR_LINUXDVB_NO_ERROR;
|
||||
if (bufferSize > 0)
|
||||
{
|
||||
LinuxDvbBuffSetSize(bufferSize);
|
||||
isBufferedOutput = true;
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
case OUTPUT_GET_BUFFER_SIZE:
|
||||
{
|
||||
ret = cERR_LINUXDVB_NO_ERROR;
|
||||
*((uint32_t *)argument) = LinuxDvbBuffGetSize();
|
||||
break;
|
||||
}
|
||||
default:
|
||||
linuxdvb_err("ContainerCmd %d not supported!\n", command);
|
||||
ret = cERR_LINUXDVB_ERROR;
|
||||
break;
|
||||
}
|
||||
|
||||
linuxdvb_printf(50, "exiting with value %d\n", ret);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static char *LinuxDvbCapabilities[] = { "audio", "video", NULL };
|
||||
|
||||
struct Output_s LinuxDvbOutput =
|
||||
{
|
||||
"LinuxDvb",
|
||||
&Command,
|
||||
&Write,
|
||||
LinuxDvbCapabilities
|
||||
};
|
1173
libeplayer3/output/linuxdvb_mipsel.c
Normal file
1173
libeplayer3/output/linuxdvb_mipsel.c
Normal file
File diff suppressed because it is too large
Load Diff
1316
libeplayer3/output/linuxdvb_sh4.c
Normal file
1316
libeplayer3/output/linuxdvb_sh4.c
Normal file
File diff suppressed because it is too large
Load Diff
604
libeplayer3/output/output.c
Normal file
604
libeplayer3/output/output.c
Normal file
@@ -0,0 +1,604 @@
|
||||
/*
|
||||
* 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 "debug.h"
|
||||
#include "common.h"
|
||||
#include "output.h"
|
||||
|
||||
/* ***************************** */
|
||||
/* Makros/Constants */
|
||||
/* ***************************** */
|
||||
|
||||
/* Error Constants */
|
||||
#define cERR_OUTPUT_NO_ERROR 0
|
||||
#define cERR_OUTPUT_INTERNAL_ERROR -1
|
||||
|
||||
/* ***************************** */
|
||||
/* Types */
|
||||
/* ***************************** */
|
||||
|
||||
/* ***************************** */
|
||||
/* Variables */
|
||||
/* ***************************** */
|
||||
|
||||
static Output_t *AvailableOutput[] =
|
||||
{
|
||||
&LinuxDvbOutput,
|
||||
&SubtitleOutput,
|
||||
NULL
|
||||
};
|
||||
|
||||
/* ***************************** */
|
||||
/* Prototypes */
|
||||
/* ***************************** */
|
||||
|
||||
/* ***************************** */
|
||||
/* MISC Functions */
|
||||
/* ***************************** */
|
||||
|
||||
static void printOutputCapabilities()
|
||||
{
|
||||
int i, j;
|
||||
|
||||
output_printf(10, "%s::%s\n", __FILE__, __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", __FILE__, __FUNCTION__);
|
||||
|
||||
for (i = 0; AvailableOutput[i] != NULL; i++)
|
||||
{
|
||||
for (j = 0; AvailableOutput[i]->Capabilities[j] != NULL; j++)
|
||||
{
|
||||
if (!strcmp(AvailableOutput[i]->Capabilities[j], port))
|
||||
{
|
||||
if (!strcmp("audio", port))
|
||||
{
|
||||
context->output->audio = AvailableOutput[i];
|
||||
return;
|
||||
}
|
||||
else if (!strcmp("video", port))
|
||||
{
|
||||
context->output->video = AvailableOutput[i];
|
||||
return;
|
||||
}
|
||||
else if (!strcmp("subtitle", port))
|
||||
{
|
||||
context->output->subtitle = AvailableOutput[i];
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void OutputDel(Context_t *context, char *port)
|
||||
{
|
||||
output_printf(10, "%s::%s\n", __FILE__, __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(Context_t *context, OutputCmd_t command, void *argument)
|
||||
{
|
||||
int ret = cERR_OUTPUT_NO_ERROR;
|
||||
|
||||
output_printf(10, "%s::%s Command %d\n", __FILE__, __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");
|
||||
}
|
||||
else
|
||||
ret = cERR_OUTPUT_INTERNAL_ERROR;
|
||||
|
||||
// success or not executed, dunn care
|
||||
if (context->playback->isAudio)
|
||||
{
|
||||
ret = context->output->audio->Command(context, OUTPUT_PLAY, "audio");
|
||||
}
|
||||
|
||||
if (!ret)
|
||||
{
|
||||
if (context->playback->isSubtitle)
|
||||
{
|
||||
ret = context->output->subtitle->Command(context, OUTPUT_PLAY, "subtitle");
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
ret = cERR_OUTPUT_INTERNAL_ERROR;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case OUTPUT_STOP:
|
||||
{
|
||||
if (context && context->playback)
|
||||
{
|
||||
if (context->playback->isVideo)
|
||||
{
|
||||
ret |= context->output->video->Command(context, OUTPUT_STOP, "video");
|
||||
}
|
||||
|
||||
if (context->playback->isAudio)
|
||||
{
|
||||
ret |= context->output->audio->Command(context, OUTPUT_STOP, "audio");
|
||||
}
|
||||
|
||||
if (context->playback->isSubtitle)
|
||||
{
|
||||
ret |= context->output->subtitle->Command(context, OUTPUT_STOP, "subtitle");
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
ret = cERR_OUTPUT_INTERNAL_ERROR;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case OUTPUT_FLUSH:
|
||||
{
|
||||
if (context && context->playback)
|
||||
{
|
||||
if (context->playback->isVideo)
|
||||
{
|
||||
ret |= context->output->video->Command(context, OUTPUT_FLUSH, "video");
|
||||
}
|
||||
|
||||
if (context->playback->isAudio)
|
||||
{
|
||||
ret |= context->output->audio->Command(context, OUTPUT_FLUSH, "audio");
|
||||
}
|
||||
|
||||
if (context->playback->isSubtitle)
|
||||
{
|
||||
ret |= context->output->subtitle->Command(context, OUTPUT_FLUSH, "subtitle");
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
ret = cERR_OUTPUT_INTERNAL_ERROR;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case OUTPUT_PAUSE:
|
||||
{
|
||||
if (context && context->playback)
|
||||
{
|
||||
if (context->playback->isVideo)
|
||||
{
|
||||
ret |= context->output->video->Command(context, OUTPUT_PAUSE, "video");
|
||||
}
|
||||
|
||||
if (context->playback->isAudio)
|
||||
{
|
||||
ret |= context->output->audio->Command(context, OUTPUT_PAUSE, "audio");
|
||||
}
|
||||
|
||||
if (context->playback->isSubtitle)
|
||||
{
|
||||
ret |= context->output->subtitle->Command(context, OUTPUT_PAUSE, "subtitle");
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
ret = cERR_OUTPUT_INTERNAL_ERROR;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case OUTPUT_FASTFORWARD:
|
||||
{
|
||||
if (context && context->playback)
|
||||
{
|
||||
if (context->playback->isVideo)
|
||||
{
|
||||
ret |= context->output->video->Command(context, OUTPUT_FASTFORWARD, "video");
|
||||
}
|
||||
|
||||
if (context->playback->isAudio)
|
||||
{
|
||||
ret |= context->output->audio->Command(context, OUTPUT_FASTFORWARD, "audio");
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
ret = cERR_OUTPUT_INTERNAL_ERROR;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case OUTPUT_REVERSE:
|
||||
{
|
||||
if (context && context->playback)
|
||||
{
|
||||
if (context->playback->isVideo)
|
||||
{
|
||||
ret |= context->output->video->Command(context, OUTPUT_REVERSE, "video");
|
||||
}
|
||||
|
||||
if (context->playback->isAudio)
|
||||
{
|
||||
ret |= context->output->audio->Command(context, OUTPUT_REVERSE, "audio");
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
ret = cERR_OUTPUT_INTERNAL_ERROR;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case OUTPUT_CONTINUE:
|
||||
{
|
||||
if (context && context->playback)
|
||||
{
|
||||
if (context->playback->isVideo)
|
||||
{
|
||||
ret |= context->output->video->Command(context, OUTPUT_CONTINUE, "video");
|
||||
}
|
||||
|
||||
if (context->playback->isAudio)
|
||||
{
|
||||
ret |= context->output->audio->Command(context, OUTPUT_CONTINUE, "audio");
|
||||
}
|
||||
|
||||
if (context->playback->isSubtitle)
|
||||
{
|
||||
ret |= context->output->subtitle->Command(context, OUTPUT_CONTINUE, "subtitle");
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
ret = cERR_OUTPUT_INTERNAL_ERROR;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case OUTPUT_AVSYNC:
|
||||
{
|
||||
if (context && context->playback)
|
||||
{
|
||||
if (context->playback->isVideo && context->playback->isAudio)
|
||||
{
|
||||
ret |= context->output->audio->Command(context, OUTPUT_AVSYNC, "audio");
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
ret = cERR_OUTPUT_INTERNAL_ERROR;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case OUTPUT_CLEAR:
|
||||
{
|
||||
if (context && context->playback)
|
||||
{
|
||||
if (context->playback->isVideo && (argument == NULL || *(char *) argument == 'v'))
|
||||
{
|
||||
ret |= context->output->video->Command(context, OUTPUT_CLEAR, "video");
|
||||
}
|
||||
|
||||
if (context->playback->isAudio && (argument == NULL || *(char *) argument == 'a'))
|
||||
{
|
||||
ret |= context->output->audio->Command(context, OUTPUT_CLEAR, "audio");
|
||||
}
|
||||
|
||||
if (context->playback->isSubtitle && (argument == NULL || *(char *) argument == 's'))
|
||||
{
|
||||
ret |= context->output->subtitle->Command(context, OUTPUT_CLEAR, "subtitle");
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
ret = cERR_OUTPUT_INTERNAL_ERROR;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case OUTPUT_PTS:
|
||||
{
|
||||
if (context && context->playback)
|
||||
{
|
||||
if (context->playback->isVideo)
|
||||
{
|
||||
return context->output->video->Command(context, OUTPUT_PTS, argument);
|
||||
}
|
||||
|
||||
if (context->playback->isAudio)
|
||||
{
|
||||
return context->output->audio->Command(context, OUTPUT_PTS, argument);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
ret = cERR_OUTPUT_INTERNAL_ERROR;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case OUTPUT_SWITCH:
|
||||
{
|
||||
if (context && context->playback)
|
||||
{
|
||||
if (context->playback->isAudio)
|
||||
{
|
||||
return context->output->audio->Command(context, OUTPUT_SWITCH, "audio");
|
||||
}
|
||||
|
||||
if (context->playback->isVideo)
|
||||
{
|
||||
return context->output->video->Command(context, OUTPUT_SWITCH, "video");
|
||||
}
|
||||
|
||||
if (context->playback->isSubtitle)
|
||||
{
|
||||
return context->output->subtitle->Command(context, OUTPUT_SWITCH, "subtitle");
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
ret = cERR_OUTPUT_INTERNAL_ERROR;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case OUTPUT_SLOWMOTION:
|
||||
{
|
||||
if (context && context->playback)
|
||||
{
|
||||
if (context->playback->isVideo)
|
||||
{
|
||||
ret |= context->output->video->Command(context, OUTPUT_SLOWMOTION, "video");
|
||||
}
|
||||
|
||||
if (context->playback->isAudio)
|
||||
{
|
||||
ret |= context->output->audio->Command(context, OUTPUT_SLOWMOTION, "audio");
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
ret = cERR_OUTPUT_INTERNAL_ERROR;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case OUTPUT_AUDIOMUTE:
|
||||
{
|
||||
if (context && context->playback)
|
||||
{
|
||||
if (context->playback->isAudio)
|
||||
{
|
||||
ret |= context->output->audio->Command(context, OUTPUT_AUDIOMUTE, (char *) argument);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
ret = cERR_OUTPUT_INTERNAL_ERROR;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case OUTPUT_DISCONTINUITY_REVERSE:
|
||||
{
|
||||
if (context && context->playback)
|
||||
{
|
||||
if (context->playback->isVideo)
|
||||
{
|
||||
ret |= context->output->video->Command(context, OUTPUT_DISCONTINUITY_REVERSE, (void *) argument);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
ret = cERR_OUTPUT_INTERNAL_ERROR;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case OUTPUT_GET_FRAME_COUNT:
|
||||
{
|
||||
if (context && context->playback)
|
||||
{
|
||||
if (context->playback->isVideo)
|
||||
{
|
||||
return context->output->video->Command(context, OUTPUT_GET_FRAME_COUNT, argument);
|
||||
}
|
||||
|
||||
if (context->playback->isAudio)
|
||||
{
|
||||
return context->output->audio->Command(context, OUTPUT_GET_FRAME_COUNT, argument);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
ret = cERR_OUTPUT_INTERNAL_ERROR;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case OUTPUT_GET_PROGRESSIVE:
|
||||
{
|
||||
if (context && context->playback)
|
||||
{
|
||||
if (context->playback->isVideo)
|
||||
{
|
||||
return context->output->video->Command(context, OUTPUT_GET_PROGRESSIVE, (void *) argument);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
ret = cERR_OUTPUT_INTERNAL_ERROR;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case OUTPUT_SET_BUFFER_SIZE:
|
||||
{
|
||||
if (context && context->playback)
|
||||
{
|
||||
if (context->output->video)
|
||||
{
|
||||
return context->output->video->Command(context, OUTPUT_SET_BUFFER_SIZE, argument);
|
||||
}
|
||||
else if (context->output->audio)
|
||||
{
|
||||
return context->output->audio->Command(context, OUTPUT_SET_BUFFER_SIZE, argument);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
ret = cERR_OUTPUT_INTERNAL_ERROR;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case OUTPUT_GET_BUFFER_SIZE:
|
||||
{
|
||||
if (context && context->playback)
|
||||
{
|
||||
if (context->output->video)
|
||||
{
|
||||
return context->output->video->Command(context, OUTPUT_GET_BUFFER_SIZE, argument);
|
||||
}
|
||||
else if (context->output->audio)
|
||||
{
|
||||
return context->output->audio->Command(context, OUTPUT_GET_BUFFER_SIZE, argument);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
ret = cERR_OUTPUT_INTERNAL_ERROR;
|
||||
}
|
||||
break;
|
||||
}
|
||||
default:
|
||||
output_err("%s::%s OutputCmd %d not supported!\n", __FILE__, __FUNCTION__, command);
|
||||
ret = cERR_OUTPUT_INTERNAL_ERROR;
|
||||
break;
|
||||
}
|
||||
|
||||
output_printf(10, "%s::%s exiting with value %d\n", __FILE__, __FUNCTION__, ret);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
OutputHandler_t OutputHandler =
|
||||
{
|
||||
"Output",
|
||||
NULL, //audio
|
||||
NULL, //video
|
||||
NULL, //subtitle
|
||||
&Command
|
||||
};
|
337
libeplayer3/output/output_subtitle.c
Normal file
337
libeplayer3/output/output_subtitle.c
Normal file
@@ -0,0 +1,337 @@
|
||||
/*
|
||||
* 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 <inttypes.h>
|
||||
#include <fcntl.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
#include <memory.h>
|
||||
#include <asm/types.h>
|
||||
#include <errno.h>
|
||||
|
||||
#include "common.h"
|
||||
#include "debug.h"
|
||||
#include "output.h"
|
||||
|
||||
/* ***************************** */
|
||||
/* Makros/Constants */
|
||||
/* ***************************** */
|
||||
|
||||
/* Error Constants */
|
||||
#define cERR_SUBTITLE_NO_ERROR 0
|
||||
#define cERR_SUBTITLE_ERROR -1
|
||||
|
||||
/*
|
||||
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 */
|
||||
/* ***************************** */
|
||||
|
||||
|
||||
/* ***************************** */
|
||||
/* Variables */
|
||||
/* ***************************** */
|
||||
|
||||
static pthread_mutex_t mutex;
|
||||
static int isSubtitleOpened = 0;
|
||||
|
||||
/* ***************************** */
|
||||
/* Prototypes */
|
||||
/* ***************************** */
|
||||
|
||||
/* ***************************** */
|
||||
/* MISC Functions */
|
||||
/* ***************************** */
|
||||
|
||||
static void getMutex(int line __attribute__((unused)))
|
||||
{
|
||||
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 __attribute__((unused)))
|
||||
{
|
||||
pthread_mutex_unlock(&mutex);
|
||||
|
||||
subtitle_printf(100, "%d released mutex\n", line);
|
||||
}
|
||||
|
||||
/* ***************************** */
|
||||
/* Functions */
|
||||
/* ***************************** */
|
||||
|
||||
static char *ass_get_text(char *str)
|
||||
{
|
||||
// Events are stored in the Block in this order:
|
||||
// ReadOrder, Layer, Style, Name, MarginL, MarginR, MarginV, Effect, Text
|
||||
// 91,0,Default,,0,0,0,,maar hij smaakt vast tof.
|
||||
int i = 0;
|
||||
char *p_str = str;
|
||||
while (i < 8 && *p_str != '\0')
|
||||
{
|
||||
if (*p_str == ',')
|
||||
i++;
|
||||
p_str++;
|
||||
}
|
||||
// standardize hard break: '\N' -> '\n'
|
||||
// http://docs.aegisub.org/3.2/ASS_Tags/
|
||||
char *p_newline = NULL;
|
||||
while ((p_newline = strstr(p_str, "\\N")) != NULL)
|
||||
* (p_newline + 1) = 'n';
|
||||
return p_str;
|
||||
}
|
||||
|
||||
static char *json_string_escape(char *str)
|
||||
{
|
||||
static char tmp[2048];
|
||||
char *ptr1 = tmp;
|
||||
char *ptr2 = str;
|
||||
while (*ptr2 != '\0')
|
||||
{
|
||||
switch (*ptr2)
|
||||
{
|
||||
case '"':
|
||||
*ptr1++ = '\\';
|
||||
*ptr1++ = '\"';
|
||||
break;
|
||||
case '\\':
|
||||
*ptr1++ = '\\';
|
||||
*ptr1++ = '\\';
|
||||
break;
|
||||
case '\b':
|
||||
*ptr1++ = '\\';
|
||||
*ptr1++ = 'b';
|
||||
break;
|
||||
case '\f':
|
||||
*ptr1++ = '\\';
|
||||
*ptr1++ = 'f';
|
||||
break;
|
||||
case '\n':
|
||||
*ptr1++ = '\\';
|
||||
*ptr1++ = 'n';
|
||||
break;
|
||||
case '\r':
|
||||
*ptr1++ = '\\';
|
||||
*ptr1++ = 'r';
|
||||
break;
|
||||
case '\t':
|
||||
*ptr1++ = '\\';
|
||||
*ptr1++ = 't';
|
||||
break;
|
||||
default:
|
||||
*ptr1++ = *ptr2;
|
||||
break;
|
||||
}
|
||||
|
||||
++ptr2;
|
||||
}
|
||||
*ptr1 = '\0';
|
||||
return tmp;
|
||||
}
|
||||
|
||||
static int Flush()
|
||||
{
|
||||
fprintf(stderr, "{\"s_f\":{\"r\":0}}\n");
|
||||
return cERR_SUBTITLE_NO_ERROR;
|
||||
}
|
||||
|
||||
static int Write(Context_t *context, void *data)
|
||||
{
|
||||
char *Encoding = NULL;
|
||||
SubtitleOut_t *out = NULL;
|
||||
int32_t curtrackid = -1;
|
||||
|
||||
subtitle_printf(10, "\n");
|
||||
|
||||
if (data == NULL)
|
||||
{
|
||||
subtitle_err("null pointer passed\n");
|
||||
return cERR_SUBTITLE_ERROR;
|
||||
}
|
||||
|
||||
out = (SubtitleOut_t *) data;
|
||||
|
||||
context->manager->subtitle->Command(context, MANAGER_GET, &curtrackid);
|
||||
if (curtrackid != (int32_t)out->trackId)
|
||||
{
|
||||
Flush();
|
||||
}
|
||||
context->manager->subtitle->Command(context, MANAGER_GETENCODING, &Encoding);
|
||||
|
||||
if (Encoding == NULL)
|
||||
{
|
||||
subtitle_err("encoding unknown\n");
|
||||
return cERR_SUBTITLE_ERROR;
|
||||
}
|
||||
|
||||
subtitle_printf(20, "Encoding:%s Text:%s Len:%d\n", Encoding, (const char *) out->data, out->len);
|
||||
|
||||
if (!strncmp("S_TEXT/SUBRIP", Encoding, 13))
|
||||
{
|
||||
fprintf(stderr, "{\"s_a\":{\"id\":%d,\"s\":%" PRId64 ",\"e\":%" PRId64 ",\"t\":\"%s\"}}\n", out->trackId, out->pts / 90, out->pts / 90 + out->durationMS, json_string_escape((char *)out->data));
|
||||
}
|
||||
else if (!strncmp("S_TEXT/ASS", Encoding, 10))
|
||||
{
|
||||
fprintf(stderr, "{\"s_a\":{\"id\":%d,\"s\":%" PRId64 ",\"e\":%" PRId64 ",\"t\":\"%s\"}}\n", out->trackId, out->pts / 90, out->pts / 90 + out->durationMS, ass_get_text((char *)out->data));
|
||||
}
|
||||
else if (!strncmp("D_WEBVTT/SUBTITLES", Encoding, 18))
|
||||
{
|
||||
fprintf(stderr, "{\"s_a\":{\"id\":%d,\"s\":%" PRId64 ",\"e\":%" PRId64 ",\"t\":\"%s\"}}\n", out->trackId, out->pts / 90, out->pts / 90 + out->durationMS, json_string_escape((char *)out->data));
|
||||
}
|
||||
else
|
||||
{
|
||||
subtitle_err("unknown encoding %s\n", Encoding);
|
||||
return cERR_SUBTITLE_ERROR;
|
||||
}
|
||||
|
||||
subtitle_printf(10, "<\n");
|
||||
return cERR_SUBTITLE_NO_ERROR;
|
||||
}
|
||||
|
||||
static int32_t subtitle_Open(Context_t *context __attribute__((unused)))
|
||||
{
|
||||
//uint32_t i = 0 ;
|
||||
|
||||
subtitle_printf(10, "\n");
|
||||
|
||||
if (isSubtitleOpened == 1)
|
||||
{
|
||||
subtitle_err("already opened! ignoring\n");
|
||||
return cERR_SUBTITLE_ERROR;
|
||||
}
|
||||
|
||||
getMutex(__LINE__);
|
||||
|
||||
isSubtitleOpened = 1;
|
||||
|
||||
releaseMutex(__LINE__);
|
||||
|
||||
subtitle_printf(10, "<\n");
|
||||
return cERR_SUBTITLE_NO_ERROR;
|
||||
}
|
||||
|
||||
static int32_t subtitle_Close(Context_t *context __attribute__((unused)))
|
||||
{
|
||||
subtitle_printf(10, "\n");
|
||||
|
||||
getMutex(__LINE__);
|
||||
|
||||
isSubtitleOpened = 0;
|
||||
|
||||
releaseMutex(__LINE__);
|
||||
|
||||
subtitle_printf(10, "<\n");
|
||||
|
||||
return cERR_SUBTITLE_NO_ERROR;
|
||||
}
|
||||
|
||||
static int Command(Context_t *context, OutputCmd_t command, void *argument __attribute__((unused)))
|
||||
{
|
||||
int ret = cERR_SUBTITLE_NO_ERROR;
|
||||
|
||||
subtitle_printf(50, "%d\n", command);
|
||||
|
||||
switch (command)
|
||||
{
|
||||
case OUTPUT_OPEN:
|
||||
{
|
||||
ret = subtitle_Open(context);
|
||||
break;
|
||||
}
|
||||
case OUTPUT_CLOSE:
|
||||
{
|
||||
ret = subtitle_Close(context);
|
||||
break;
|
||||
}
|
||||
case OUTPUT_PLAY:
|
||||
{
|
||||
break;
|
||||
}
|
||||
case OUTPUT_STOP:
|
||||
{
|
||||
break;
|
||||
}
|
||||
case OUTPUT_SWITCH:
|
||||
{
|
||||
ret = Flush();
|
||||
break;
|
||||
}
|
||||
case OUTPUT_FLUSH:
|
||||
{
|
||||
ret = Flush();
|
||||
break;
|
||||
}
|
||||
case OUTPUT_CLEAR:
|
||||
{
|
||||
ret = Flush();
|
||||
break;
|
||||
}
|
||||
case OUTPUT_PAUSE:
|
||||
{
|
||||
subtitle_err("Subtitle Pause not implemented\n");
|
||||
ret = cERR_SUBTITLE_ERROR;
|
||||
break;
|
||||
}
|
||||
case OUTPUT_CONTINUE:
|
||||
{
|
||||
subtitle_err("Subtitle Continue not implemented\n");
|
||||
ret = cERR_SUBTITLE_ERROR;
|
||||
break;
|
||||
}
|
||||
default:
|
||||
subtitle_err("OutputCmd %d not supported!\n", command);
|
||||
ret = cERR_SUBTITLE_ERROR;
|
||||
break;
|
||||
}
|
||||
|
||||
subtitle_printf(50, "exiting with value %d\n", ret);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
static char *SubtitleCapabilitis[] = { "subtitle", NULL };
|
||||
|
||||
Output_t SubtitleOutput =
|
||||
{
|
||||
"Subtitle",
|
||||
&Command,
|
||||
&Write,
|
||||
SubtitleCapabilitis
|
||||
};
|
159
libeplayer3/output/writer/common/misc.c
Normal file
159
libeplayer3/output/writer/common/misc.c
Normal file
@@ -0,0 +1,159 @@
|
||||
/*
|
||||
* LinuxDVB Output handling.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*
|
||||
*/
|
||||
|
||||
/* ***************************** */
|
||||
/* Includes */
|
||||
/* ***************************** */
|
||||
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
#include <unistd.h>
|
||||
#include <fcntl.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
#include <sys/ioctl.h>
|
||||
#include <linux/dvb/video.h>
|
||||
#include <linux/dvb/audio.h>
|
||||
|
||||
#include <memory.h>
|
||||
#include <asm/types.h>
|
||||
#include <pthread.h>
|
||||
#include <errno.h>
|
||||
|
||||
#include "stm_ioctls.h"
|
||||
#include "bcm_ioctls.h"
|
||||
|
||||
#include "common.h"
|
||||
#include "output.h"
|
||||
#include "debug.h"
|
||||
#include "misc.h"
|
||||
|
||||
/* ***************************** */
|
||||
/* Makros/Constants */
|
||||
/* ***************************** */
|
||||
|
||||
/* ***************************** */
|
||||
/* Types */
|
||||
/* ***************************** */
|
||||
|
||||
/* ***************************** */
|
||||
/* Varaibles */
|
||||
/* ***************************** */
|
||||
|
||||
/* ***************************** */
|
||||
/* Prototypes */
|
||||
/* ***************************** */
|
||||
|
||||
/* ***************************** */
|
||||
/* MISC Functions */
|
||||
/* ***************************** */
|
||||
|
||||
void PutBits(BitPacker_t *ld, unsigned int code, unsigned int length)
|
||||
{
|
||||
unsigned int bit_buf;
|
||||
unsigned int bit_left;
|
||||
|
||||
bit_buf = ld->BitBuffer;
|
||||
bit_left = ld->Remaining;
|
||||
|
||||
#ifdef DEBUG_PUTBITS
|
||||
if (ld->debug)
|
||||
dprintf("code = %d, length = %d, bit_buf = 0x%x, bit_left = %d\n", code, length, bit_buf, bit_left);
|
||||
#endif /* DEBUG_PUTBITS */
|
||||
|
||||
if (length < bit_left)
|
||||
{
|
||||
/* fits into current buffer */
|
||||
bit_buf = (bit_buf << length) | code;
|
||||
bit_left -= length;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* doesn't fit */
|
||||
bit_buf <<= bit_left;
|
||||
bit_buf |= code >> (length - bit_left);
|
||||
ld->Ptr[0] = (char)(bit_buf >> 24);
|
||||
ld->Ptr[1] = (char)(bit_buf >> 16);
|
||||
ld->Ptr[2] = (char)(bit_buf >> 8);
|
||||
ld->Ptr[3] = (char)bit_buf;
|
||||
ld->Ptr += 4;
|
||||
length -= bit_left;
|
||||
bit_buf = code & ((1 << length) - 1);
|
||||
bit_left = 32 - length;
|
||||
bit_buf = code;
|
||||
}
|
||||
|
||||
#ifdef DEBUG_PUTBITS
|
||||
if (ld->debug)
|
||||
dprintf("bit_left = %d, bit_buf = 0x%x\n", bit_left, bit_buf);
|
||||
#endif /* DEBUG_PUTBITS */
|
||||
|
||||
/* writeback */
|
||||
ld->BitBuffer = bit_buf;
|
||||
ld->Remaining = bit_left;
|
||||
}
|
||||
|
||||
void FlushBits(BitPacker_t *ld)
|
||||
{
|
||||
ld->BitBuffer <<= ld->Remaining;
|
||||
while (ld->Remaining < 32)
|
||||
{
|
||||
#ifdef DEBUG_PUTBITS
|
||||
if (ld->debug)
|
||||
dprintf("flushing 0x%2.2x\n", ld->BitBuffer >> 24);
|
||||
#endif /* DEBUG_PUTBITS */
|
||||
*ld->Ptr++ = ld->BitBuffer >> 24;
|
||||
ld->BitBuffer <<= 8;
|
||||
ld->Remaining += 8;
|
||||
}
|
||||
ld->Remaining = 32;
|
||||
ld->BitBuffer = 0;
|
||||
}
|
||||
|
||||
stb_type_t GetSTBType()
|
||||
{
|
||||
static stb_type_t type = STB_UNKNOWN;
|
||||
if (type == STB_UNKNOWN)
|
||||
{
|
||||
// struct stat buffer;
|
||||
if (access("/proc/stb/tpm/0/serial", F_OK) != -1)
|
||||
{
|
||||
type = STB_DREAMBOX;
|
||||
}
|
||||
else if (access("/proc/stb/info/vumodel", F_OK) != -1 &&
|
||||
access("/proc/stb/info/boxtype", F_OK) == -1)
|
||||
{
|
||||
// some STB like Octagon SF4008 has also /proc/stb/info/vumodel
|
||||
// but VU PLUS does not have /proc/stb/info/boxtype
|
||||
// please see: https://gitlab.com/e2i/e2iplayer/issues/282
|
||||
type = STB_VUPLUS;
|
||||
}
|
||||
else if (access("/sys/firmware/devicetree/base/soc/hisilicon_clock/name", F_OK) != -1)
|
||||
{
|
||||
type = STB_HISILICON;
|
||||
}
|
||||
else
|
||||
{
|
||||
type = STB_OTHER;
|
||||
}
|
||||
}
|
||||
|
||||
return type;
|
||||
}
|
184
libeplayer3/output/writer/common/pes.c
Normal file
184
libeplayer3/output/writer/common/pes.c
Normal file
@@ -0,0 +1,184 @@
|
||||
/*
|
||||
* linuxdvb output/writer handling.
|
||||
*
|
||||
* konfetti 2010 based on linuxdvb.c code from libeplayer2
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*
|
||||
*/
|
||||
|
||||
/* ***************************** */
|
||||
/* Includes */
|
||||
/* ***************************** */
|
||||
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
#include <unistd.h>
|
||||
#include <fcntl.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
#include <sys/ioctl.h>
|
||||
#include <linux/dvb/video.h>
|
||||
#include <linux/dvb/audio.h>
|
||||
|
||||
#include <memory.h>
|
||||
#include <asm/types.h>
|
||||
#include <pthread.h>
|
||||
#include <errno.h>
|
||||
|
||||
#include "stm_ioctls.h"
|
||||
#include "bcm_ioctls.h"
|
||||
|
||||
#include "common.h"
|
||||
#include "output.h"
|
||||
#include "debug.h"
|
||||
#include "misc.h"
|
||||
#include "pes.h"
|
||||
#include "writer.h"
|
||||
|
||||
/* ***************************** */
|
||||
/* Makros/Constants */
|
||||
/* ***************************** */
|
||||
|
||||
/* ***************************** */
|
||||
/* Types */
|
||||
/* ***************************** */
|
||||
|
||||
|
||||
/* ***************************** */
|
||||
/* Varaibles */
|
||||
/* ***************************** */
|
||||
|
||||
/* ***************************** */
|
||||
/* Prototypes */
|
||||
/* ***************************** */
|
||||
|
||||
/* ***************************** */
|
||||
/* Functions */
|
||||
/* ***************************** */
|
||||
|
||||
int32_t InsertVideoPrivateDataHeader(uint8_t *data, int32_t payload_size)
|
||||
{
|
||||
BitPacker_t ld2 = {data, 0, 32};
|
||||
int32_t i = 0;
|
||||
|
||||
PutBits(&ld2, PES_PRIVATE_DATA_FLAG, 8);
|
||||
PutBits(&ld2, payload_size & 0xff, 8);
|
||||
PutBits(&ld2, (payload_size >> 8) & 0xff, 8);
|
||||
PutBits(&ld2, (payload_size >> 16) & 0xff, 8);
|
||||
|
||||
for (i = 4; i < (PES_PRIVATE_DATA_LENGTH + 1); i++)
|
||||
{
|
||||
PutBits(&ld2, 0, 8);
|
||||
}
|
||||
|
||||
FlushBits(&ld2);
|
||||
|
||||
return PES_PRIVATE_DATA_LENGTH + 1;
|
||||
}
|
||||
|
||||
void UpdatePesHeaderPayloadSize(uint8_t *data, int32_t size)
|
||||
{
|
||||
if (size > MAX_PES_PACKET_SIZE || size < 0)
|
||||
size = 0;
|
||||
data[4] = size >> 8;
|
||||
data[5] = size & 0xFF;
|
||||
}
|
||||
|
||||
int32_t InsertPesHeader(uint8_t *data, int32_t size, uint8_t stream_id, uint64_t pts, int32_t pic_start_code)
|
||||
{
|
||||
BitPacker_t ld2 = {data, 0, 32};
|
||||
|
||||
PutBits(&ld2, 0x0, 8);
|
||||
PutBits(&ld2, 0x0, 8);
|
||||
PutBits(&ld2, 0x1, 8); // Start Code
|
||||
PutBits(&ld2, stream_id, 8); // Stream_id = Audio Stream
|
||||
|
||||
if (size > 0)
|
||||
{
|
||||
size += 3 + (pts != INVALID_PTS_VALUE ? 5 : 0) + (pic_start_code ? (5) : 0);
|
||||
}
|
||||
|
||||
if (size > MAX_PES_PACKET_SIZE || size < 0)
|
||||
{
|
||||
size = 0; // unbounded
|
||||
}
|
||||
|
||||
//4
|
||||
PutBits(&ld2, size, 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);
|
||||
}
|
65
libeplayer3/output/writer/common/writer.c
Normal file
65
libeplayer3/output/writer/common/writer.c
Normal file
@@ -0,0 +1,65 @@
|
||||
/*
|
||||
* linuxdvb output/writer handling.
|
||||
*
|
||||
* konfetti 2010
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*
|
||||
*/
|
||||
|
||||
/* ***************************** */
|
||||
/* Includes */
|
||||
/* ***************************** */
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <errno.h>
|
||||
|
||||
#include "misc.h"
|
||||
#include "writer.h"
|
||||
#include "debug.h"
|
||||
#include "common.h"
|
||||
|
||||
/* ***************************** */
|
||||
/* Makros/Constants */
|
||||
/* ***************************** */
|
||||
|
||||
/* ***************************** */
|
||||
/* Types */
|
||||
/* ***************************** */
|
||||
|
||||
/* ***************************** */
|
||||
/* Varaibles */
|
||||
/* ***************************** */
|
||||
|
||||
/* ***************************** */
|
||||
/* Prototypes */
|
||||
/* ***************************** */
|
||||
|
||||
/* ***************************** */
|
||||
/* Functions */
|
||||
/* ***************************** */
|
||||
void FlushPipe(int pipefd)
|
||||
{
|
||||
char tmp;
|
||||
while (1 == read(pipefd, &tmp, 1));
|
||||
}
|
||||
|
||||
ssize_t WriteExt(WriteV_t _call, int fd, void *data, size_t size)
|
||||
{
|
||||
struct iovec iov[1];
|
||||
iov[0].iov_base = data;
|
||||
iov[0].iov_len = size;
|
||||
return _call(fd, iov, 1);
|
||||
}
|
384
libeplayer3/output/writer/mipsel/aac.c
Normal file
384
libeplayer3/output/writer/mipsel/aac.c
Normal file
@@ -0,0 +1,384 @@
|
||||
/*
|
||||
* linuxdvb output/writer handling.
|
||||
*
|
||||
* konfetti 2010 based on linuxdvb.c code from libeplayer2
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*
|
||||
*/
|
||||
|
||||
/* ***************************** */
|
||||
/* Includes */
|
||||
/* ***************************** */
|
||||
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
#include <unistd.h>
|
||||
#include <fcntl.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
#include <sys/ioctl.h>
|
||||
#include <linux/dvb/video.h>
|
||||
#include <linux/dvb/audio.h>
|
||||
#include <memory.h>
|
||||
#include <asm/types.h>
|
||||
#include <pthread.h>
|
||||
#include <errno.h>
|
||||
#include <sys/uio.h>
|
||||
|
||||
#include <libavutil/intreadwrite.h>
|
||||
#include "ffmpeg/latmenc.h"
|
||||
|
||||
#include "stm_ioctls.h"
|
||||
#include "bcm_ioctls.h"
|
||||
|
||||
#include "debug.h"
|
||||
#include "common.h"
|
||||
#include "output.h"
|
||||
#include "debug.h"
|
||||
#include "misc.h"
|
||||
#include "pes.h"
|
||||
#include "writer.h"
|
||||
#include "aac.h"
|
||||
|
||||
/* ***************************** */
|
||||
/* Makros/Constants */
|
||||
/* ***************************** */
|
||||
|
||||
/* ***************************** */
|
||||
/* Types */
|
||||
/* ***************************** */
|
||||
|
||||
/* ***************************** */
|
||||
/* Variables */
|
||||
/* ***************************** */
|
||||
|
||||
/// ** AAC ADTS format **
|
||||
///
|
||||
/// AAAAAAAA AAAABCCD EEFFFFGH HHIJKLMM
|
||||
/// MMMMMMMM MMMNNNNN NNNNNNOO ........
|
||||
///
|
||||
/// Sign Length Position Description
|
||||
///
|
||||
/// A 12 (31-20) Sync code
|
||||
/// B 1 (19) ID
|
||||
/// C 2 (18-17) layer
|
||||
/// D 1 (16) protect absent
|
||||
/// E 2 (15-14) profile
|
||||
/// F 4 (13-10) sample freq index
|
||||
/// G 1 (9) private
|
||||
/// H 3 (8-6) channel config
|
||||
/// I 1 (5) original/copy
|
||||
/// J 1 (4) home
|
||||
/// K 1 (3) copyright id
|
||||
/// L 1 (2) copyright start
|
||||
/// M 13 (1-0,31-21) frame length
|
||||
/// N 11 (20-10) adts buffer fullness
|
||||
/// O 2 (9-8) num of raw data blocks in frame
|
||||
|
||||
/*
|
||||
LC: Audio: aac, 44100 Hz, stereo, s16, 192 kb/ ->ff f1 50 80 00 1f fc
|
||||
HE: Audio: aac, 48000 Hz, stereo, s16, 77 kb/s ->ff f1 4c 80 00 1f fc
|
||||
*/
|
||||
|
||||
/*
|
||||
ADIF = basic format called Audio Data Interchange Format (ADIF)
|
||||
consisting of a single header followed by the raw AAC audio data blocks
|
||||
ADTS = streaming format called Audio Data Transport Stream (ADTS)
|
||||
consisting of a series of frames, each frame having a header followed by the AAC audio data
|
||||
LOAS = Low Overhead Audio Stream (LOAS), a self-synchronizing streaming format
|
||||
*/
|
||||
|
||||
static unsigned char DefaultAACHeader[] =
|
||||
{
|
||||
0xff,
|
||||
0xf1,
|
||||
/*0x00, 0x00*/0x50, //((Profile & 0x03) << 6) | (SampleIndex << 2) | ((Channels >> 2) & 0x01);s
|
||||
0x80, //(Channels & 0x03) << 6;
|
||||
0x00,
|
||||
0x1f,
|
||||
0xfc
|
||||
};
|
||||
|
||||
LATMContext *pLATMCtx = NULL;
|
||||
|
||||
/* ***************************** */
|
||||
/* Prototypes */
|
||||
/* ***************************** */
|
||||
|
||||
/* ***************************** */
|
||||
/* MISC Functions */
|
||||
/* ***************************** */
|
||||
|
||||
static int reset()
|
||||
{
|
||||
if (pLATMCtx)
|
||||
{
|
||||
free(pLATMCtx);
|
||||
pLATMCtx = NULL;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int _writeData(WriterAVCallData_t *call, int type)
|
||||
{
|
||||
aac_printf(10, "\n _writeData type[%d]\n", type);
|
||||
|
||||
if (call == NULL)
|
||||
{
|
||||
aac_err("call data is NULL...\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
if ((call->data == NULL) || (call->len < 8))
|
||||
{
|
||||
aac_err("parsing Data with missing AAC header. ignoring...\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* simple validation */
|
||||
if (0 == type) // check ADTS header
|
||||
{
|
||||
if (0xFF != call->data[0] || 0xF0 != (0xF0 & call->data[1]))
|
||||
{
|
||||
aac_err("parsing Data with missing syncword. ignoring...\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
// STB can handle only AAC LC profile
|
||||
if (0 == (call->data[2] & 0xC0))
|
||||
{
|
||||
// change profile AAC Main -> AAC LC (Low Complexity)
|
||||
aac_printf(1, "change profile AAC Main -> AAC LC (Low Complexity) in the ADTS header");
|
||||
call->data[2] = (call->data[2] & 0x1F) | 0x40;
|
||||
}
|
||||
}
|
||||
else // check LOAS header
|
||||
{
|
||||
if (!(call->len > 2 && call->data[0] == 0x56 && (call->data[1] >> 4) == 0xe &&
|
||||
((uint32_t)(AV_RB16(call->data + 1) & 0x1FFF) + 3) == call->len))
|
||||
{
|
||||
aac_err("parsing Data with wrong latm header. ignoring...\n");
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
unsigned char PesHeader[PES_MAX_HEADER_SIZE];
|
||||
|
||||
aac_printf(10, "AudioPts %lld\n", call->Pts);
|
||||
|
||||
unsigned int HeaderLength = InsertPesHeader(PesHeader, call->len, MPEG_AUDIO_PES_START_CODE, call->Pts, 0);
|
||||
|
||||
struct iovec iov[2];
|
||||
iov[0].iov_base = PesHeader;
|
||||
iov[0].iov_len = HeaderLength;
|
||||
iov[1].iov_base = call->data;
|
||||
iov[1].iov_len = call->len;
|
||||
return call->WriteV(call->fd, iov, 2);
|
||||
}
|
||||
|
||||
static int writeDataADTS(WriterAVCallData_t *call)
|
||||
{
|
||||
aac_printf(10, "\n");
|
||||
|
||||
if (call == NULL)
|
||||
{
|
||||
aac_err("call data is NULL...\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
if ((call->data == NULL) || (call->len <= 0))
|
||||
{
|
||||
aac_err("parsing NULL Data. ignoring...\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (call->fd < 0)
|
||||
{
|
||||
aac_err("file pointer < 0. ignoring ...\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
if ((call->private_data && 0 == strncmp("ADTS", (const char *)call->private_data, call->private_size)) ||
|
||||
HasADTSHeader(call->data, call->len))
|
||||
{
|
||||
//printf("%hhx %hhx %hhx %hhx %hhx %hhx %hhx %hhx\n", call->data[0], call->data[1], call->data[2], call->data[3], call->data[4], call->data[5], call->data[6], call->data[7]);
|
||||
return _writeData(call, 0);
|
||||
}
|
||||
|
||||
uint32_t PacketLength = call->len + AAC_HEADER_LENGTH;
|
||||
uint8_t PesHeader[PES_MAX_HEADER_SIZE + AAC_HEADER_LENGTH];
|
||||
uint32_t headerSize = InsertPesHeader(PesHeader, PacketLength, MPEG_AUDIO_PES_START_CODE, call->Pts, 0);
|
||||
uint8_t *pExtraData = &PesHeader[headerSize];
|
||||
|
||||
aac_printf(10, "AudioPts %lld\n", call->Pts);
|
||||
if (call->private_data == NULL)
|
||||
{
|
||||
aac_printf(10, "private_data = NULL\n");
|
||||
memcpy(pExtraData, DefaultAACHeader, AAC_HEADER_LENGTH);
|
||||
}
|
||||
else
|
||||
{
|
||||
memcpy(pExtraData, call->private_data, AAC_HEADER_LENGTH);
|
||||
}
|
||||
|
||||
pExtraData[3] &= 0xC0;
|
||||
/* frame size over last 2 bits */
|
||||
pExtraData[3] |= (PacketLength & 0x1800) >> 11;
|
||||
/* frame size continued over full byte */
|
||||
pExtraData[4] = (PacketLength & 0x1FF8) >> 3;
|
||||
/* frame size continued first 3 bits */
|
||||
pExtraData[5] = (PacketLength & 7) << 5;
|
||||
/* buffer fullness(0x7FF for VBR) over 5 last bits */
|
||||
pExtraData[5] |= 0x1F;
|
||||
/* buffer fullness(0x7FF for VBR) continued over 6 first bits + 2 zeros for
|
||||
* number of raw data blocks */
|
||||
pExtraData[6] = 0xFC;
|
||||
|
||||
//PesHeader[6] = 0x81;
|
||||
|
||||
struct iovec iov[2];
|
||||
iov[0].iov_base = PesHeader;
|
||||
iov[0].iov_len = headerSize + AAC_HEADER_LENGTH;
|
||||
iov[1].iov_base = call->data;
|
||||
iov[1].iov_len = call->len;
|
||||
|
||||
return call->WriteV(call->fd, iov, 2);
|
||||
}
|
||||
|
||||
static int writeDataLATM(WriterAVCallData_t *call)
|
||||
{
|
||||
aac_printf(10, "\n");
|
||||
|
||||
if (call == NULL)
|
||||
{
|
||||
aac_err("call data is NULL...\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
if ((call->data == NULL) || (call->len <= 0))
|
||||
{
|
||||
aac_err("parsing NULL Data. ignoring...\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (call->private_data && 0 == strncmp("LATM", (const char *)call->private_data, call->private_size))
|
||||
{
|
||||
return _writeData(call, 1);
|
||||
}
|
||||
|
||||
aac_printf(10, "AudioPts %lld\n", call->Pts);
|
||||
|
||||
if (!pLATMCtx)
|
||||
{
|
||||
pLATMCtx = malloc(sizeof(LATMContext));
|
||||
memset(pLATMCtx, 0x00, sizeof(LATMContext));
|
||||
pLATMCtx->mod = 14;
|
||||
pLATMCtx->counter = 0;
|
||||
}
|
||||
|
||||
if (!pLATMCtx)
|
||||
{
|
||||
aac_err("parsing NULL pLATMCtx. ignoring...\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
unsigned char PesHeader[PES_MAX_HEADER_SIZE];
|
||||
int ret = latmenc_decode_extradata(pLATMCtx, call->private_data, call->private_size);
|
||||
if (ret)
|
||||
{
|
||||
/* printf("%02x %02x %02x %02x %02x %02x %02x %02x\n", (int)call->data[0], (int)call->data[1], (int)call->data[2], (int)call->data[3], \
|
||||
(int)call->data[4], (int)call->data[5], (int)call->data[6], (int)call->data[7]);
|
||||
*/
|
||||
aac_err("latm_decode_extradata failed. ignoring...\n");
|
||||
return 0;
|
||||
}
|
||||
ret = latmenc_write_packet(pLATMCtx, call->data, call->len, call->private_data, call->private_size);
|
||||
if (ret)
|
||||
{
|
||||
aac_err("latm_write_packet failed. ignoring...\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
unsigned int HeaderLength = InsertPesHeader(PesHeader, pLATMCtx->len + 3, MPEG_AUDIO_PES_START_CODE, call->Pts, 0);
|
||||
|
||||
struct iovec iov[3];
|
||||
iov[0].iov_base = PesHeader;
|
||||
iov[0].iov_len = HeaderLength;
|
||||
|
||||
iov[1].iov_base = pLATMCtx->loas_header;
|
||||
iov[1].iov_len = 3;
|
||||
|
||||
iov[2].iov_base = pLATMCtx->buffer;
|
||||
iov[2].iov_len = pLATMCtx->len;
|
||||
|
||||
return call->WriteV(call->fd, iov, 3);
|
||||
}
|
||||
|
||||
/* ***************************** */
|
||||
/* Writer Definition */
|
||||
/* ***************************** */
|
||||
|
||||
static WriterCaps_t caps =
|
||||
{
|
||||
"aac",
|
||||
eAudio,
|
||||
"A_AAC",
|
||||
-1,
|
||||
AUDIOTYPE_AAC_PLUS,
|
||||
-1
|
||||
};
|
||||
|
||||
struct Writer_s WriterAudioAAC =
|
||||
{
|
||||
&reset,
|
||||
&writeDataADTS,
|
||||
&caps
|
||||
};
|
||||
|
||||
static WriterCaps_t caps_aac_latm =
|
||||
{
|
||||
"aac",
|
||||
eAudio,
|
||||
"A_AAC_LATM",
|
||||
-1,
|
||||
AUDIOTYPE_AAC_HE, // it is some misunderstanding, this should be AUDIOTYPE_AAC_LATM
|
||||
-1
|
||||
};
|
||||
|
||||
struct Writer_s WriterAudioAACLATM =
|
||||
{
|
||||
&reset,
|
||||
&writeDataLATM,
|
||||
&caps_aac_latm
|
||||
};
|
||||
|
||||
static WriterCaps_t caps_aacplus =
|
||||
{
|
||||
"aac",
|
||||
eAudio,
|
||||
"A_AAC_PLUS",
|
||||
-1,
|
||||
AUDIOTYPE_AAC_PLUS,
|
||||
-1
|
||||
};
|
||||
|
||||
struct Writer_s WriterAudioAACPLUS =
|
||||
{
|
||||
&reset,
|
||||
&writeDataADTS,
|
||||
&caps_aacplus
|
||||
};
|
162
libeplayer3/output/writer/mipsel/ac3.c
Normal file
162
libeplayer3/output/writer/mipsel/ac3.c
Normal file
@@ -0,0 +1,162 @@
|
||||
/*
|
||||
* linuxdvb output/writer handling.
|
||||
*
|
||||
* konfetti 2010 based on linuxdvb.c code from libeplayer2
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*
|
||||
*/
|
||||
|
||||
/* ***************************** */
|
||||
/* Includes */
|
||||
/* ***************************** */
|
||||
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
#include <unistd.h>
|
||||
#include <fcntl.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
#include <sys/ioctl.h>
|
||||
#include <sys/uio.h>
|
||||
#include <linux/dvb/video.h>
|
||||
#include <linux/dvb/audio.h>
|
||||
#include <memory.h>
|
||||
#include <asm/types.h>
|
||||
#include <pthread.h>
|
||||
#include <errno.h>
|
||||
|
||||
#include "stm_ioctls.h"
|
||||
#include "bcm_ioctls.h"
|
||||
|
||||
#include "debug.h"
|
||||
#include "common.h"
|
||||
#include "output.h"
|
||||
#include "debug.h"
|
||||
#include "misc.h"
|
||||
#include "pes.h"
|
||||
#include "writer.h"
|
||||
|
||||
/* ***************************** */
|
||||
/* Makros/Constants */
|
||||
/* ***************************** */
|
||||
#define AC3_HEADER_LENGTH 7
|
||||
|
||||
/* ***************************** */
|
||||
/* Types */
|
||||
/* ***************************** */
|
||||
|
||||
/* ***************************** */
|
||||
/* Variables */
|
||||
/* ***************************** */
|
||||
|
||||
unsigned char AC3_SYNC_HEADER[] = {0x80, 0x01, 0x00, 0x01};
|
||||
|
||||
/* ***************************** */
|
||||
/* Prototypes */
|
||||
/* ***************************** */
|
||||
|
||||
/* ***************************** */
|
||||
/* MISC Functions */
|
||||
/* ***************************** */
|
||||
|
||||
static int reset()
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int writeData(WriterAVCallData_t *call)
|
||||
{
|
||||
ac3_printf(10, "\n");
|
||||
|
||||
unsigned char PesHeader[PES_MAX_HEADER_SIZE];
|
||||
|
||||
if (call == NULL)
|
||||
{
|
||||
ac3_err("call data is NULL...\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
ac3_printf(10, "AudioPts %lld\n", call->Pts);
|
||||
|
||||
if ((call->data == NULL) || (call->len <= 0))
|
||||
{
|
||||
ac3_err("parsing NULL Data. ignoring...\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (call->fd < 0)
|
||||
{
|
||||
ac3_err("file pointer < 0. ignoring ...\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
struct iovec iov[3];
|
||||
|
||||
iov[0].iov_base = PesHeader;
|
||||
iov[0].iov_len = InsertPesHeader(PesHeader, call->len, MPEG_AUDIO_PES_START_CODE, call->Pts, 0); //+ sizeof(AC3_SYNC_HEADER)
|
||||
|
||||
//PesHeader[6] = 0x81;
|
||||
//PesHeader[7] = 0x80;
|
||||
//PesHeader[8] = 0x09;
|
||||
|
||||
//iov[1].iov_base = AC3_SYNC_HEADER;
|
||||
//iov[1].iov_len = sizeof(AC3_SYNC_HEADER);
|
||||
iov[1].iov_base = call->data;
|
||||
iov[1].iov_len = call->len;
|
||||
|
||||
ac3_printf(40, "PES HEADER LEN %d\n", (int)iov[0].iov_len);
|
||||
|
||||
return call->WriteV(call->fd, iov, 2);
|
||||
}
|
||||
|
||||
/* ***************************** */
|
||||
/* Writer Definition */
|
||||
/* ***************************** */
|
||||
|
||||
static WriterCaps_t caps_ac3 =
|
||||
{
|
||||
"ac3",
|
||||
eAudio,
|
||||
"A_AC3",
|
||||
AUDIO_ENCODING_AC3,
|
||||
AUDIOTYPE_AC3,
|
||||
-1
|
||||
};
|
||||
|
||||
struct Writer_s WriterAudioAC3 =
|
||||
{
|
||||
&reset,
|
||||
&writeData,
|
||||
&caps_ac3
|
||||
};
|
||||
|
||||
static WriterCaps_t caps_eac3 =
|
||||
{
|
||||
"ac3",
|
||||
eAudio,
|
||||
"A_EAC3",
|
||||
AUDIO_ENCODING_AC3,
|
||||
AUDIOTYPE_AC3_PLUS,
|
||||
-1
|
||||
};
|
||||
|
||||
struct Writer_s WriterAudioEAC3 =
|
||||
{
|
||||
&reset,
|
||||
&writeData,
|
||||
&caps_eac3
|
||||
};
|
162
libeplayer3/output/writer/mipsel/amr.c
Normal file
162
libeplayer3/output/writer/mipsel/amr.c
Normal file
@@ -0,0 +1,162 @@
|
||||
/*
|
||||
* linuxdvb output/writer handling.
|
||||
*
|
||||
* konfetti 2010 based on linuxdvb.c code from libeplayer2
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*
|
||||
*/
|
||||
|
||||
/* ***************************** */
|
||||
/* Includes */
|
||||
/* ***************************** */
|
||||
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
#include <unistd.h>
|
||||
#include <fcntl.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
#include <sys/ioctl.h>
|
||||
#include <sys/uio.h>
|
||||
#include <linux/dvb/video.h>
|
||||
#include <linux/dvb/audio.h>
|
||||
#include <memory.h>
|
||||
#include <asm/types.h>
|
||||
#include <pthread.h>
|
||||
#include <errno.h>
|
||||
|
||||
//#include "stm_ioctls.h"
|
||||
#include "bcm_ioctls.h"
|
||||
|
||||
#include "debug.h"
|
||||
#include "common.h"
|
||||
#include "output.h"
|
||||
#include "debug.h"
|
||||
#include "misc.h"
|
||||
#include "pes.h"
|
||||
#include "writer.h"
|
||||
|
||||
/* ***************************** */
|
||||
/* Makros/Constants */
|
||||
/* ***************************** */
|
||||
|
||||
/* ***************************** */
|
||||
/* Types */
|
||||
/* ***************************** */
|
||||
|
||||
/* ***************************** */
|
||||
/* Variables */
|
||||
/* ***************************** */
|
||||
|
||||
/* ***************************** */
|
||||
/* Prototypes */
|
||||
/* ***************************** */
|
||||
|
||||
/* ***************************** */
|
||||
/* MISC Functions */
|
||||
/* ***************************** */
|
||||
|
||||
static int reset()
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int writeData(WriterAVCallData_t *call)
|
||||
{
|
||||
unsigned char PesHeader[PES_MAX_HEADER_SIZE + 4 + 9];
|
||||
|
||||
amr_printf(10, "\n");
|
||||
|
||||
if (call == NULL)
|
||||
{
|
||||
amr_err("call data is NULL...\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
amr_printf(10, "AudioPts %lld\n", call->Pts);
|
||||
|
||||
if ((call->data == NULL) || (call->len <= 0))
|
||||
{
|
||||
amr_err("parsing NULL Data. ignoring...\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (call->fd < 0)
|
||||
{
|
||||
amr_err("file pointer < 0. ignoring ...\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
uint8_t hasCodecData = 1;
|
||||
if (NULL != call->private_data && call->private_size >= 17)
|
||||
{
|
||||
amr_err("wrong private_data. ignoring ...\n");
|
||||
hasCodecData = 1;
|
||||
}
|
||||
size_t payload_len = call->len;
|
||||
if (hasCodecData)
|
||||
{
|
||||
payload_len += 9;
|
||||
}
|
||||
payload_len += 4;
|
||||
|
||||
uint32_t headerSize = InsertPesHeader(PesHeader, payload_len, MPEG_AUDIO_PES_START_CODE, call->Pts, 0);
|
||||
PesHeader[headerSize++] = (payload_len >> 24) & 0xff;
|
||||
PesHeader[headerSize++] = (payload_len >> 16) & 0xff;
|
||||
PesHeader[headerSize++] = (payload_len >> 8) & 0xff;
|
||||
PesHeader[headerSize++] = payload_len & 0xff;
|
||||
|
||||
if (hasCodecData)
|
||||
{
|
||||
uint8_t tmp[] = {0x45, 0x4d, 0x50, 0x20, 0x00, 0x00, 0x80, 0x00, 0x01};
|
||||
memcpy(&PesHeader[headerSize], tmp, 9);
|
||||
//memcpy(&PesHeader[headerSize], call->private_data + 8, 9);
|
||||
//memset(&PesHeader[headerSize], 0, 9);
|
||||
}
|
||||
|
||||
struct iovec iov[2];
|
||||
iov[0].iov_base = PesHeader;
|
||||
iov[0].iov_len = headerSize;
|
||||
iov[1].iov_base = call->data;
|
||||
iov[1].iov_len = call->len;
|
||||
|
||||
int len = call->WriteV(call->fd, iov, 2);
|
||||
|
||||
amr_printf(10, "amr_Write-< len=%d\n", len);
|
||||
return len;
|
||||
}
|
||||
|
||||
/* ***************************** */
|
||||
/* Writer Definition */
|
||||
/* ***************************** */
|
||||
|
||||
static WriterCaps_t caps_amr =
|
||||
{
|
||||
"amr",
|
||||
eAudio,
|
||||
"A_AMR",
|
||||
-1,
|
||||
AUDIOTYPE_AMR,
|
||||
-1
|
||||
};
|
||||
|
||||
struct Writer_s WriterAudioAMR =
|
||||
{
|
||||
&reset,
|
||||
&writeData,
|
||||
&caps_amr
|
||||
};
|
189
libeplayer3/output/writer/mipsel/divx3.c
Normal file
189
libeplayer3/output/writer/mipsel/divx3.c
Normal file
@@ -0,0 +1,189 @@
|
||||
/*
|
||||
* linuxdvb output/writer handling.
|
||||
*
|
||||
* konfetti 2010 based on linuxdvb.c code from libeplayer2
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*
|
||||
*/
|
||||
|
||||
/* ***************************** */
|
||||
/* Includes */
|
||||
/* ***************************** */
|
||||
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
#include <unistd.h>
|
||||
#include <fcntl.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
#include <sys/ioctl.h>
|
||||
#include <sys/uio.h>
|
||||
#include <linux/dvb/video.h>
|
||||
#include <linux/dvb/audio.h>
|
||||
#include <memory.h>
|
||||
#include <asm/types.h>
|
||||
#include <pthread.h>
|
||||
#include <errno.h>
|
||||
|
||||
#include "stm_ioctls.h"
|
||||
#include "bcm_ioctls.h"
|
||||
|
||||
#include "debug.h"
|
||||
#include "common.h"
|
||||
#include "output.h"
|
||||
#include "debug.h"
|
||||
#include "misc.h"
|
||||
#include "pes.h"
|
||||
#include "writer.h"
|
||||
|
||||
/* ***************************** */
|
||||
/* Makros/Constants */
|
||||
/* ***************************** */
|
||||
|
||||
#define B_GET_BITS(w,e,b) (((w)>>(b))&(((unsigned)(-1))>>((sizeof(unsigned))*8-(e+1-b))))
|
||||
#define B_SET_BITS(name,v,e,b) (((unsigned)(v))<<(b))
|
||||
|
||||
/* ***************************** */
|
||||
/* Types */
|
||||
/* ***************************** */
|
||||
|
||||
/* ***************************** */
|
||||
/* Variables */
|
||||
/* ***************************** */
|
||||
|
||||
static uint8_t initialHeader = 1;
|
||||
static uint8_t brcm_divx311_sequence_header[] =
|
||||
{
|
||||
0x00, 0x00, 0x01, 0xE0, 0x00, 0x34, 0x80, 0x80, // PES HEADER
|
||||
0x05, 0x2F, 0xFF, 0xFF, 0xFF, 0xFF,
|
||||
0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x20, /* 0 .. 7 */
|
||||
0x08, 0xC8, 0x0D, 0x40, 0x00, 0x53, 0x88, 0x40, /* 8 .. 15 */
|
||||
0x0C, 0x40, 0x01, 0x90, 0x00, 0x97, 0x53, 0x0A, /* 16 .. 24 */
|
||||
0x00, 0x00, 0x00, 0x00,
|
||||
0x30, 0x7F, 0x00, 0x00, 0x01, 0xB2, 0x44, 0x69, /* 0 .. 7 */
|
||||
0x76, 0x58, 0x33, 0x31, 0x31, 0x41, 0x4E, 0x44 /* 8 .. 15 */
|
||||
};
|
||||
|
||||
/* ***************************** */
|
||||
/* Prototypes */
|
||||
/* ***************************** */
|
||||
|
||||
/* ***************************** */
|
||||
/* MISC Functions */
|
||||
/* ***************************** */
|
||||
|
||||
static int reset()
|
||||
{
|
||||
initialHeader = 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int writeData(WriterAVCallData_t *call)
|
||||
{
|
||||
unsigned char PesHeader[PES_MAX_HEADER_SIZE + 4];
|
||||
// unsigned char Version = 5;
|
||||
// unsigned int FakeStartCode = (Version << 8) | PES_VERSION_FAKE_START_CODE;
|
||||
|
||||
divx_printf(10, "\n");
|
||||
|
||||
if (call == NULL)
|
||||
{
|
||||
divx_err("call data is NULL...\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
if ((call->data == NULL) || (call->len <= 0))
|
||||
{
|
||||
divx_err("parsing NULL Data. ignoring...\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (call->fd < 0)
|
||||
{
|
||||
divx_err("file pointer < 0. ignoring ...\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
divx_printf(10, "AudioPts %lld\n", call->Pts);
|
||||
|
||||
struct iovec iov[8];
|
||||
int ic = 0;
|
||||
|
||||
if (initialHeader)
|
||||
{
|
||||
initialHeader = 0;
|
||||
uint8_t *data = brcm_divx311_sequence_header;
|
||||
int32_t height = call->Height;
|
||||
int32_t width = call->Width;
|
||||
data += 38;
|
||||
data[0] = B_GET_BITS(width, 11, 4);
|
||||
data[1] = B_SET_BITS("width [3..0]", B_GET_BITS(width, 3, 0), 7, 4) |
|
||||
B_SET_BITS("'10'", 0x02, 3, 2) |
|
||||
B_SET_BITS("height [11..10]", B_GET_BITS(height, 11, 10), 1, 0);
|
||||
data[2] = B_GET_BITS(height, 9, 2);
|
||||
data[3] = B_SET_BITS("height [1.0]", B_GET_BITS(height, 1, 0), 7, 6) |
|
||||
B_SET_BITS("'100000'", 0x20, 5, 0);
|
||||
|
||||
iov[ic].iov_base = brcm_divx311_sequence_header;
|
||||
iov[ic++].iov_len = sizeof(brcm_divx311_sequence_header);
|
||||
}
|
||||
|
||||
iov[ic].iov_base = PesHeader;
|
||||
uint32_t headerSize = 0;
|
||||
|
||||
if (memcmp(call->data, "\x00\x00\x01\xb6", 4))
|
||||
{
|
||||
headerSize = InsertPesHeader(PesHeader, call->len + 4, MPEG_VIDEO_PES_START_CODE, call->Pts, 0);
|
||||
memcpy(PesHeader + headerSize, "\x00\x00\x01\xb6", 4);
|
||||
headerSize += 4;
|
||||
}
|
||||
else
|
||||
{
|
||||
headerSize = InsertPesHeader(PesHeader, call->len, MPEG_VIDEO_PES_START_CODE, call->Pts, 0);
|
||||
}
|
||||
iov[ic++].iov_len = headerSize;
|
||||
|
||||
iov[ic].iov_base = call->data;
|
||||
iov[ic++].iov_len = call->len;
|
||||
|
||||
int len = call->WriteV(call->fd, iov, ic);
|
||||
|
||||
divx_printf(10, "xvid_Write < len=%d\n", len);
|
||||
|
||||
return len;
|
||||
}
|
||||
|
||||
/* ***************************** */
|
||||
/* Writer Definition */
|
||||
/* ***************************** */
|
||||
|
||||
static WriterCaps_t divix3_caps =
|
||||
{
|
||||
"divix3",
|
||||
eVideo,
|
||||
"V_DIVX3",
|
||||
VIDEO_ENCODING_MPEG4P2,
|
||||
STREAMTYPE_DIVX311,
|
||||
-1
|
||||
};
|
||||
|
||||
struct Writer_s WriterVideoDIVX3 =
|
||||
{
|
||||
&reset,
|
||||
&writeData,
|
||||
&divix3_caps
|
||||
};
|
167
libeplayer3/output/writer/mipsel/dts.c
Normal file
167
libeplayer3/output/writer/mipsel/dts.c
Normal file
@@ -0,0 +1,167 @@
|
||||
/*
|
||||
* linuxdvb output/writer handling.
|
||||
*
|
||||
* konfetti 2010 based on linuxdvb.c code from libeplayer2
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*
|
||||
*/
|
||||
|
||||
/* ***************************** */
|
||||
/* Includes */
|
||||
/* ***************************** */
|
||||
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
#include <unistd.h>
|
||||
#include <fcntl.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
#include <sys/ioctl.h>
|
||||
#include <sys/uio.h>
|
||||
#include <linux/dvb/video.h>
|
||||
#include <linux/dvb/audio.h>
|
||||
#include <memory.h>
|
||||
#include <asm/types.h>
|
||||
#include <pthread.h>
|
||||
#include <errno.h>
|
||||
|
||||
#include "stm_ioctls.h"
|
||||
#include "bcm_ioctls.h"
|
||||
|
||||
#include "debug.h"
|
||||
#include "common.h"
|
||||
#include "output.h"
|
||||
#include "debug.h"
|
||||
#include "misc.h"
|
||||
#include "pes.h"
|
||||
#include "writer.h"
|
||||
|
||||
/* ***************************** */
|
||||
/* Makros/Constants */
|
||||
/* ***************************** */
|
||||
|
||||
#define PES_AUDIO_PRIVATE_HEADER_SIZE 16 // consider maximum private header size.
|
||||
#define PES_AUDIO_HEADER_SIZE (32 + PES_AUDIO_PRIVATE_HEADER_SIZE)
|
||||
#define PES_AUDIO_PACKET_SIZE 2028
|
||||
#define SPDIF_AUDIO_PACKET_SIZE (1024 * sizeof(unsigned int) * 2) // stereo 32bit samples.
|
||||
|
||||
/* ***************************** */
|
||||
/* Types */
|
||||
/* ***************************** */
|
||||
|
||||
/* ***************************** */
|
||||
/* Variables */
|
||||
/* ***************************** */
|
||||
|
||||
/* ***************************** */
|
||||
/* Prototypes */
|
||||
/* ***************************** */
|
||||
|
||||
/* ***************************** */
|
||||
/* MISC Functions */
|
||||
/* ***************************** */
|
||||
|
||||
static int32_t reset()
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int writeData(WriterAVCallData_t *call)
|
||||
{
|
||||
uint8_t PesHeader[PES_AUDIO_HEADER_SIZE];
|
||||
|
||||
dts_printf(10, "\n");
|
||||
|
||||
if (call == NULL)
|
||||
{
|
||||
dts_err("call data is NULL...\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
dts_printf(10, "AudioPts %lld\n", call->Pts);
|
||||
|
||||
if ((call->data == NULL) || (call->len <= 0))
|
||||
{
|
||||
dts_err("parsing NULL Data. ignoring...\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (call->fd < 0)
|
||||
{
|
||||
dts_err("file pointer < 0. ignoring ...\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
uint8_t *Data = call->data;
|
||||
int32_t Size = call->len;
|
||||
|
||||
#ifdef CHECK_FOR_DTS_HD
|
||||
int32_t pos = 0;
|
||||
while ((pos + 4) <= Size)
|
||||
{
|
||||
// check for DTS-HD
|
||||
if (!strcmp((char *)(Data + pos), "\x64\x58\x20\x25"))
|
||||
{
|
||||
Size = pos;
|
||||
break;
|
||||
}
|
||||
++pos;
|
||||
}
|
||||
#endif
|
||||
|
||||
// #define DO_BYTESWAP
|
||||
#ifdef DO_BYTESWAP
|
||||
/* 16-bit byte swap all data before injecting it */
|
||||
for (i = 0; i < Size; i += 2)
|
||||
{
|
||||
uint8_t Tmp = Data[i];
|
||||
Data[i] = Data[i + 1];
|
||||
Data[i + 1] = Tmp;
|
||||
}
|
||||
#endif
|
||||
|
||||
struct iovec iov[2];
|
||||
iov[0].iov_base = PesHeader;
|
||||
iov[0].iov_len = InsertPesHeader(PesHeader, Size, MPEG_AUDIO_PES_START_CODE, call->Pts, 0);
|
||||
iov[1].iov_base = Data;
|
||||
iov[1].iov_len = Size;
|
||||
|
||||
int32_t len = call->WriteV(call->fd, iov, 2);
|
||||
dts_printf(10, "< len %d\n", len);
|
||||
return len;
|
||||
}
|
||||
|
||||
/* ***************************** */
|
||||
/* Writer Definition */
|
||||
/* ***************************** */
|
||||
|
||||
static WriterCaps_t caps =
|
||||
{
|
||||
"dts",
|
||||
eAudio,
|
||||
"A_DTS",
|
||||
AUDIO_ENCODING_DTS,
|
||||
AUDIOTYPE_DTS,
|
||||
-1
|
||||
};
|
||||
|
||||
struct Writer_s WriterAudioDTS =
|
||||
{
|
||||
&reset,
|
||||
&writeData,
|
||||
&caps
|
||||
};
|
488
libeplayer3/output/writer/mipsel/h264.c
Normal file
488
libeplayer3/output/writer/mipsel/h264.c
Normal file
@@ -0,0 +1,488 @@
|
||||
/*
|
||||
* linuxdvb output/writer handling.
|
||||
*
|
||||
* konfetti 2010 based on linuxdvb.c code from libeplayer2
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*
|
||||
*/
|
||||
|
||||
/* ***************************** */
|
||||
/* Includes */
|
||||
/* ***************************** */
|
||||
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
#include <unistd.h>
|
||||
#include <fcntl.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
#include <sys/ioctl.h>
|
||||
#include <sys/uio.h>
|
||||
#include <linux/dvb/video.h>
|
||||
#include <linux/dvb/audio.h>
|
||||
#include <memory.h>
|
||||
#include <asm/types.h>
|
||||
#include <pthread.h>
|
||||
#include <errno.h>
|
||||
#include <assert.h>
|
||||
#include <stdint.h>
|
||||
#include <poll.h>
|
||||
|
||||
#include "stm_ioctls.h"
|
||||
#include "bcm_ioctls.h"
|
||||
|
||||
#include "debug.h"
|
||||
#include "common.h"
|
||||
#include "output.h"
|
||||
#include "debug.h"
|
||||
#include "misc.h"
|
||||
#include "pes.h"
|
||||
#include "writer.h"
|
||||
|
||||
/* ***************************** */
|
||||
/* Makros/Constants */
|
||||
/* ***************************** */
|
||||
|
||||
#define IOVEC_SIZE 128
|
||||
|
||||
/* ***************************** */
|
||||
/* Types */
|
||||
/* ***************************** */
|
||||
|
||||
/* ***************************** */
|
||||
/* Variables */
|
||||
/* ***************************** */
|
||||
|
||||
static unsigned char Head[] = {0, 0, 0, 1};
|
||||
static int initialHeader = 1;
|
||||
static unsigned int NalLengthBytes = 1;
|
||||
static unsigned char *CodecData = NULL;
|
||||
static unsigned int CodecDataLen = 0;
|
||||
static int avc3 = 0;
|
||||
static int sps_pps_in_stream = 0;
|
||||
|
||||
/* ***************************** */
|
||||
/* Prototypes */
|
||||
/* ***************************** */
|
||||
|
||||
/* ***************************** */
|
||||
/* MISC Functions */
|
||||
/* ***************************** */
|
||||
|
||||
// Please see: https://bugzilla.mozilla.org/show_bug.cgi?id=1105771
|
||||
static int32_t UpdateExtraData(uint8_t **ppExtraData, uint32_t *pExtraDataSize, uint8_t *pData, uint32_t dataSize)
|
||||
{
|
||||
uint8_t *aExtraData = *ppExtraData;
|
||||
|
||||
if (aExtraData[0] != 1 || !pData)
|
||||
{
|
||||
// Not AVCC or nothing to update with.
|
||||
return -1;
|
||||
}
|
||||
|
||||
int32_t nalsize = (aExtraData[4] & 3) + 1;
|
||||
|
||||
uint8_t sps[256];
|
||||
uint8_t spsIdx = 0;
|
||||
|
||||
uint8_t numSps = 0;
|
||||
|
||||
uint8_t pps[256];
|
||||
uint8_t ppsIdx = 0;
|
||||
|
||||
uint8_t numPps = 0;
|
||||
|
||||
if (nalsize != 4)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
// Find SPS and PPS NALUs in AVCC data
|
||||
uint8_t *d = pData;
|
||||
while (d + 4 < pData + dataSize)
|
||||
{
|
||||
uint32_t nalLen = ReadUint32(d);
|
||||
|
||||
uint8_t nalType = d[4] & 0x1f;
|
||||
if (nalType == 7)
|
||||
{
|
||||
/* SPS */
|
||||
|
||||
// 16 bits size
|
||||
sps[spsIdx++] = (uint8_t)(0xFF & (nalLen >> 8));
|
||||
sps[spsIdx++] = (uint8_t)(0xFF & nalLen);
|
||||
|
||||
if (spsIdx + nalLen >= sizeof(sps))
|
||||
{
|
||||
h264_err("SPS no free space to copy...\n");
|
||||
return -1;
|
||||
}
|
||||
memcpy(&(sps[spsIdx]), d + 4, nalLen);
|
||||
spsIdx += nalLen;
|
||||
|
||||
numSps += 1;
|
||||
|
||||
h264_printf(10, "SPS len[%u]...\n", nalLen);
|
||||
}
|
||||
else if (nalType == 8)
|
||||
{
|
||||
/* PPS */
|
||||
|
||||
// 16 bits size
|
||||
pps[ppsIdx++] = (uint8_t)(0xFF & (nalLen >> 8));
|
||||
pps[ppsIdx++] = (uint8_t)(0xFF & nalLen);
|
||||
|
||||
if (ppsIdx + nalLen >= sizeof(sps))
|
||||
{
|
||||
h264_err("PPS not free space to copy...\n");
|
||||
return -1;
|
||||
}
|
||||
memcpy(&(pps[ppsIdx]), d + 4, nalLen);
|
||||
ppsIdx += nalLen;
|
||||
|
||||
numPps += 1;
|
||||
|
||||
h264_printf(10, "PPS len[%u]...\n", nalLen);
|
||||
}
|
||||
d += 4 + nalLen;
|
||||
}
|
||||
uint32_t idx = 0;
|
||||
*ppExtraData = malloc(7 + spsIdx + ppsIdx);
|
||||
aExtraData = *ppExtraData;
|
||||
aExtraData[idx++] = 0x1; // version
|
||||
aExtraData[idx++] = sps[3]; // profile
|
||||
aExtraData[idx++] = sps[4]; // profile compat
|
||||
aExtraData[idx++] = sps[5]; // level
|
||||
aExtraData[idx++] = 0xff; // nal size - 1
|
||||
|
||||
aExtraData[idx++] = 0xe0 | numSps;
|
||||
if (numSps)
|
||||
{
|
||||
memcpy(&(aExtraData[idx]), sps, spsIdx);
|
||||
idx += spsIdx;
|
||||
}
|
||||
|
||||
aExtraData[idx++] = numPps;
|
||||
if (numPps)
|
||||
{
|
||||
memcpy(&(aExtraData[idx]), pps, ppsIdx);
|
||||
idx += ppsIdx;
|
||||
}
|
||||
|
||||
h264_printf(10, "aExtraData len[%u]...\n", idx);
|
||||
*pExtraDataSize = idx;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int32_t PreparCodecData(unsigned char *data, unsigned int cd_len, unsigned int *NalLength)
|
||||
{
|
||||
h264_printf(10, "H264 check codec data..!\n");
|
||||
int32_t ret = -100;
|
||||
if (data)
|
||||
{
|
||||
unsigned char tmp[2048];
|
||||
unsigned int tmp_len = 0;
|
||||
|
||||
unsigned int cd_pos = 0;
|
||||
h264_printf(10, "H264 have codec data..!\n");
|
||||
if (cd_len > 7 && data[0] == 1)
|
||||
{
|
||||
unsigned short len = (data[6] << 8) | data[7];
|
||||
if (cd_len >= (uint32_t)(len + 8))
|
||||
{
|
||||
unsigned int i = 0;
|
||||
uint8_t profile_num[] = { 66, 77, 88, 100 };
|
||||
uint8_t profile_cmp[2] = { 0x67, 0x00 };
|
||||
const char *profile_str[] = { "baseline", "main", "extended", "high" };
|
||||
/* avoid compiler warning */
|
||||
if (*profile_str) {}
|
||||
memcpy(tmp, Head, sizeof(Head));
|
||||
tmp_len += 4;
|
||||
memcpy(tmp + tmp_len, data + 8, len);
|
||||
for (i = 0; i < 4; ++i)
|
||||
{
|
||||
profile_cmp[1] = profile_num[i];
|
||||
if (!memcmp(tmp + tmp_len, profile_cmp, 2))
|
||||
{
|
||||
uint8_t level_org = tmp[tmp_len + 3];
|
||||
if (level_org > 0x29)
|
||||
{
|
||||
h264_printf(10, "H264 %s profile@%d.%d patched down to 4.1!", profile_str[i], level_org / 10, level_org % 10);
|
||||
tmp[tmp_len + 3] = 0x29; // level 4.1
|
||||
}
|
||||
else
|
||||
{
|
||||
h264_printf(10, "H264 %s profile@%d.%d", profile_str[i], level_org / 10, level_org % 10);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
tmp_len += len;
|
||||
cd_pos = 8 + len;
|
||||
if (cd_len > (cd_pos + 2))
|
||||
{
|
||||
len = (data[cd_pos + 1] << 8) | data[cd_pos + 2];
|
||||
cd_pos += 3;
|
||||
if (cd_len >= (cd_pos + len))
|
||||
{
|
||||
memcpy(tmp + tmp_len, "\x00\x00\x00\x01", 4);
|
||||
tmp_len += 4;
|
||||
memcpy(tmp + tmp_len, data + cd_pos, len);
|
||||
tmp_len += len;
|
||||
|
||||
CodecData = malloc(tmp_len);
|
||||
memcpy(CodecData, tmp, tmp_len);
|
||||
CodecDataLen = tmp_len;
|
||||
|
||||
*NalLength = (data[4] & 0x03) + 1;
|
||||
ret = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
h264_printf(10, "codec_data too short(4)");
|
||||
ret = -4;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
h264_printf(10, "codec_data too short(3)");
|
||||
ret = -3;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
h264_printf(10, "codec_data too short(2)");
|
||||
ret = -2;
|
||||
}
|
||||
}
|
||||
else if (cd_len <= 7)
|
||||
{
|
||||
h264_printf(10, "codec_data too short(1)");
|
||||
ret = -1;
|
||||
}
|
||||
else
|
||||
{
|
||||
h264_printf(10, "wrong avcC version %d!", data[0]);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
*NalLength = 0;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int reset()
|
||||
{
|
||||
initialHeader = 1;
|
||||
avc3 = 0;
|
||||
sps_pps_in_stream = 0;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int writeData(WriterAVCallData_t *call)
|
||||
{
|
||||
unsigned char PesHeader[PES_MAX_HEADER_SIZE];
|
||||
unsigned long long int VideoPts;
|
||||
unsigned int TimeDelta;
|
||||
unsigned int TimeScale;
|
||||
unsigned int len = 0;
|
||||
int ic = 0;
|
||||
struct iovec iov[IOVEC_SIZE];
|
||||
h264_printf(20, "\n");
|
||||
|
||||
if (call == NULL)
|
||||
{
|
||||
h264_err("call data is NULL...\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
TimeDelta = call->FrameRate;
|
||||
TimeScale = call->FrameScale;
|
||||
/* avoid compiler warnings */
|
||||
if (TimeDelta) {}
|
||||
if (TimeScale) {}
|
||||
VideoPts = call->Pts;
|
||||
|
||||
h264_printf(20, "VideoPts %lld - %d %d\n", call->Pts, TimeDelta, TimeScale);
|
||||
|
||||
if ((call->data == NULL) || (call->len <= 0))
|
||||
{
|
||||
h264_err("NULL Data. ignoring...\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (call->fd < 0)
|
||||
{
|
||||
h264_err("file pointer < 0. ignoring ...\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* AnnexA */
|
||||
if (!avc3 && ((1 < call->private_size && 0 == call->private_data[0]) ||
|
||||
((call->len > 3) && ((call->data[0] == 0x00 && call->data[1] == 0x00 && call->data[2] == 0x00 && call->data[3] == 0x01) ||
|
||||
(call->data[0] == 0xff && call->data[1] == 0xff && call->data[2] == 0xff && call->data[3] == 0xff)))))
|
||||
{
|
||||
uint32_t i = 0;
|
||||
uint8_t InsertPrivData = !sps_pps_in_stream;
|
||||
uint32_t PacketLength = 0;
|
||||
uint32_t FakeStartCode = (call->Version << 8) | PES_VERSION_FAKE_START_CODE;
|
||||
iov[ic++].iov_base = PesHeader;
|
||||
|
||||
while (InsertPrivData && i < 36 && (call->len - i) > 5)
|
||||
{
|
||||
if ((call->data[i] == 0x00 && call->data[i + 1] == 0x00 && call->data[i + 2] == 0x00 && call->data[i + 3] == 0x01 && (call->data[i + 4] == 0x67 || call->data[i + 4] == 0x68)))
|
||||
{
|
||||
InsertPrivData = 0;
|
||||
sps_pps_in_stream = 1;
|
||||
}
|
||||
i += 1;
|
||||
}
|
||||
|
||||
if (InsertPrivData && call->private_size > 0 /*&& initialHeader*/) // some rtsp streams can update codec data at runtime
|
||||
{
|
||||
initialHeader = 0;
|
||||
iov[ic].iov_base = call->private_data;
|
||||
iov[ic++].iov_len = call->private_size;
|
||||
PacketLength += call->private_size;
|
||||
}
|
||||
|
||||
iov[ic].iov_base = call->data;
|
||||
iov[ic++].iov_len = call->len;
|
||||
PacketLength += call->len;
|
||||
|
||||
iov[0].iov_len = InsertPesHeader(PesHeader, -1, MPEG_VIDEO_PES_START_CODE, VideoPts, FakeStartCode);
|
||||
|
||||
return call->WriteV(call->fd, iov, ic);
|
||||
}
|
||||
else if (!call->private_data || call->private_size < 7 || 1 != call->private_data[0])
|
||||
{
|
||||
h264_err("No valid private data available! [%d]\n", (int)call->private_size);
|
||||
return 0;
|
||||
}
|
||||
|
||||
uint32_t PacketLength = 0;
|
||||
|
||||
ic = 0;
|
||||
iov[ic++].iov_base = PesHeader;
|
||||
|
||||
if (!avc3)
|
||||
{
|
||||
if (CodecData)
|
||||
{
|
||||
free(CodecData);
|
||||
CodecData = NULL;
|
||||
}
|
||||
|
||||
uint8_t *private_data = call->private_data;
|
||||
uint32_t private_size = call->private_size;
|
||||
|
||||
if (PreparCodecData(private_data, private_size, &NalLengthBytes))
|
||||
{
|
||||
UpdateExtraData(&private_data, &private_size, call->data, call->len);
|
||||
PreparCodecData(private_data, private_size, &NalLengthBytes);
|
||||
}
|
||||
|
||||
if (private_data != call->private_data)
|
||||
{
|
||||
avc3 = 1;
|
||||
free(private_data);
|
||||
private_data = NULL;
|
||||
}
|
||||
|
||||
if (CodecData != NULL)
|
||||
{
|
||||
iov[ic].iov_base = CodecData;
|
||||
iov[ic++].iov_len = CodecDataLen;
|
||||
PacketLength += CodecDataLen;
|
||||
initialHeader = 0;
|
||||
}
|
||||
}
|
||||
|
||||
if (CodecData != NULL)
|
||||
{
|
||||
uint32_t pos = 0;
|
||||
do
|
||||
{
|
||||
if (ic >= IOVEC_SIZE)
|
||||
{
|
||||
h264_err(">> Drop data due to ic overflow\n");
|
||||
break;
|
||||
}
|
||||
|
||||
uint32_t pack_len = 0;
|
||||
uint32_t i = 0;
|
||||
for (i = 0; i < NalLengthBytes; i++, pos++)
|
||||
{
|
||||
pack_len <<= 8;
|
||||
pack_len += call->data[pos];
|
||||
}
|
||||
|
||||
if ((pos + pack_len) > call->len)
|
||||
{
|
||||
pack_len = call->len - pos;
|
||||
}
|
||||
|
||||
iov[ic].iov_base = Head;
|
||||
iov[ic++].iov_len = sizeof(Head);
|
||||
PacketLength += sizeof(Head);
|
||||
|
||||
iov[ic].iov_base = call->data + pos;
|
||||
iov[ic++].iov_len = pack_len;
|
||||
PacketLength += pack_len;
|
||||
|
||||
pos += pack_len;
|
||||
|
||||
}
|
||||
while ((pos + NalLengthBytes) < call->len);
|
||||
|
||||
h264_printf(10, "<<<< PacketLength [%d]\n", PacketLength);
|
||||
iov[0].iov_len = InsertPesHeader(PesHeader, -1, MPEG_VIDEO_PES_START_CODE, VideoPts, 0);
|
||||
|
||||
len = call->WriteV(call->fd, iov, ic);
|
||||
PacketLength += iov[0].iov_len;
|
||||
if (PacketLength != len)
|
||||
{
|
||||
h264_err("<<<< not all data have been written [%d/%d]\n", len, PacketLength);
|
||||
}
|
||||
}
|
||||
|
||||
h264_printf(10, "< len %d\n", len);
|
||||
return len;
|
||||
}
|
||||
|
||||
/* ***************************** */
|
||||
/* Writer Definition */
|
||||
/* ***************************** */
|
||||
|
||||
static WriterCaps_t caps =
|
||||
{
|
||||
"h264",
|
||||
eVideo,
|
||||
"V_MPEG4/ISO/AVC",
|
||||
VIDEO_ENCODING_H264,
|
||||
STREAMTYPE_MPEG4_H264,
|
||||
CT_H264
|
||||
};
|
||||
|
||||
struct Writer_s WriterVideoH264 =
|
||||
{
|
||||
&reset,
|
||||
&writeData,
|
||||
&caps
|
||||
};
|
324
libeplayer3/output/writer/mipsel/h265.c
Normal file
324
libeplayer3/output/writer/mipsel/h265.c
Normal file
@@ -0,0 +1,324 @@
|
||||
/*
|
||||
* linuxdvb output/writer handling.
|
||||
*
|
||||
* konfetti 2010 based on linuxdvb.c code from libeplayer2
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*
|
||||
*/
|
||||
|
||||
/* ***************************** */
|
||||
/* Includes */
|
||||
/* ***************************** */
|
||||
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
#include <unistd.h>
|
||||
#include <fcntl.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
#include <sys/ioctl.h>
|
||||
#include <sys/uio.h>
|
||||
#include <linux/dvb/video.h>
|
||||
#include <linux/dvb/audio.h>
|
||||
#include <memory.h>
|
||||
#include <asm/types.h>
|
||||
#include <pthread.h>
|
||||
#include <errno.h>
|
||||
#include <assert.h>
|
||||
#include <stdint.h>
|
||||
#include <poll.h>
|
||||
|
||||
#include "stm_ioctls.h"
|
||||
#include "bcm_ioctls.h"
|
||||
|
||||
#include "common.h"
|
||||
#include "output.h"
|
||||
#include "debug.h"
|
||||
#include "misc.h"
|
||||
#include "pes.h"
|
||||
#include "writer.h"
|
||||
|
||||
/* ***************************** */
|
||||
/* Makros/Constants */
|
||||
/* ***************************** */
|
||||
|
||||
#define IOVEC_SIZE 128
|
||||
|
||||
/* ***************************** */
|
||||
/* Types */
|
||||
/* ***************************** */
|
||||
|
||||
/* ***************************** */
|
||||
/* Variables */
|
||||
/* ***************************** */
|
||||
|
||||
static unsigned char Head[] = {0, 0, 0, 1};
|
||||
static int initialHeader = 1;
|
||||
static unsigned int NalLengthBytes = 1;
|
||||
static unsigned char *CodecData = NULL;
|
||||
static unsigned int CodecDataLen = 0;
|
||||
|
||||
/* ***************************** */
|
||||
/* Prototypes */
|
||||
/* ***************************** */
|
||||
|
||||
/* ***************************** */
|
||||
/* MISC Functions */
|
||||
/* ***************************** */
|
||||
|
||||
static int32_t PreparCodecData(unsigned char *data, unsigned int cd_len, unsigned int *NalLength)
|
||||
{
|
||||
h265_printf(10, "H265 check codec data..!\n");
|
||||
int32_t ret = -100;
|
||||
if (data)
|
||||
{
|
||||
unsigned char tmp[4096];
|
||||
unsigned int tmp_len = 0;
|
||||
|
||||
h265_printf(10, "H265 have codec data..!");
|
||||
|
||||
if (cd_len > 3 && (data[0] || data[1] || data[2] > 1))
|
||||
{
|
||||
if (cd_len > 22)
|
||||
{
|
||||
int i;
|
||||
if (data[0] != 0)
|
||||
{
|
||||
h265_printf(10, "Unsupported extra data version %d, decoding may fail", (int)data[0]);
|
||||
}
|
||||
|
||||
*NalLength = (data[21] & 3) + 1;
|
||||
int num_param_sets = data[22];
|
||||
uint32_t pos = 23;
|
||||
for (i = 0; i < num_param_sets; i++)
|
||||
{
|
||||
int j;
|
||||
if (pos + 3 > cd_len)
|
||||
{
|
||||
h265_printf(10, "Buffer underrun in extra header (%d >= %u)", pos + 3, cd_len);
|
||||
break;
|
||||
}
|
||||
// ignore flags + NAL type (1 byte)
|
||||
int nal_count = data[pos + 1] << 8 | data[pos + 2];
|
||||
pos += 3;
|
||||
for (j = 0; j < nal_count; j++)
|
||||
{
|
||||
if (pos + 2 > cd_len)
|
||||
{
|
||||
h265_printf(10, "Buffer underrun in extra nal header (%d >= %u)", pos + 2, cd_len);
|
||||
break;
|
||||
}
|
||||
int nal_size = data[pos] << 8 | data[pos + 1];
|
||||
pos += 2;
|
||||
if (pos + nal_size > cd_len)
|
||||
{
|
||||
h265_printf(10, "Buffer underrun in extra nal (%d >= %u)", pos + 2 + nal_size, cd_len);
|
||||
break;
|
||||
}
|
||||
memcpy(tmp + tmp_len, "\x00\x00\x00\x01", 4);
|
||||
tmp_len += 4;
|
||||
memcpy(tmp + tmp_len, data + pos, nal_size);
|
||||
tmp_len += nal_size;
|
||||
pos += nal_size;
|
||||
}
|
||||
}
|
||||
|
||||
CodecData = malloc(tmp_len);
|
||||
memcpy(CodecData, tmp, tmp_len);
|
||||
CodecDataLen = tmp_len;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
*NalLength = 0;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int reset()
|
||||
{
|
||||
initialHeader = 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int writeData(WriterAVCallData_t *call)
|
||||
{
|
||||
unsigned char PesHeader[PES_MAX_HEADER_SIZE];
|
||||
unsigned long long int VideoPts;
|
||||
unsigned int TimeDelta;
|
||||
unsigned int TimeScale;
|
||||
unsigned int len = 0;
|
||||
int ic = 0;
|
||||
struct iovec iov[IOVEC_SIZE];
|
||||
h265_printf(20, "\n");
|
||||
|
||||
if (call == NULL)
|
||||
{
|
||||
h264_err("call data is NULL...\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
TimeDelta = call->FrameRate;
|
||||
TimeScale = call->FrameScale;
|
||||
/* avoid compiler warnings */
|
||||
if (TimeDelta) {}
|
||||
if (TimeScale) {}
|
||||
VideoPts = call->Pts;
|
||||
|
||||
h265_printf(20, "VideoPts %lld - %d %d\n", call->Pts, TimeDelta, TimeScale);
|
||||
|
||||
if ((call->data == NULL) || (call->len <= 0))
|
||||
{
|
||||
h264_err("NULL Data. ignoring...\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (call->fd < 0)
|
||||
{
|
||||
h264_err("file pointer < 0. ignoring ...\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (call->InfoFlags & 0x1) // TS container
|
||||
{
|
||||
h265_printf(10, "H265 simple inject method!\n");
|
||||
uint32_t PacketLength = 0;
|
||||
uint32_t FakeStartCode = (call->Version << 8) | PES_VERSION_FAKE_START_CODE;
|
||||
|
||||
iov[ic++].iov_base = PesHeader;
|
||||
initialHeader = 0;
|
||||
if (initialHeader)
|
||||
{
|
||||
initialHeader = 0;
|
||||
iov[ic].iov_base = call->private_data;
|
||||
iov[ic++].iov_len = call->private_size;
|
||||
PacketLength += call->private_size;
|
||||
}
|
||||
|
||||
iov[ic].iov_base = "";
|
||||
iov[ic++].iov_len = 1;
|
||||
|
||||
iov[ic].iov_base = call->data;
|
||||
iov[ic++].iov_len = call->len;
|
||||
PacketLength += call->len;
|
||||
|
||||
iov[0].iov_len = InsertPesHeader(PesHeader, -1, MPEG_VIDEO_PES_START_CODE, VideoPts, FakeStartCode);
|
||||
|
||||
return call->WriteV(call->fd, iov, ic);
|
||||
}
|
||||
|
||||
uint32_t PacketLength = 0;
|
||||
|
||||
ic = 0;
|
||||
iov[ic++].iov_base = PesHeader;
|
||||
|
||||
if (initialHeader)
|
||||
{
|
||||
if (CodecData)
|
||||
{
|
||||
free(CodecData);
|
||||
CodecData = NULL;
|
||||
}
|
||||
|
||||
uint8_t *private_data = call->private_data;
|
||||
uint32_t private_size = call->private_size;
|
||||
|
||||
PreparCodecData(private_data, private_size, &NalLengthBytes);
|
||||
|
||||
if (CodecData != NULL)
|
||||
{
|
||||
iov[ic].iov_base = CodecData;
|
||||
iov[ic++].iov_len = CodecDataLen;
|
||||
PacketLength += CodecDataLen;
|
||||
initialHeader = 0;
|
||||
}
|
||||
}
|
||||
|
||||
if (CodecData != NULL)
|
||||
{
|
||||
uint32_t pos = 0;
|
||||
do
|
||||
{
|
||||
if (ic >= IOVEC_SIZE)
|
||||
{
|
||||
h264_err(">> Drop data due to ic overflow\n");
|
||||
break;
|
||||
}
|
||||
|
||||
uint32_t pack_len = 0;
|
||||
uint32_t i = 0;
|
||||
for (i = 0; i < NalLengthBytes; i++, pos++)
|
||||
{
|
||||
pack_len <<= 8;
|
||||
pack_len += call->data[pos];
|
||||
}
|
||||
|
||||
if ((pos + pack_len) > call->len)
|
||||
{
|
||||
pack_len = call->len - pos;
|
||||
}
|
||||
|
||||
iov[ic].iov_base = Head;
|
||||
iov[ic++].iov_len = sizeof(Head);
|
||||
PacketLength += sizeof(Head);
|
||||
|
||||
iov[ic].iov_base = call->data + pos;
|
||||
iov[ic++].iov_len = pack_len;
|
||||
PacketLength += pack_len;
|
||||
|
||||
pos += pack_len;
|
||||
|
||||
}
|
||||
while ((pos + NalLengthBytes) < call->len);
|
||||
|
||||
h265_printf(10, "<<<< PacketLength [%d]\n", PacketLength);
|
||||
iov[0].iov_len = InsertPesHeader(PesHeader, -1, MPEG_VIDEO_PES_START_CODE, VideoPts, 0);
|
||||
|
||||
len = call->WriteV(call->fd, iov, ic);
|
||||
PacketLength += iov[0].iov_len;
|
||||
if (PacketLength != len)
|
||||
{
|
||||
h264_err("<<<< not all data have been written [%d/%d]\n", len, PacketLength);
|
||||
}
|
||||
}
|
||||
|
||||
h265_printf(10, "< len %d\n", len);
|
||||
return len;
|
||||
}
|
||||
|
||||
/* ***************************** */
|
||||
/* Writer Definition */
|
||||
/* ***************************** */
|
||||
|
||||
static WriterCaps_t caps =
|
||||
{
|
||||
"h265",
|
||||
eVideo,
|
||||
"V_HEVC",
|
||||
-1,
|
||||
STREAMTYPE_MPEG4_H265,
|
||||
CT_H265
|
||||
};
|
||||
|
||||
struct Writer_s WriterVideoH265 =
|
||||
{
|
||||
&reset,
|
||||
&writeData,
|
||||
&caps
|
||||
};
|
263
libeplayer3/output/writer/mipsel/lpcm.c
Normal file
263
libeplayer3/output/writer/mipsel/lpcm.c
Normal file
@@ -0,0 +1,263 @@
|
||||
/*
|
||||
* linuxdvb output/writer handling.
|
||||
*
|
||||
* konfetti 2010 based on linuxdvb.c code from libeplayer2
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*
|
||||
*/
|
||||
|
||||
/* ***************************** */
|
||||
/* Includes */
|
||||
/* ***************************** */
|
||||
|
||||
#define _XOPEN_SOURCE
|
||||
#include <unistd.h>
|
||||
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
#include <fcntl.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
#include <sys/ioctl.h>
|
||||
#include <sys/uio.h>
|
||||
#include <linux/dvb/video.h>
|
||||
#include <linux/dvb/audio.h>
|
||||
#include <memory.h>
|
||||
#include <asm/types.h>
|
||||
#include <pthread.h>
|
||||
#include <errno.h>
|
||||
|
||||
#include <libavcodec/avcodec.h>
|
||||
|
||||
#include "stm_ioctls.h"
|
||||
#include "bcm_ioctls.h"
|
||||
|
||||
#include "common.h"
|
||||
#include "output.h"
|
||||
#include "debug.h"
|
||||
#include "misc.h"
|
||||
#include "pes.h"
|
||||
#include "writer.h"
|
||||
#include "pcm.h"
|
||||
|
||||
/* ***************************** */
|
||||
/* Makros/Constants */
|
||||
/* ***************************** */
|
||||
|
||||
#define LLPCM_VOB_HEADER_LEN (6)
|
||||
|
||||
/* ***************************** */
|
||||
/* Types */
|
||||
/* ***************************** */
|
||||
|
||||
/* ***************************** */
|
||||
/* Variables */
|
||||
/* ***************************** */
|
||||
|
||||
static uint8_t PesHeader[PES_MAX_HEADER_SIZE];
|
||||
static uint8_t initialHeader = 1;
|
||||
|
||||
static uint8_t i_freq_code = 0;
|
||||
static int32_t i_frame_samples;
|
||||
static int32_t i_frame_size;
|
||||
static int32_t i_buffer_used;
|
||||
static int32_t i_frame_num;
|
||||
static int32_t i_bitspersample;
|
||||
static uint8_t *p_buffer = 0;
|
||||
static uint8_t *p_frame_buffer = 0;
|
||||
/* ***************************** */
|
||||
/* Prototypes */
|
||||
/* ***************************** */
|
||||
|
||||
/* ***************************** */
|
||||
/* MISC Functions */
|
||||
/* ***************************** */
|
||||
|
||||
/* https://www.videolan.org/developers/vlc/modules/codec/lpcm.c
|
||||
* LPCM DVD header :
|
||||
* - number of frames in this packet (8 bits)
|
||||
* - first access unit (16 bits) == 0x0003 ?
|
||||
* - emphasis (1 bit)
|
||||
* - mute (1 bit)
|
||||
* - reserved (1 bit)
|
||||
* - current frame (5 bits)
|
||||
* - quantisation (2 bits) 0 == 16bps, 1 == 20bps, 2 == 24bps, 3 == illegal
|
||||
* - frequency (2 bits) 0 == 48 kHz, 1 == 96 kHz, 2 == 44.1 kHz, 3 == 32 kHz
|
||||
* - reserved (1 bit)
|
||||
* - number of channels - 1 (3 bits) 1 == 2 channels
|
||||
* - dynamic range (8 bits) 0x80 == neutral
|
||||
*/
|
||||
|
||||
static int32_t reset()
|
||||
{
|
||||
initialHeader = 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int writeData(WriterAVCallData_t *call)
|
||||
{
|
||||
lpcm_printf(10, "\n");
|
||||
|
||||
if (!call)
|
||||
{
|
||||
lpcm_err("call data is NULL...\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
lpcm_printf(10, "AudioPts %lld\n", call->Pts);
|
||||
|
||||
if (!call->data || (call->len <= 0))
|
||||
{
|
||||
lpcm_err("parsing NULL Data. ignoring...\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (call->fd < 0)
|
||||
{
|
||||
lpcm_err("file pointer < 0. ignoring ...\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
pcmPrivateData_t *pcmPrivateData = (pcmPrivateData_t *)call->private_data;
|
||||
|
||||
int32_t i_rate = (int32_t)pcmPrivateData->sample_rate;
|
||||
int32_t i_channels = (int32_t)pcmPrivateData->channels;
|
||||
int32_t i_nb_samples = call->len / (i_channels * 2);
|
||||
int32_t i_ret_size = 0;
|
||||
if (i_channels > 8)
|
||||
{
|
||||
lpcm_err("Error DVD LPCM supports a maximum of eight channels i_channels[%d]\n", i_channels);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (pcmPrivateData->bResampling || NULL == p_buffer)
|
||||
{
|
||||
lpcm_printf(1, "i_rate: [%d]\n", i_rate);
|
||||
lpcm_printf(1, "i_channels: [%d]\n", i_channels);
|
||||
switch (i_rate)
|
||||
{
|
||||
case 48000:
|
||||
i_freq_code = 0;
|
||||
break;
|
||||
case 96000:
|
||||
i_freq_code = 1;
|
||||
break;
|
||||
case 44100:
|
||||
i_freq_code = 2;
|
||||
break;
|
||||
case 32000:
|
||||
i_freq_code = 3;
|
||||
break;
|
||||
default:
|
||||
lpcm_err("Error DVD LPCM sample_rate not supported [%d]\n", i_rate);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* In DVD LCPM, a frame is always 150 PTS ticks. */
|
||||
i_frame_samples = i_rate * 150 / 90000;
|
||||
i_frame_size = i_frame_samples * i_channels * 2 + LLPCM_VOB_HEADER_LEN;
|
||||
if (NULL != p_buffer)
|
||||
{
|
||||
free(p_buffer);
|
||||
}
|
||||
p_buffer = malloc(i_frame_samples * i_channels * 16);
|
||||
|
||||
if (NULL != p_frame_buffer)
|
||||
{
|
||||
free(p_frame_buffer);
|
||||
}
|
||||
p_frame_buffer = malloc(i_frame_size);
|
||||
i_buffer_used = 0;
|
||||
i_frame_num = 0;
|
||||
i_bitspersample = 16;
|
||||
}
|
||||
|
||||
const int i_num_frames = (i_buffer_used + i_nb_samples) / i_frame_samples;
|
||||
const int i_leftover_samples = (i_buffer_used + i_nb_samples) % i_frame_samples;
|
||||
const int i_start_offset = -i_buffer_used;
|
||||
|
||||
int32_t i_bytes_consumed = 0;
|
||||
int32_t i = 0;
|
||||
for (i = 0; i < i_num_frames; ++i)
|
||||
{
|
||||
uint8_t *frame = (uint8_t *)p_frame_buffer;
|
||||
frame[0] = 1; /* one frame in packet */
|
||||
frame[1] = 0;
|
||||
frame[2] = 0; /* no first access unit */
|
||||
frame[3] = (i_frame_num + i) & 0x1f; /* no emphasis, no mute */
|
||||
frame[4] = (i_freq_code << 4) | (i_channels - 1);
|
||||
frame[5] = 0x80; /* neutral dynamic range */
|
||||
|
||||
const int i_consume_samples = i_frame_samples - i_buffer_used;
|
||||
const int i_kept_bytes = i_buffer_used * i_channels * 2;
|
||||
const int i_consume_bytes = i_consume_samples * i_channels * 2;
|
||||
|
||||
#ifdef WORDS_BIGENDIAN
|
||||
memcpy(frame + 6, p_buffer, i_kept_bytes);
|
||||
memcpy(frame + 6 + i_kept_bytes, call->data + i_bytes_consumed, i_consume_bytes);
|
||||
#else
|
||||
swab(p_buffer, frame + 6, i_kept_bytes);
|
||||
swab(call->data + i_bytes_consumed, frame + 6 + i_kept_bytes, i_consume_bytes);
|
||||
#endif
|
||||
|
||||
i_frame_num++;
|
||||
i_buffer_used = 0;
|
||||
i_bytes_consumed += i_consume_bytes;
|
||||
|
||||
/* We need to find i_length by means of next_pts due to possible roundoff errors. */
|
||||
uint64_t this_pts = call->Pts + (i * i_frame_samples + i_start_offset) * 90000 / i_rate;
|
||||
|
||||
uint32_t pes_header_size = 0;
|
||||
pes_header_size = InsertPesHeader(PesHeader, i_frame_size + 1, MPEG_AUDIO_PES_START_CODE, this_pts, 0);
|
||||
|
||||
PesHeader[pes_header_size] = 0xa0;
|
||||
pes_header_size += 1;
|
||||
|
||||
struct iovec iov[2];
|
||||
iov[0].iov_base = PesHeader;
|
||||
iov[0].iov_len = pes_header_size;
|
||||
iov[1].iov_base = frame;
|
||||
iov[1].iov_len = i_frame_size;
|
||||
i_ret_size += call->WriteV(call->fd, iov, 2);
|
||||
}
|
||||
|
||||
memcpy(p_buffer, call->data + i_bytes_consumed, i_leftover_samples * i_channels * 2);
|
||||
i_buffer_used = i_leftover_samples;
|
||||
|
||||
return i_ret_size;
|
||||
}
|
||||
|
||||
/* ***************************** */
|
||||
/* Writer Definition */
|
||||
/* ***************************** */
|
||||
|
||||
static WriterCaps_t caps_lpcm =
|
||||
{
|
||||
"ipcm",
|
||||
eAudio,
|
||||
"A_LPCM",
|
||||
AUDIO_ENCODING_LPCMA,
|
||||
AUDIOTYPE_LPCM,
|
||||
-1
|
||||
};
|
||||
|
||||
struct Writer_s WriterAudioLPCM =
|
||||
{
|
||||
&reset,
|
||||
&writeData, /* writeDataLPCM */
|
||||
&caps_lpcm
|
||||
};
|
125
libeplayer3/output/writer/mipsel/mjpeg.c
Executable file
125
libeplayer3/output/writer/mipsel/mjpeg.c
Executable file
@@ -0,0 +1,125 @@
|
||||
/*
|
||||
* linuxdvb output/writer handling.
|
||||
*
|
||||
* konfetti 2010 based on linuxdvb.c code from libeplayer2
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*
|
||||
*/
|
||||
|
||||
/* ***************************** */
|
||||
/* Includes */
|
||||
/* ***************************** */
|
||||
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
#include <unistd.h>
|
||||
#include <fcntl.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
#include <sys/ioctl.h>
|
||||
#include <sys/uio.h>
|
||||
#include <linux/dvb/video.h>
|
||||
#include <linux/dvb/audio.h>
|
||||
#include <memory.h>
|
||||
#include <asm/types.h>
|
||||
#include <pthread.h>
|
||||
#include <errno.h>
|
||||
|
||||
#include "stm_ioctls.h"
|
||||
#include "bcm_ioctls.h"
|
||||
|
||||
#include "debug.h"
|
||||
#include "common.h"
|
||||
#include "output.h"
|
||||
#include "debug.h"
|
||||
#include "misc.h"
|
||||
#include "pes.h"
|
||||
#include "writer.h"
|
||||
|
||||
/* ***************************** */
|
||||
/* Makros/Constants */
|
||||
/* ***************************** */
|
||||
|
||||
/* ***************************** */
|
||||
/* Types */
|
||||
/* ***************************** */
|
||||
|
||||
/* ***************************** */
|
||||
/* Variables */
|
||||
/* ***************************** */
|
||||
|
||||
static bool must_send_header = true;
|
||||
|
||||
/* ***************************** */
|
||||
/* Prototypes */
|
||||
/* ***************************** */
|
||||
|
||||
/* ***************************** */
|
||||
/* MISC Functions */
|
||||
/* ***************************** */
|
||||
|
||||
static int reset()
|
||||
{
|
||||
must_send_header = true;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int writeData(WriterAVCallData_t *call)
|
||||
{
|
||||
static uint8_t PesHeader[PES_MAX_HEADER_SIZE];
|
||||
|
||||
mjpeg_printf(10, "\n");
|
||||
|
||||
if (call == NULL)
|
||||
{
|
||||
mjpeg_err("call data is NULL...\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
mjpeg_printf(10, "VideoPts %lld\n", call->Pts);
|
||||
|
||||
struct iovec iov[2];
|
||||
|
||||
iov[0].iov_base = PesHeader;
|
||||
iov[0].iov_len = InsertPesHeader(PesHeader, call->len, MPEG_VIDEO_PES_START_CODE, call->Pts, 0);
|
||||
|
||||
iov[1].iov_base = call->data;
|
||||
iov[1].iov_len = call->len;
|
||||
|
||||
return call->WriteV(call->fd, iov, 2);;
|
||||
}
|
||||
|
||||
/* ***************************** */
|
||||
/* Writer Definition */
|
||||
/* ***************************** */
|
||||
|
||||
static WriterCaps_t caps =
|
||||
{
|
||||
"mjpeg",
|
||||
eVideo,
|
||||
"V_MJPEG",
|
||||
VIDEO_ENCODING_AUTO,
|
||||
STREAMTYPE_MJPEG,
|
||||
-1
|
||||
};
|
||||
|
||||
struct Writer_s WriterVideoMJPEG =
|
||||
{
|
||||
&reset,
|
||||
&writeData,
|
||||
&caps
|
||||
};
|
176
libeplayer3/output/writer/mipsel/mp3.c
Normal file
176
libeplayer3/output/writer/mipsel/mp3.c
Normal file
@@ -0,0 +1,176 @@
|
||||
/*
|
||||
* linuxdvb output/writer handling.
|
||||
*
|
||||
* konfetti 2010 based on linuxdvb.c code from libeplayer2
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*
|
||||
*/
|
||||
|
||||
/* ***************************** */
|
||||
/* Includes */
|
||||
/* ***************************** */
|
||||
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
#include <unistd.h>
|
||||
#include <fcntl.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
#include <sys/ioctl.h>
|
||||
#include <sys/uio.h>
|
||||
#include <linux/dvb/video.h>
|
||||
#include <linux/dvb/audio.h>
|
||||
#include <memory.h>
|
||||
#include <asm/types.h>
|
||||
#include <pthread.h>
|
||||
#include <errno.h>
|
||||
|
||||
#include "stm_ioctls.h"
|
||||
#include "bcm_ioctls.h"
|
||||
|
||||
#include "common.h"
|
||||
#include "output.h"
|
||||
#include "debug.h"
|
||||
#include "misc.h"
|
||||
#include "pes.h"
|
||||
#include "writer.h"
|
||||
|
||||
/* ***************************** */
|
||||
/* Makros/Constants */
|
||||
/* ***************************** */
|
||||
|
||||
/* ***************************** */
|
||||
/* Types */
|
||||
/* ***************************** */
|
||||
|
||||
/* ***************************** */
|
||||
/* Variables */
|
||||
/* ***************************** */
|
||||
|
||||
/* ***************************** */
|
||||
/* Prototypes */
|
||||
/* ***************************** */
|
||||
|
||||
/* ***************************** */
|
||||
/* MISC Functions */
|
||||
/* ***************************** */
|
||||
|
||||
static int reset()
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int writeData(WriterAVCallData_t *call)
|
||||
{
|
||||
unsigned char PesHeader[PES_MAX_HEADER_SIZE + 22];
|
||||
|
||||
mp3_printf(10, "\n");
|
||||
|
||||
if (call == NULL)
|
||||
{
|
||||
mp3_err("call data is NULL...\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
mp3_printf(10, "AudioPts %lld\n", call->Pts);
|
||||
|
||||
if ((call->data == NULL) || (call->len <= 0))
|
||||
{
|
||||
mp3_err("parsing NULL Data. ignoring...\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (call->fd < 0)
|
||||
{
|
||||
mp3_err("file pointer < 0. ignoring ...\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
call->private_size = 0;
|
||||
|
||||
uint32_t headerSize = InsertPesHeader(PesHeader, call->len + call->private_size, MPEG_AUDIO_PES_START_CODE, call->Pts, 0);
|
||||
if (call->private_size > 0)
|
||||
{
|
||||
memcpy(&PesHeader[headerSize], call->private_data, call->private_size);
|
||||
headerSize += call->private_size;
|
||||
}
|
||||
struct iovec iov[2];
|
||||
iov[0].iov_base = PesHeader;
|
||||
iov[0].iov_len = headerSize;
|
||||
iov[1].iov_base = call->data;
|
||||
iov[1].iov_len = call->len;
|
||||
|
||||
int len = call->WriteV(call->fd, iov, 2);
|
||||
|
||||
mp3_printf(10, "mp3_Write-< len=%d\n", len);
|
||||
return len;
|
||||
}
|
||||
|
||||
/* ***************************** */
|
||||
/* Writer Definition */
|
||||
/* ***************************** */
|
||||
|
||||
static WriterCaps_t caps_mp3 =
|
||||
{
|
||||
"mp3",
|
||||
eAudio,
|
||||
"A_MP3",
|
||||
AUDIO_ENCODING_MP3,
|
||||
AUDIOTYPE_MP3,
|
||||
-1
|
||||
};
|
||||
|
||||
struct Writer_s WriterAudioMP3 =
|
||||
{
|
||||
&reset,
|
||||
&writeData,
|
||||
&caps_mp3
|
||||
};
|
||||
|
||||
static WriterCaps_t caps_mpegl3 =
|
||||
{
|
||||
"mpeg/l3",
|
||||
eAudio,
|
||||
"A_MPEG/L3",
|
||||
AUDIO_ENCODING_MPEG2,
|
||||
AUDIOTYPE_MP3,
|
||||
-1
|
||||
};
|
||||
|
||||
struct Writer_s WriterAudioMPEGL3 =
|
||||
{
|
||||
&reset,
|
||||
&writeData,
|
||||
&caps_mpegl3
|
||||
};
|
||||
|
||||
static WriterCaps_t caps_vorbis =
|
||||
{
|
||||
"vorbis",
|
||||
eAudio,
|
||||
"A_VORBIS",
|
||||
AUDIO_ENCODING_VORBIS,
|
||||
AUDIO_ENCODING_MP3,
|
||||
-1
|
||||
};
|
||||
|
||||
struct Writer_s WriterAudioVORBIS =
|
||||
{
|
||||
&reset,
|
||||
&writeData,
|
||||
&caps_vorbis
|
||||
};
|
283
libeplayer3/output/writer/mipsel/mpeg2.c
Normal file
283
libeplayer3/output/writer/mipsel/mpeg2.c
Normal file
@@ -0,0 +1,283 @@
|
||||
/*
|
||||
* linuxdvb output/writer handling.
|
||||
*
|
||||
* konfetti 2010 based on linuxdvb.c code from libeplayer2
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*
|
||||
*/
|
||||
|
||||
/* ***************************** */
|
||||
/* Includes */
|
||||
/* ***************************** */
|
||||
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
#include <unistd.h>
|
||||
#include <fcntl.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
#include <sys/ioctl.h>
|
||||
#include <sys/uio.h>
|
||||
#include <linux/dvb/video.h>
|
||||
#include <linux/dvb/audio.h>
|
||||
#include <memory.h>
|
||||
#include <asm/types.h>
|
||||
#include <pthread.h>
|
||||
#include <errno.h>
|
||||
|
||||
#include "stm_ioctls.h"
|
||||
#include "bcm_ioctls.h"
|
||||
|
||||
#include "common.h"
|
||||
#include "output.h"
|
||||
#include "debug.h"
|
||||
#include "misc.h"
|
||||
#include "pes.h"
|
||||
#include "writer.h"
|
||||
|
||||
/* ***************************** */
|
||||
/* Makros/Constants */
|
||||
/* ***************************** */
|
||||
|
||||
/* ***************************** */
|
||||
/* Types */
|
||||
/* ***************************** */
|
||||
|
||||
/* ***************************** */
|
||||
/* Variables */
|
||||
/* ***************************** */
|
||||
|
||||
static bool must_send_header = true;
|
||||
static uint8_t *private_data = NULL;
|
||||
static uint32_t private_size = 0;
|
||||
|
||||
|
||||
/* ***************************** */
|
||||
/* Prototypes */
|
||||
/* ***************************** */
|
||||
|
||||
/* ***************************** */
|
||||
/* MISC Functions */
|
||||
/* ***************************** */
|
||||
|
||||
static int reset()
|
||||
{
|
||||
must_send_header = true;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int writeData(WriterAVCallData_t *call)
|
||||
{
|
||||
static uint8_t PesHeader[PES_MAX_HEADER_SIZE];
|
||||
|
||||
mpeg2_printf(10, "\n");
|
||||
|
||||
if (call == NULL)
|
||||
{
|
||||
mpeg2_err("call data is NULL...\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
mpeg2_printf(10, "VideoPts %lld\n", call->Pts);
|
||||
|
||||
if ((call->data == NULL) || (call->len <= 0))
|
||||
{
|
||||
mpeg2_err("parsing NULL Data. ignoring...\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (call->fd < 0)
|
||||
{
|
||||
mpeg2_err("file pointer < 0. ignoring ...\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
uint8_t *data = call->data;
|
||||
uint32_t data_len = call->len;
|
||||
|
||||
if (!private_data && !call->private_data && data_len > 3 && !memcmp(data, "\x00\x00\x01\xb3", 4))
|
||||
{
|
||||
bool ok = true;
|
||||
uint32_t pos = 4;
|
||||
uint32_t sheader_data_len = 0;
|
||||
while (pos < data_len && ok)
|
||||
{
|
||||
if (pos >= data_len) break;
|
||||
pos += 7;
|
||||
if (pos >= data_len) break;
|
||||
sheader_data_len = 12;
|
||||
if (data[pos] & 2)
|
||||
{
|
||||
// intra matrix
|
||||
pos += 64;
|
||||
if (pos >= data_len) break;
|
||||
sheader_data_len += 64;
|
||||
}
|
||||
if (data[pos] & 1)
|
||||
{
|
||||
// non intra matrix
|
||||
pos += 64;
|
||||
if (pos >= data_len) break;
|
||||
sheader_data_len += 64;
|
||||
}
|
||||
pos += 1;
|
||||
if (pos + 3 >= data_len) break;
|
||||
if (!memcmp(&data[pos], "\x00\x00\x01\xb5", 4))
|
||||
{
|
||||
// extended start code
|
||||
pos += 3;
|
||||
sheader_data_len += 3;
|
||||
do
|
||||
{
|
||||
pos += 1;
|
||||
++sheader_data_len;
|
||||
if (pos + 2 > data_len)
|
||||
{
|
||||
ok = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
while (memcmp(&data[pos], "\x00\x00\x01", 3));
|
||||
if (!ok) break;
|
||||
}
|
||||
if (pos + 3 >= data_len) break;
|
||||
if (!memcmp(&data[pos], "\x00\x00\x01\xb2", 4))
|
||||
{
|
||||
// private data
|
||||
pos += 3;
|
||||
sheader_data_len += 3;
|
||||
do
|
||||
{
|
||||
pos += 1;
|
||||
++sheader_data_len;
|
||||
if (pos + 2 > data_len)
|
||||
{
|
||||
ok = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
while (memcmp(&data[pos], "\x00\x00\x01", 3));
|
||||
if (!ok) break;
|
||||
}
|
||||
|
||||
free(private_data);
|
||||
private_data = malloc(sheader_data_len);
|
||||
if (private_data)
|
||||
{
|
||||
private_size = sheader_data_len;
|
||||
memcpy(private_data, data + pos - sheader_data_len, sheader_data_len);
|
||||
}
|
||||
must_send_header = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
else if ((private_data || call->private_data) && must_send_header)
|
||||
{
|
||||
uint8_t *codec_data = NULL;
|
||||
uint32_t codec_data_size = 0;
|
||||
int pos = 0;
|
||||
|
||||
if (private_data)
|
||||
{
|
||||
codec_data = private_data;
|
||||
codec_data_size = private_size;
|
||||
}
|
||||
else
|
||||
{
|
||||
codec_data = call->private_data;
|
||||
codec_data_size = call->private_size;
|
||||
}
|
||||
|
||||
while ((unsigned)pos <= data_len - 4)
|
||||
{
|
||||
if (memcmp(&data[pos], "\x00\x00\x01\xb8", 4)) /* find group start code */
|
||||
{
|
||||
pos++;
|
||||
continue;
|
||||
}
|
||||
|
||||
struct iovec iov[4];
|
||||
iov[0].iov_base = PesHeader;
|
||||
iov[0].iov_len = InsertPesHeader(PesHeader, call->len + codec_data_size, MPEG_VIDEO_PES_START_CODE, call->Pts, 0);
|
||||
|
||||
iov[1].iov_base = data;
|
||||
iov[1].iov_len = pos;
|
||||
|
||||
iov[2].iov_base = codec_data;
|
||||
iov[2].iov_len = codec_data_size;
|
||||
|
||||
iov[3].iov_base = data + pos;
|
||||
iov[3].iov_len = data_len - pos;
|
||||
|
||||
must_send_header = false;
|
||||
return call->WriteV(call->fd, iov, 4);
|
||||
}
|
||||
}
|
||||
|
||||
struct iovec iov[2];
|
||||
|
||||
iov[0].iov_base = PesHeader;
|
||||
iov[0].iov_len = InsertPesHeader(PesHeader, call->len, MPEG_VIDEO_PES_START_CODE, call->Pts, 0);
|
||||
|
||||
iov[1].iov_base = data;
|
||||
iov[1].iov_len = data_len;
|
||||
|
||||
PesHeader[6] = 0x81;
|
||||
|
||||
UpdatePesHeaderPayloadSize(PesHeader, data_len + iov[0].iov_len - 6);
|
||||
if (iov[0].iov_len != (unsigned)WriteExt(call->WriteV, call->fd, iov[0].iov_base, iov[0].iov_len)) return -1;
|
||||
if (iov[1].iov_len != (unsigned)WriteExt(call->WriteV, call->fd, iov[1].iov_base, iov[1].iov_len)) return -1;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* ***************************** */
|
||||
/* Writer Definition */
|
||||
/* ***************************** */
|
||||
static WriterCaps_t caps =
|
||||
{
|
||||
"mpeg2",
|
||||
eVideo,
|
||||
"V_MPEG2",
|
||||
VIDEO_ENCODING_AUTO,
|
||||
STREAMTYPE_MPEG2,
|
||||
-1
|
||||
};
|
||||
|
||||
struct Writer_s WriterVideoMPEG2 =
|
||||
{
|
||||
&reset,
|
||||
&writeData,
|
||||
&caps
|
||||
};
|
||||
|
||||
static WriterCaps_t mpg1_caps =
|
||||
{
|
||||
"mpge1",
|
||||
eVideo,
|
||||
"V_MPEG1",
|
||||
VIDEO_ENCODING_AUTO,
|
||||
STREAMTYPE_MPEG1,
|
||||
-1
|
||||
};
|
||||
|
||||
struct Writer_s WriterVideoMPEG1 =
|
||||
{
|
||||
&reset,
|
||||
&writeData,
|
||||
&mpg1_caps
|
||||
};
|
169
libeplayer3/output/writer/mipsel/mpeg4.c
Normal file
169
libeplayer3/output/writer/mipsel/mpeg4.c
Normal file
@@ -0,0 +1,169 @@
|
||||
/*
|
||||
* linuxdvb output/writer handling.
|
||||
*
|
||||
* konfetti 2010 based on linuxdvb.c code from libeplayer2
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*
|
||||
*/
|
||||
|
||||
/* ***************************** */
|
||||
/* Includes */
|
||||
/* ***************************** */
|
||||
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
#include <unistd.h>
|
||||
#include <fcntl.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
#include <sys/ioctl.h>
|
||||
#include <sys/uio.h>
|
||||
#include <linux/dvb/video.h>
|
||||
#include <linux/dvb/audio.h>
|
||||
#include <memory.h>
|
||||
#include <asm/types.h>
|
||||
#include <pthread.h>
|
||||
#include <errno.h>
|
||||
|
||||
#include "stm_ioctls.h"
|
||||
#include "bcm_ioctls.h"
|
||||
|
||||
#include "common.h"
|
||||
#include "output.h"
|
||||
#include "debug.h"
|
||||
#include "misc.h"
|
||||
#include "pes.h"
|
||||
#include "writer.h"
|
||||
|
||||
/* ***************************** */
|
||||
/* Makros/Constants */
|
||||
/* ***************************** */
|
||||
|
||||
/* ***************************** */
|
||||
/* Types */
|
||||
/* ***************************** */
|
||||
|
||||
/* ***************************** */
|
||||
/* Variables */
|
||||
/* ***************************** */
|
||||
|
||||
static int initialHeader = 1;
|
||||
|
||||
/* ***************************** */
|
||||
/* Prototypes */
|
||||
/* ***************************** */
|
||||
|
||||
/* ***************************** */
|
||||
/* MISC Functions */
|
||||
/* ***************************** */
|
||||
|
||||
static int reset()
|
||||
{
|
||||
initialHeader = 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int writeData(WriterAVCallData_t *call)
|
||||
{
|
||||
unsigned char PesHeader[PES_MAX_HEADER_SIZE];
|
||||
|
||||
mpeg4_printf(10, "\n");
|
||||
|
||||
if (call == NULL)
|
||||
{
|
||||
mpeg4_err("call data is NULL...\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
if ((call->data == NULL) || (call->len <= 0))
|
||||
{
|
||||
mpeg4_err("parsing NULL Data. ignoring...\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (call->fd < 0)
|
||||
{
|
||||
mpeg4_err("file pointer < 0. ignoring ...\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
mpeg4_printf(10, "VideoPts %lld\n", call->Pts);
|
||||
|
||||
unsigned int PacketLength = call->len;
|
||||
if (initialHeader && call->private_size && call->private_data != NULL)
|
||||
{
|
||||
PacketLength += call->private_size;
|
||||
}
|
||||
|
||||
struct iovec iov[3];
|
||||
int ic = 0;
|
||||
iov[ic].iov_base = PesHeader;
|
||||
iov[ic++].iov_len = InsertPesHeader(PesHeader, PacketLength, MPEG_VIDEO_PES_START_CODE, call->Pts, 0);
|
||||
|
||||
if (initialHeader && call->private_size && call->private_data != NULL)
|
||||
{
|
||||
initialHeader = 0;
|
||||
iov[ic].iov_base = call->private_data;
|
||||
iov[ic++].iov_len = call->private_size;
|
||||
}
|
||||
iov[ic].iov_base = call->data;
|
||||
iov[ic++].iov_len = call->len;
|
||||
|
||||
int len = call->WriteV(call->fd, iov, ic);
|
||||
|
||||
mpeg4_printf(10, "xvid_Write < len=%d\n", len);
|
||||
|
||||
return len;
|
||||
}
|
||||
|
||||
/* ***************************** */
|
||||
/* Writer Definition */
|
||||
/* ***************************** */
|
||||
|
||||
static WriterCaps_t mpeg4p2_caps =
|
||||
{
|
||||
"mpeg4p2",
|
||||
eVideo,
|
||||
"V_MPEG4",
|
||||
VIDEO_ENCODING_MPEG4P2,
|
||||
STREAMTYPE_MPEG4_Part2,
|
||||
-1
|
||||
};
|
||||
|
||||
struct Writer_s WriterVideoMPEG4 =
|
||||
{
|
||||
&reset,
|
||||
&writeData,
|
||||
&mpeg4p2_caps
|
||||
};
|
||||
|
||||
static WriterCaps_t caps_h263 =
|
||||
{
|
||||
"h263",
|
||||
eVideo,
|
||||
"V_H263",
|
||||
VIDEO_ENCODING_H263,
|
||||
STREAMTYPE_H263,
|
||||
-1
|
||||
};
|
||||
|
||||
struct Writer_s WriterVideoH263 =
|
||||
{
|
||||
&reset,
|
||||
&writeData,
|
||||
&caps_h263
|
||||
};
|
301
libeplayer3/output/writer/mipsel/pcm.c
Normal file
301
libeplayer3/output/writer/mipsel/pcm.c
Normal file
@@ -0,0 +1,301 @@
|
||||
/*
|
||||
* linuxdvb output/writer handling.
|
||||
*
|
||||
* konfetti 2010 based on linuxdvb.c code from libeplayer2
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*
|
||||
*/
|
||||
|
||||
/* ***************************** */
|
||||
/* Includes */
|
||||
/* ***************************** */
|
||||
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
#include <unistd.h>
|
||||
#include <fcntl.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
#include <sys/ioctl.h>
|
||||
#include <sys/uio.h>
|
||||
#include <linux/dvb/video.h>
|
||||
#include <linux/dvb/audio.h>
|
||||
#include <memory.h>
|
||||
#include <asm/types.h>
|
||||
#include <pthread.h>
|
||||
#include <errno.h>
|
||||
|
||||
#include <libavcodec/avcodec.h>
|
||||
|
||||
#include "stm_ioctls.h"
|
||||
#include "bcm_ioctls.h"
|
||||
|
||||
#include "common.h"
|
||||
#include "output.h"
|
||||
#include "debug.h"
|
||||
#include "misc.h"
|
||||
#include "pes.h"
|
||||
#include "writer.h"
|
||||
#include "pcm.h"
|
||||
|
||||
/* ***************************** */
|
||||
/* Makros/Constants */
|
||||
/* ***************************** */
|
||||
|
||||
/* ***************************** */
|
||||
/* Types */
|
||||
/* ***************************** */
|
||||
|
||||
/* ***************************** */
|
||||
/* Variables */
|
||||
/* ***************************** */
|
||||
|
||||
static uint8_t initialHeader = 1;
|
||||
static uint8_t codec_data[18];
|
||||
static uint64_t fixed_buffertimestamp;
|
||||
static uint64_t fixed_bufferduration;
|
||||
static uint32_t fixed_buffersize;
|
||||
static uint8_t *fixed_buffer;
|
||||
static uint32_t fixed_bufferfilled;
|
||||
|
||||
/* ***************************** */
|
||||
/* Prototypes */
|
||||
/* ***************************** */
|
||||
|
||||
/* ***************************** */
|
||||
/* MISC Functions */
|
||||
/* ***************************** */
|
||||
|
||||
static int32_t reset()
|
||||
{
|
||||
initialHeader = 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int writeData(WriterAVCallData_t *call)
|
||||
{
|
||||
pcm_printf(10, "\n");
|
||||
|
||||
if (!call)
|
||||
{
|
||||
pcm_err("call data is NULL...\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
pcm_printf(10, "AudioPts %lld\n", call->Pts);
|
||||
|
||||
if (!call->data || (call->len <= 0))
|
||||
{
|
||||
pcm_err("parsing NULL Data. ignoring...\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (call->fd < 0)
|
||||
{
|
||||
pcm_err("file pointer < 0. ignoring ...\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
static uint8_t PesHeader[PES_MAX_HEADER_SIZE + 22];
|
||||
pcmPrivateData_t *pcmPrivateData = (pcmPrivateData_t *)call->private_data;
|
||||
uint8_t *buffer = call->data;
|
||||
uint32_t size = call->len;
|
||||
|
||||
if (pcmPrivateData->bResampling || NULL == fixed_buffer)
|
||||
{
|
||||
int32_t width = 0;
|
||||
int32_t depth = 0;
|
||||
int32_t rate = (uint64_t)pcmPrivateData->sample_rate;
|
||||
int32_t channels = (uint8_t) pcmPrivateData->channels;
|
||||
int32_t block_align = 0;
|
||||
int32_t byterate = 0;
|
||||
|
||||
uint32_t codecID = (uint32_t)pcmPrivateData->ffmpeg_codec_id;
|
||||
|
||||
//uint8_t dataPrecision = 0;
|
||||
uint8_t LE = 0;
|
||||
switch (codecID)
|
||||
{
|
||||
case AV_CODEC_ID_PCM_S8:
|
||||
case AV_CODEC_ID_PCM_U8:
|
||||
width = depth = 8;
|
||||
break;
|
||||
case AV_CODEC_ID_PCM_S16LE:
|
||||
case AV_CODEC_ID_PCM_U16LE:
|
||||
LE = 1;
|
||||
// fall through
|
||||
case AV_CODEC_ID_PCM_S16BE:
|
||||
case AV_CODEC_ID_PCM_U16BE:
|
||||
width = depth = 16;
|
||||
break;
|
||||
case AV_CODEC_ID_PCM_S24LE:
|
||||
case AV_CODEC_ID_PCM_U24LE:
|
||||
LE = 1;
|
||||
// fall through
|
||||
case AV_CODEC_ID_PCM_S24BE:
|
||||
case AV_CODEC_ID_PCM_U24BE:
|
||||
width = depth = 24;
|
||||
break;
|
||||
case AV_CODEC_ID_PCM_S32LE:
|
||||
case AV_CODEC_ID_PCM_U32LE:
|
||||
LE = 1;
|
||||
// fall through
|
||||
case AV_CODEC_ID_PCM_S32BE:
|
||||
case AV_CODEC_ID_PCM_U32BE:
|
||||
width = depth = 32;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
uint8_t *data = codec_data;
|
||||
uint16_t format = LE ? 0x0001 : 0x0100;
|
||||
|
||||
byterate = channels * rate * width / 8;
|
||||
block_align = channels * width / 8;
|
||||
memset(data, 0, sizeof(codec_data));
|
||||
/* format tag */
|
||||
*(data++) = format & 0xff;
|
||||
*(data++) = (format >> 8) & 0xff;
|
||||
/* channels */
|
||||
*(data++) = channels & 0xff;
|
||||
*(data++) = (channels >> 8) & 0xff;
|
||||
/* sample rate */
|
||||
*(data++) = rate & 0xff;
|
||||
*(data++) = (rate >> 8) & 0xff;
|
||||
*(data++) = (rate >> 16) & 0xff;
|
||||
*(data++) = (rate >> 24) & 0xff;
|
||||
/* byte rate */
|
||||
*(data++) = byterate & 0xff;
|
||||
*(data++) = (byterate >> 8) & 0xff;
|
||||
*(data++) = (byterate >> 16) & 0xff;
|
||||
*(data++) = (byterate >> 24) & 0xff;
|
||||
/* block align */
|
||||
*(data++) = block_align & 0xff;
|
||||
*(data++) = (block_align >> 8) & 0xff;
|
||||
/* word size */
|
||||
*(data++) = depth & 0xff;
|
||||
*(data++) = (depth >> 8) & 0xff;
|
||||
|
||||
uint32_t nfixed_buffersize = rate * 30 / 1000;
|
||||
nfixed_buffersize *= channels * depth / 8;
|
||||
fixed_buffertimestamp = call->Pts;
|
||||
fixed_bufferduration = 90000 * nfixed_buffersize / byterate;
|
||||
|
||||
if (fixed_buffersize != nfixed_buffersize || NULL == fixed_buffer)
|
||||
{
|
||||
fixed_buffersize = nfixed_buffersize;
|
||||
if (NULL != fixed_buffer)
|
||||
{
|
||||
free(fixed_buffer);
|
||||
}
|
||||
fixed_buffer = malloc(fixed_buffersize);
|
||||
}
|
||||
fixed_bufferfilled = 0;
|
||||
/* avoid compiler warning */
|
||||
if (LE) {}
|
||||
pcm_printf(40, "PCM fixed_buffersize [%u] [%s]\n", fixed_buffersize, LE ? "LE" : "BE");
|
||||
}
|
||||
|
||||
while (size > 0)
|
||||
{
|
||||
uint32_t cpSize = (fixed_buffersize - fixed_bufferfilled);
|
||||
if (cpSize > size)
|
||||
{
|
||||
memcpy(fixed_buffer + fixed_bufferfilled, buffer, size);
|
||||
fixed_bufferfilled += size;
|
||||
return size;
|
||||
}
|
||||
|
||||
memcpy(fixed_buffer + fixed_bufferfilled, buffer, cpSize);
|
||||
fixed_bufferfilled = 0;
|
||||
buffer += cpSize;
|
||||
size -= cpSize;
|
||||
|
||||
uint32_t addHeaderSize = 0;
|
||||
if (STB_DREAMBOX == GetSTBType())
|
||||
{
|
||||
addHeaderSize = 4;
|
||||
}
|
||||
uint32_t headerSize = InsertPesHeader(PesHeader, fixed_buffersize + 4 + addHeaderSize + sizeof(codec_data), MPEG_AUDIO_PES_START_CODE, fixed_buffertimestamp, 0);
|
||||
if (STB_DREAMBOX == GetSTBType())
|
||||
{
|
||||
PesHeader[headerSize++] = 0x42; // B
|
||||
PesHeader[headerSize++] = 0x43; // C
|
||||
PesHeader[headerSize++] = 0x4D; // M
|
||||
PesHeader[headerSize++] = 0x41; // A
|
||||
}
|
||||
|
||||
PesHeader[headerSize++] = (fixed_buffersize >> 24) & 0xff;
|
||||
PesHeader[headerSize++] = (fixed_buffersize >> 16) & 0xff;
|
||||
PesHeader[headerSize++] = (fixed_buffersize >> 8) & 0xff;
|
||||
PesHeader[headerSize++] = fixed_buffersize & 0xff;
|
||||
|
||||
memcpy(PesHeader + headerSize, codec_data, sizeof(codec_data));
|
||||
headerSize += sizeof(codec_data);
|
||||
|
||||
PesHeader[6] |= 1;
|
||||
|
||||
struct iovec iov[2];
|
||||
iov[0].iov_base = PesHeader;
|
||||
iov[0].iov_len = headerSize;
|
||||
iov[1].iov_base = fixed_buffer;
|
||||
iov[1].iov_len = fixed_buffersize;
|
||||
call->WriteV(call->fd, iov, 2);
|
||||
fixed_buffertimestamp += fixed_bufferduration;
|
||||
}
|
||||
|
||||
return size;
|
||||
}
|
||||
|
||||
/* ***************************** */
|
||||
/* Writer Definition */
|
||||
/* ***************************** */
|
||||
|
||||
static WriterCaps_t caps_pcm =
|
||||
{
|
||||
"pcm",
|
||||
eAudio,
|
||||
"A_PCM",
|
||||
AUDIO_ENCODING_LPCMA,
|
||||
0x30,
|
||||
-1
|
||||
};
|
||||
|
||||
struct Writer_s WriterAudioPCM =
|
||||
{
|
||||
&reset,
|
||||
&writeData,
|
||||
&caps_pcm
|
||||
};
|
||||
|
||||
static WriterCaps_t caps_ipcm =
|
||||
{
|
||||
"ipcm",
|
||||
eAudio,
|
||||
"A_IPCM",
|
||||
AUDIO_ENCODING_LPCMA,
|
||||
0x30,
|
||||
-1
|
||||
};
|
||||
|
||||
struct Writer_s WriterAudioIPCM =
|
||||
{
|
||||
&reset,
|
||||
&writeData, /* writeDataIPCM */
|
||||
&caps_ipcm
|
||||
};
|
191
libeplayer3/output/writer/mipsel/vc1.c
Normal file
191
libeplayer3/output/writer/mipsel/vc1.c
Normal file
@@ -0,0 +1,191 @@
|
||||
/*
|
||||
* linuxdvb output/writer handling.
|
||||
*
|
||||
* konfetti 2010 based on linuxdvb.c code from libeplayer2
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*
|
||||
*/
|
||||
|
||||
/* ***************************** */
|
||||
/* Includes */
|
||||
/* ***************************** */
|
||||
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
#include <unistd.h>
|
||||
#include <fcntl.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
#include <sys/ioctl.h>
|
||||
#include <sys/uio.h>
|
||||
#include <linux/dvb/video.h>
|
||||
#include <linux/dvb/audio.h>
|
||||
#include <memory.h>
|
||||
#include <asm/types.h>
|
||||
#include <pthread.h>
|
||||
#include <errno.h>
|
||||
|
||||
#include "stm_ioctls.h"
|
||||
#include "bcm_ioctls.h"
|
||||
|
||||
#include "common.h"
|
||||
#include "output.h"
|
||||
#include "debug.h"
|
||||
#include "misc.h"
|
||||
#include "pes.h"
|
||||
#include "writer.h"
|
||||
|
||||
/* ***************************** */
|
||||
/* Makros/Constants */
|
||||
/* ***************************** */
|
||||
|
||||
#define VC1_SEQUENCE_LAYER_METADATA_START_CODE 0x80
|
||||
#define VC1_FRAME_START_CODE 0x0d
|
||||
|
||||
/* ***************************** */
|
||||
/* Types */
|
||||
/* ***************************** */
|
||||
|
||||
//static const unsigned char SequenceLayerStartCode[] = {0x00, 0x00, 0x01, VC1_SEQUENCE_LAYER_METADATA_START_CODE};
|
||||
static const uint8_t Vc1FrameStartCode[] = {0, 0, 1, VC1_FRAME_START_CODE};
|
||||
|
||||
/* ***************************** */
|
||||
/* Variables */
|
||||
/* ***************************** */
|
||||
|
||||
static int initialHeader = 1;
|
||||
static video_codec_data_t videocodecdata = {0, 0};
|
||||
|
||||
/* ***************************** */
|
||||
/* Prototypes */
|
||||
/* ***************************** */
|
||||
|
||||
/* ***************************** */
|
||||
/* MISC Functions */
|
||||
/* ***************************** */
|
||||
|
||||
static int reset()
|
||||
{
|
||||
initialHeader = 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int writeData(WriterAVCallData_t *call)
|
||||
{
|
||||
//int len = 0;
|
||||
|
||||
vc1_printf(10, "\n");
|
||||
|
||||
if (call == NULL)
|
||||
{
|
||||
vc1_err("call data is NULL...\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
if ((call->data == NULL) || (call->len <= 0))
|
||||
{
|
||||
vc1_err("parsing NULL Data. ignoring...\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (call->fd < 0)
|
||||
{
|
||||
vc1_err("file pointer < 0. ignoring ...\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
vc1_printf(10, "VideoPts %lld\n", call->Pts);
|
||||
vc1_printf(10, "Got Private Size %d\n", call->private_size);
|
||||
|
||||
unsigned char PesHeader[PES_MAX_HEADER_SIZE + sizeof(Vc1FrameStartCode)];
|
||||
int32_t ic = 0;
|
||||
struct iovec iov[5];
|
||||
unsigned int PacketLength = 0;
|
||||
|
||||
iov[ic++].iov_base = PesHeader;
|
||||
if (initialHeader)
|
||||
{
|
||||
initialHeader = 0;
|
||||
if (videocodecdata.data)
|
||||
{
|
||||
free(videocodecdata.data);
|
||||
videocodecdata.data = NULL;
|
||||
}
|
||||
videocodecdata.length = call->private_size + 8;
|
||||
videocodecdata.data = malloc(videocodecdata.length);
|
||||
memset(videocodecdata.data, 0, videocodecdata.length);
|
||||
memcpy(videocodecdata.data + 8, call->private_data, call->private_size);
|
||||
if (STB_DREAMBOX == GetSTBType() || 0 != ioctl(call->fd, VIDEO_SET_CODEC_DATA, &videocodecdata))
|
||||
{
|
||||
iov[ic].iov_base = videocodecdata.data;
|
||||
iov[ic++].iov_len = videocodecdata.length;
|
||||
PacketLength += videocodecdata.length;
|
||||
}
|
||||
}
|
||||
|
||||
uint8_t needFrameStartCode = 0;
|
||||
if (sizeof(Vc1FrameStartCode) >= call->len ||
|
||||
memcmp(call->data, Vc1FrameStartCode, sizeof(Vc1FrameStartCode)) != 0)
|
||||
{
|
||||
needFrameStartCode = 1;
|
||||
PacketLength += sizeof(Vc1FrameStartCode);
|
||||
}
|
||||
|
||||
iov[ic].iov_base = call->data;
|
||||
iov[ic++].iov_len = call->len;
|
||||
PacketLength += call->len;
|
||||
|
||||
iov[0].iov_len = InsertPesHeader(PesHeader, PacketLength, MPEG_VIDEO_PES_START_CODE, call->Pts, 0);
|
||||
|
||||
/* some mipsel receiver(s) like et4x00 needs to have Copy(0)/Original(1) flag set to Original */
|
||||
PesHeader[6] |= 1;
|
||||
|
||||
if (needFrameStartCode)
|
||||
{
|
||||
memcpy(PesHeader + iov[0].iov_len, Vc1FrameStartCode, sizeof(Vc1FrameStartCode));
|
||||
iov[0].iov_len += sizeof(Vc1FrameStartCode);
|
||||
}
|
||||
|
||||
if (videocodecdata.data)
|
||||
{
|
||||
free(videocodecdata.data);
|
||||
videocodecdata.data = NULL;
|
||||
}
|
||||
|
||||
return call->WriteV(call->fd, iov, ic);
|
||||
}
|
||||
|
||||
/* ***************************** */
|
||||
/* Writer Definition */
|
||||
/* ***************************** */
|
||||
|
||||
static WriterCaps_t caps =
|
||||
{
|
||||
"vc1",
|
||||
eVideo,
|
||||
"V_VC1",
|
||||
VIDEO_ENCODING_VC1,
|
||||
STREAMTYPE_VC1,
|
||||
CT_MPEG4_PART2
|
||||
};
|
||||
|
||||
struct Writer_s WriterVideoVC1 =
|
||||
{
|
||||
&reset,
|
||||
&writeData,
|
||||
&caps
|
||||
};
|
305
libeplayer3/output/writer/mipsel/vp.c
Normal file
305
libeplayer3/output/writer/mipsel/vp.c
Normal file
@@ -0,0 +1,305 @@
|
||||
/*
|
||||
* linuxdvb output/writer handling.
|
||||
*
|
||||
* konfetti 2010 based on linuxdvb.c code from libeplayer2
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*
|
||||
*/
|
||||
|
||||
/* ***************************** */
|
||||
/* Includes */
|
||||
/* ***************************** */
|
||||
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
#include <unistd.h>
|
||||
#include <fcntl.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
#include <sys/ioctl.h>
|
||||
#include <sys/uio.h>
|
||||
#include <linux/dvb/video.h>
|
||||
#include <linux/dvb/audio.h>
|
||||
#include <memory.h>
|
||||
#include <asm/types.h>
|
||||
#include <pthread.h>
|
||||
#include <errno.h>
|
||||
|
||||
#include "stm_ioctls.h"
|
||||
#include "bcm_ioctls.h"
|
||||
|
||||
#include "common.h"
|
||||
#include "output.h"
|
||||
#include "debug.h"
|
||||
#include "misc.h"
|
||||
#include "pes.h"
|
||||
#include "writer.h"
|
||||
|
||||
/* ***************************** */
|
||||
/* Makros/Constants */
|
||||
/* ***************************** */
|
||||
|
||||
/* ***************************** */
|
||||
/* Types */
|
||||
/* ***************************** */
|
||||
|
||||
/* ***************************** */
|
||||
/* Variables */
|
||||
/* ***************************** */
|
||||
|
||||
/* ***************************** */
|
||||
/* Prototypes */
|
||||
/* ***************************** */
|
||||
|
||||
/* ***************************** */
|
||||
/* MISC Functions */
|
||||
/* ***************************** */
|
||||
|
||||
static int reset()
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
static uint8_t PesHeader[256];
|
||||
static int writeData(WriterAVCallData_t *call, bool is_vp6, bool is_vp9)
|
||||
{
|
||||
vp_printf(10, "\n");
|
||||
|
||||
if (call == NULL)
|
||||
{
|
||||
vp_err("call data is NULL...\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
if ((call->data == NULL) || (call->len <= 0))
|
||||
{
|
||||
vp_err("parsing NULL Data. ignoring...\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (call->fd < 0)
|
||||
{
|
||||
vp_err("file pointer < 0. ignoring ...\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
vp_printf(10, "VideoPts %lld\n", call->Pts);
|
||||
vp_printf(10, "Got Private Size %d\n", call->private_size);
|
||||
|
||||
struct iovec iov[2];
|
||||
uint64_t pts = is_vp9 && STB_VUPLUS == GetSTBType() ? 0 : call->Pts;
|
||||
|
||||
iov[0].iov_base = PesHeader;
|
||||
uint32_t pes_header_len = InsertPesHeader(PesHeader, call->len, MPEG_VIDEO_PES_START_CODE, pts, 0);
|
||||
uint32_t len = call->len + 4 + 6;
|
||||
memcpy(PesHeader + pes_header_len, "BCMV", 4);
|
||||
pes_header_len += 4;
|
||||
|
||||
if (is_vp9 && STB_VUPLUS == GetSTBType())
|
||||
{
|
||||
uint32_t vp9_pts = (call->Pts == INVALID_PTS_VALUE ? call->Dts : call->Pts) / 2;
|
||||
memcpy(&PesHeader[9], &vp9_pts, sizeof(vp9_pts));
|
||||
}
|
||||
|
||||
if (is_vp6)
|
||||
++len;
|
||||
PesHeader[pes_header_len++] = (len & 0xFF000000) >> 24;
|
||||
PesHeader[pes_header_len++] = (len & 0x00FF0000) >> 16;
|
||||
PesHeader[pes_header_len++] = (len & 0x0000FF00) >> 8;
|
||||
PesHeader[pes_header_len++] = (len & 0x000000FF) >> 0;
|
||||
PesHeader[pes_header_len++] = 0;
|
||||
PesHeader[pes_header_len++] = STB_VUPLUS != GetSTBType() && is_vp9 ? 1 : 0;
|
||||
if (is_vp6)
|
||||
PesHeader[pes_header_len++] = 0;
|
||||
iov[0].iov_len = pes_header_len;
|
||||
iov[1].iov_base = call->data;
|
||||
iov[1].iov_len = call->len;
|
||||
|
||||
int32_t payload_len = call->len + pes_header_len - 6;
|
||||
|
||||
if (!is_vp9 || STB_VUPLUS == GetSTBType() || STB_HISILICON == GetSTBType() || STB_DREAMBOX == GetSTBType())
|
||||
{
|
||||
UpdatePesHeaderPayloadSize(PesHeader, payload_len);
|
||||
// it looks like for VUPLUS drivers PES header must be written separately
|
||||
int ret = call->WriteV(call->fd, iov, 1);
|
||||
if (iov[0].iov_len != (unsigned)ret)
|
||||
return ret;
|
||||
ret = call->WriteV(call->fd, iov + 1, 1);
|
||||
return iov[0].iov_len + ret;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (payload_len > 0x8008)
|
||||
payload_len = 0x8008;
|
||||
|
||||
int offs = 0;
|
||||
int bytes = payload_len - 10 - 8;
|
||||
UpdatePesHeaderPayloadSize(PesHeader, payload_len);
|
||||
// pes header
|
||||
if (pes_header_len != (unsigned)WriteExt(call->WriteV, call->fd, PesHeader, pes_header_len)) return -1;
|
||||
if (bytes != WriteExt(call->WriteV, call->fd, call->data, bytes)) return -1;
|
||||
|
||||
offs += bytes;
|
||||
|
||||
while ((unsigned)bytes < call->len)
|
||||
{
|
||||
int left = call->len - bytes;
|
||||
int wr = 0x8000;
|
||||
if (wr > left)
|
||||
wr = left;
|
||||
|
||||
//gst_buffer_unmap(self->pesheader_buffer, &pesheadermap);
|
||||
//gst_buffer_map(self->pesheader_buffer, &pesheadermap, GST_MAP_WRITE);
|
||||
//pes_header = pesheadermap.data;
|
||||
|
||||
//PesHeader[0] = 0x00;
|
||||
//PesHeader[1] = 0x00;
|
||||
//PesHeader[2] = 0x01;
|
||||
//PesHeader[3] = 0xE0;
|
||||
PesHeader[6] = 0x81;
|
||||
PesHeader[7] = 0x00;
|
||||
PesHeader[8] = 0x00;
|
||||
pes_header_len = 9;
|
||||
|
||||
UpdatePesHeaderPayloadSize(PesHeader, wr + 3);
|
||||
|
||||
if (pes_header_len != (unsigned)WriteExt(call->WriteV, call->fd, PesHeader, pes_header_len)) return -1;
|
||||
if (wr != WriteExt(call->WriteV, call->fd, call->data + offs, wr)) return -1;
|
||||
|
||||
bytes += wr;
|
||||
offs += wr;
|
||||
}
|
||||
|
||||
//gst_buffer_unmap(self->pesheader_buffer, &pesheadermap);
|
||||
//gst_buffer_map(self->pesheader_buffer, &pesheadermap, GST_MAP_WRITE);
|
||||
//pes_header = pesheadermap.data;
|
||||
|
||||
//PesHeader[0] = 0x00;
|
||||
//PesHeader[1] = 0x00;
|
||||
//PesHeader[2] = 0x01;
|
||||
//PesHeader[3] = 0xE0;
|
||||
PesHeader[4] = 0x00;
|
||||
PesHeader[5] = 0xB2;
|
||||
PesHeader[6] = 0x81;
|
||||
PesHeader[7] = 0x01;
|
||||
PesHeader[8] = 0x14;
|
||||
PesHeader[9] = 0x80;
|
||||
PesHeader[10] = 'B';
|
||||
PesHeader[11] = 'R';
|
||||
PesHeader[12] = 'C';
|
||||
PesHeader[13] = 'M';
|
||||
memset(PesHeader + 14, 0, 170);
|
||||
PesHeader[26] = 0xFF;
|
||||
PesHeader[27] = 0xFF;
|
||||
PesHeader[28] = 0xFF;
|
||||
PesHeader[29] = 0xFF;
|
||||
PesHeader[33] = 0x85;
|
||||
|
||||
if (pes_header_len != (unsigned)WriteExt(call->WriteV, call->fd, PesHeader, 184)) return -1;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
//return call->WriteV(call->fd, iov, 2);
|
||||
}
|
||||
|
||||
static int writeDataVP6(WriterAVCallData_t *call)
|
||||
{
|
||||
return writeData(call, true, false);
|
||||
}
|
||||
|
||||
static int writeDataVP8(WriterAVCallData_t *call)
|
||||
{
|
||||
return writeData(call, false, false);
|
||||
}
|
||||
|
||||
static int writeDataVP9(WriterAVCallData_t *call)
|
||||
{
|
||||
return writeData(call, false, true);
|
||||
}
|
||||
|
||||
/* ***************************** */
|
||||
/* Writer Definition */
|
||||
/* ***************************** */
|
||||
|
||||
static WriterCaps_t capsVP6 =
|
||||
{
|
||||
"vp6",
|
||||
eVideo,
|
||||
"V_VP6",
|
||||
VIDEO_ENCODING_VC1,
|
||||
STREAMTYPE_VB6,
|
||||
CT_VP6
|
||||
};
|
||||
|
||||
struct Writer_s WriterVideoVP6 =
|
||||
{
|
||||
&reset,
|
||||
&writeDataVP6,
|
||||
&capsVP6
|
||||
};
|
||||
|
||||
static WriterCaps_t capsVP8 =
|
||||
{
|
||||
"vp8",
|
||||
eVideo,
|
||||
"V_VP8",
|
||||
VIDEO_ENCODING_VC1,
|
||||
STREAMTYPE_VB8,
|
||||
CT_VP8
|
||||
};
|
||||
|
||||
struct Writer_s WriterVideoVP8 =
|
||||
{
|
||||
&reset,
|
||||
&writeDataVP8,
|
||||
&capsVP8
|
||||
};
|
||||
|
||||
static WriterCaps_t capsVP9 =
|
||||
{
|
||||
"vp9",
|
||||
eVideo,
|
||||
"V_VP9",
|
||||
VIDEO_ENCODING_VC1,
|
||||
STREAMTYPE_VB9,
|
||||
CT_VP9
|
||||
};
|
||||
|
||||
struct Writer_s WriterVideoVP9 =
|
||||
{
|
||||
&reset,
|
||||
&writeDataVP9,
|
||||
&capsVP9
|
||||
};
|
||||
|
||||
static WriterCaps_t capsFLV =
|
||||
{
|
||||
"flv1",
|
||||
eVideo,
|
||||
"V_FLV",
|
||||
VIDEO_ENCODING_VC1,
|
||||
STREAMTYPE_SPARK,
|
||||
CT_SPARK
|
||||
};
|
||||
|
||||
struct Writer_s WriterVideoFLV =
|
||||
{
|
||||
&reset,
|
||||
&writeDataVP8,
|
||||
&capsFLV
|
||||
};
|
190
libeplayer3/output/writer/mipsel/wma.c
Normal file
190
libeplayer3/output/writer/mipsel/wma.c
Normal file
@@ -0,0 +1,190 @@
|
||||
/*
|
||||
* linuxdvb output/writer handling.
|
||||
*
|
||||
* konfetti 2010 based on linuxdvb.c code from libeplayer2
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*
|
||||
*/
|
||||
|
||||
/* ***************************** */
|
||||
/* Includes */
|
||||
/* ***************************** */
|
||||
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
#include <unistd.h>
|
||||
#include <fcntl.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
#include <sys/ioctl.h>
|
||||
#include <sys/uio.h>
|
||||
#include <linux/dvb/video.h>
|
||||
#include <linux/dvb/audio.h>
|
||||
#include <memory.h>
|
||||
#include <asm/types.h>
|
||||
#include <pthread.h>
|
||||
#include <errno.h>
|
||||
|
||||
#include "stm_ioctls.h"
|
||||
#include "bcm_ioctls.h"
|
||||
|
||||
#include "common.h"
|
||||
#include "output.h"
|
||||
#include "debug.h"
|
||||
#include "misc.h"
|
||||
#include "pes.h"
|
||||
#include "writer.h"
|
||||
|
||||
/* ***************************** */
|
||||
/* Makros/Constants */
|
||||
/* ***************************** */
|
||||
|
||||
/* ***************************** */
|
||||
/* Types */
|
||||
/* ***************************** */
|
||||
|
||||
/* ***************************** */
|
||||
/* Variables */
|
||||
/* ***************************** */
|
||||
|
||||
static int initialHeader = 1;
|
||||
static uint8_t *PesHeader = NULL;
|
||||
static uint32_t MaxPesHeader = 0;
|
||||
|
||||
/* ***************************** */
|
||||
/* Prototypes */
|
||||
/* ***************************** */
|
||||
|
||||
/* ***************************** */
|
||||
/* MISC Functions */
|
||||
/* ***************************** */
|
||||
|
||||
static int reset()
|
||||
{
|
||||
initialHeader = 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int writeData(WriterAVCallData_t *call)
|
||||
{
|
||||
//int len = 0;
|
||||
|
||||
wma_printf(10, "\n");
|
||||
|
||||
if (call == NULL)
|
||||
{
|
||||
wma_err("call data is NULL...\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
wma_printf(10, "AudioPts %lld\n", call->Pts);
|
||||
|
||||
if ((call->data == NULL) || (call->len <= 0))
|
||||
{
|
||||
wma_err("parsing NULL Data. ignoring...\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (call->fd < 0)
|
||||
{
|
||||
wma_err("file pointer < 0. ignoring ...\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
uint32_t packetLength = 4 + call->private_size + call->len;
|
||||
|
||||
if (STB_DREAMBOX == GetSTBType())
|
||||
{
|
||||
packetLength += 4;
|
||||
}
|
||||
|
||||
if ((packetLength + PES_MAX_HEADER_SIZE) > MaxPesHeader)
|
||||
{
|
||||
if (PesHeader)
|
||||
{
|
||||
free(PesHeader);
|
||||
}
|
||||
MaxPesHeader = packetLength + PES_MAX_HEADER_SIZE;
|
||||
PesHeader = malloc(MaxPesHeader);
|
||||
}
|
||||
|
||||
uint32_t headerSize = InsertPesHeader(PesHeader, packetLength, MPEG_AUDIO_PES_START_CODE, call->Pts, 0);
|
||||
if (STB_DREAMBOX == GetSTBType())
|
||||
{
|
||||
PesHeader[headerSize++] = 0x42; // B
|
||||
PesHeader[headerSize++] = 0x43; // C
|
||||
PesHeader[headerSize++] = 0x4D; // M
|
||||
PesHeader[headerSize++] = 0x41; // A
|
||||
}
|
||||
|
||||
size_t payload_len = call->len;
|
||||
PesHeader[headerSize++] = (payload_len >> 24) & 0xff;
|
||||
PesHeader[headerSize++] = (payload_len >> 16) & 0xff;
|
||||
PesHeader[headerSize++] = (payload_len >> 8) & 0xff;
|
||||
PesHeader[headerSize++] = payload_len & 0xff;
|
||||
|
||||
memcpy(PesHeader + headerSize, call->private_data, call->private_size);
|
||||
headerSize += call->private_size;
|
||||
|
||||
PesHeader[6] |= 1;
|
||||
|
||||
struct iovec iov[2];
|
||||
iov[0].iov_base = PesHeader;
|
||||
iov[0].iov_len = headerSize;
|
||||
iov[1].iov_base = call->data;
|
||||
iov[1].iov_len = call->len;
|
||||
|
||||
return call->WriteV(call->fd, iov, 2);
|
||||
}
|
||||
|
||||
/* ***************************** */
|
||||
/* Writer Definition */
|
||||
/* ***************************** */
|
||||
|
||||
static WriterCaps_t capsWMAPRO =
|
||||
{
|
||||
"wma/pro",
|
||||
eAudio,
|
||||
"A_WMA/PRO",
|
||||
AUDIO_ENCODING_WMA,
|
||||
AUDIOTYPE_WMA_PRO,
|
||||
-1
|
||||
};
|
||||
|
||||
struct Writer_s WriterAudioWMAPRO =
|
||||
{
|
||||
&reset,
|
||||
&writeData,
|
||||
&capsWMAPRO
|
||||
};
|
||||
|
||||
static WriterCaps_t capsWMA =
|
||||
{
|
||||
"wma",
|
||||
eAudio,
|
||||
"A_WMA",
|
||||
AUDIO_ENCODING_WMA,
|
||||
AUDIOTYPE_WMA,
|
||||
-1
|
||||
};
|
||||
|
||||
struct Writer_s WriterAudioWMA =
|
||||
{
|
||||
&reset,
|
||||
&writeData,
|
||||
&capsWMA
|
||||
};
|
198
libeplayer3/output/writer/mipsel/wmv.c
Normal file
198
libeplayer3/output/writer/mipsel/wmv.c
Normal file
@@ -0,0 +1,198 @@
|
||||
/*
|
||||
* linuxdvb output/writer handling.
|
||||
*
|
||||
* konfetti 2010 based on linuxdvb.c code from libeplayer2
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*
|
||||
*/
|
||||
|
||||
/* ***************************** */
|
||||
/* Includes */
|
||||
/* ***************************** */
|
||||
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
#include <unistd.h>
|
||||
#include <fcntl.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
#include <sys/ioctl.h>
|
||||
#include <sys/uio.h>
|
||||
#include <linux/dvb/video.h>
|
||||
#include <linux/dvb/audio.h>
|
||||
#include <memory.h>
|
||||
#include <asm/types.h>
|
||||
#include <pthread.h>
|
||||
#include <errno.h>
|
||||
|
||||
#include "stm_ioctls.h"
|
||||
#include "bcm_ioctls.h"
|
||||
|
||||
#include "common.h"
|
||||
#include "output.h"
|
||||
#include "debug.h"
|
||||
#include "misc.h"
|
||||
#include "pes.h"
|
||||
#include "writer.h"
|
||||
|
||||
/* ***************************** */
|
||||
/* Makros/Constants */
|
||||
/* ***************************** */
|
||||
|
||||
#define WMV_FRAME_START_CODE 0x0d
|
||||
|
||||
/* ***************************** */
|
||||
/* Types */
|
||||
/* ***************************** */
|
||||
|
||||
static const uint8_t Vc1FrameStartCode[] = {0, 0, 1, WMV_FRAME_START_CODE};
|
||||
|
||||
/* ***************************** */
|
||||
/* Variables */
|
||||
/* ***************************** */
|
||||
|
||||
static int initialHeader = 1;
|
||||
static video_codec_data_t videocodecdata = {0, 0};
|
||||
|
||||
/* ***************************** */
|
||||
/* Prototypes */
|
||||
/* ***************************** */
|
||||
|
||||
/* ***************************** */
|
||||
/* MISC Functions */
|
||||
/* ***************************** */
|
||||
|
||||
static int reset()
|
||||
{
|
||||
initialHeader = 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int writeData(WriterAVCallData_t *call)
|
||||
{
|
||||
wmv_printf(10, "\n");
|
||||
|
||||
if (call == NULL)
|
||||
{
|
||||
wmv_err("call data is NULL...\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
if ((call->data == NULL) || (call->len <= 0))
|
||||
{
|
||||
wmv_err("parsing NULL Data. ignoring...\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (call->fd < 0)
|
||||
{
|
||||
wmv_err("file pointer < 0. ignoring ...\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
wmv_printf(10, "VideoPts %lld\n", call->Pts);
|
||||
wmv_printf(10, "Got Private Size %d\n", call->private_size);
|
||||
|
||||
unsigned char PesHeader[PES_MAX_HEADER_SIZE + sizeof(Vc1FrameStartCode)];
|
||||
int32_t ic = 0;
|
||||
struct iovec iov[5];
|
||||
unsigned int PacketLength = 0;
|
||||
|
||||
iov[ic++].iov_base = PesHeader;
|
||||
if (initialHeader)
|
||||
{
|
||||
initialHeader = 0;
|
||||
if (videocodecdata.data)
|
||||
{
|
||||
free(videocodecdata.data);
|
||||
videocodecdata.data = NULL;
|
||||
}
|
||||
|
||||
unsigned int codec_size = call->private_size;
|
||||
if (codec_size > 4) codec_size = 4;
|
||||
|
||||
videocodecdata.length = 33;
|
||||
uint8_t *data = videocodecdata.data = malloc(videocodecdata.length);
|
||||
memset(videocodecdata.data, 0, videocodecdata.length);
|
||||
data += 18;
|
||||
/* width */
|
||||
*(data++) = (call->Width >> 8) & 0xff;
|
||||
*(data++) = call->Width & 0xff;
|
||||
/* height */
|
||||
*(data++) = (call->Height >> 8) & 0xff;
|
||||
*(data++) = call->Height & 0xff;
|
||||
if (call->private_data && codec_size) memcpy(data, call->private_data, codec_size);
|
||||
if (STB_DREAMBOX == GetSTBType() || 0 != ioctl(call->fd, VIDEO_SET_CODEC_DATA, &videocodecdata))
|
||||
{
|
||||
iov[ic].iov_base = videocodecdata.data;
|
||||
iov[ic++].iov_len = videocodecdata.length;
|
||||
PacketLength += videocodecdata.length;
|
||||
}
|
||||
}
|
||||
|
||||
uint8_t needFrameStartCode = 0;
|
||||
if (sizeof(Vc1FrameStartCode) >= call->len ||
|
||||
memcmp(call->data, Vc1FrameStartCode, sizeof(Vc1FrameStartCode)) != 0)
|
||||
{
|
||||
needFrameStartCode = 1;
|
||||
PacketLength += sizeof(Vc1FrameStartCode);
|
||||
}
|
||||
|
||||
iov[ic].iov_base = call->data;
|
||||
iov[ic++].iov_len = call->len;
|
||||
PacketLength += call->len;
|
||||
|
||||
iov[0].iov_len = InsertPesHeader(PesHeader, PacketLength, MPEG_VIDEO_PES_START_CODE, call->Pts, 0);
|
||||
|
||||
/* some mipsel receiver(s) like et4x00 needs to have Copy(0)/Original(1) flag set to Original */
|
||||
PesHeader[6] |= 1;
|
||||
|
||||
if (needFrameStartCode)
|
||||
{
|
||||
memcpy(PesHeader + iov[0].iov_len, Vc1FrameStartCode, sizeof(Vc1FrameStartCode));
|
||||
iov[0].iov_len += sizeof(Vc1FrameStartCode);
|
||||
}
|
||||
|
||||
if (videocodecdata.data)
|
||||
{
|
||||
free(videocodecdata.data);
|
||||
videocodecdata.data = NULL;
|
||||
}
|
||||
|
||||
return call->WriteV(call->fd, iov, ic);
|
||||
}
|
||||
|
||||
/* ***************************** */
|
||||
/* Writer Definition */
|
||||
/* ***************************** */
|
||||
|
||||
static WriterCaps_t caps =
|
||||
{
|
||||
"wmv",
|
||||
eVideo,
|
||||
"V_WMV",
|
||||
VIDEO_ENCODING_WMV,
|
||||
STREAMTYPE_VC1_SM,
|
||||
CT_MPEG4_PART2
|
||||
};
|
||||
|
||||
struct Writer_s WriterVideoWMV =
|
||||
{
|
||||
&reset,
|
||||
&writeData,
|
||||
&caps
|
||||
};
|
310
libeplayer3/output/writer/mipsel/writer.c
Normal file
310
libeplayer3/output/writer/mipsel/writer.c
Normal file
@@ -0,0 +1,310 @@
|
||||
/*
|
||||
* linuxdvb output/writer handling.
|
||||
*
|
||||
* konfetti 2010
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*
|
||||
*/
|
||||
|
||||
/* ***************************** */
|
||||
/* Includes */
|
||||
/* ***************************** */
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <errno.h>
|
||||
#include <pthread.h>
|
||||
|
||||
#include "misc.h"
|
||||
#include "writer.h"
|
||||
#include "common.h"
|
||||
#include "debug.h"
|
||||
|
||||
/* ***************************** */
|
||||
/* Makros/Constants */
|
||||
/* ***************************** */
|
||||
|
||||
#define getDVBMutex(pmtx) do { if (pmtx) pthread_mutex_lock(pmtx);} while(false);
|
||||
#define releaseDVBMutex(pmtx) do { if (pmtx) pthread_mutex_unlock(pmtx);} while(false);
|
||||
|
||||
/* ***************************** */
|
||||
/* Types */
|
||||
/* ***************************** */
|
||||
|
||||
typedef enum
|
||||
{
|
||||
DVB_STS_UNKNOWN,
|
||||
DVB_STS_SEEK,
|
||||
DVB_STS_PAUSE,
|
||||
DVB_STS_EXIT
|
||||
} DVBState_t;
|
||||
|
||||
/* ***************************** */
|
||||
/* Variables */
|
||||
/* ***************************** */
|
||||
|
||||
static Writer_t *AvailableWriter[] =
|
||||
{
|
||||
&WriterAudioAAC,
|
||||
&WriterAudioAACLATM,
|
||||
&WriterAudioAACPLUS,
|
||||
&WriterAudioAC3,
|
||||
&WriterAudioEAC3,
|
||||
&WriterAudioMP3,
|
||||
&WriterAudioMPEGL3,
|
||||
&WriterAudioPCM,
|
||||
&WriterAudioIPCM,
|
||||
&WriterAudioLPCM,
|
||||
&WriterAudioDTS,
|
||||
&WriterAudioWMA,
|
||||
&WriterAudioWMAPRO,
|
||||
|
||||
&WriterVideoH264,
|
||||
&WriterVideoH265,
|
||||
&WriterVideoH263,
|
||||
&WriterVideoMPEG4,
|
||||
&WriterVideoMPEG2,
|
||||
&WriterVideoMPEG1,
|
||||
&WriterVideoVC1,
|
||||
&WriterVideoDIVX3,
|
||||
&WriterVideoVP6,
|
||||
&WriterVideoVP8,
|
||||
&WriterVideoVP9,
|
||||
&WriterVideoFLV,
|
||||
&WriterVideoWMV,
|
||||
&WriterVideoMJPEG,
|
||||
NULL
|
||||
};
|
||||
|
||||
/* ***************************** */
|
||||
/* Prototypes */
|
||||
/* ***************************** */
|
||||
|
||||
/* ***************************** */
|
||||
/* Functions */
|
||||
/* ***************************** */
|
||||
|
||||
ssize_t WriteWithRetry(Context_t *context, int pipefd, int fd, void *pDVBMtx __attribute__((unused)), const void *buf, int size)
|
||||
{
|
||||
fd_set rfds;
|
||||
fd_set wfds;
|
||||
|
||||
ssize_t ret;
|
||||
int retval = -1;
|
||||
int maxFd = pipefd > fd ? pipefd : fd;
|
||||
struct timeval tv;
|
||||
|
||||
static bool first = true;
|
||||
if (first && STB_HISILICON == GetSTBType())
|
||||
{
|
||||
// workaround: playback of some files does not start
|
||||
// if injection of the frist frame is to fast
|
||||
usleep(100000);
|
||||
}
|
||||
first = false;
|
||||
|
||||
while (size > 0 && 0 == PlaybackDieNow(0) && !context->playback->isSeeking)
|
||||
{
|
||||
FD_ZERO(&rfds);
|
||||
FD_ZERO(&wfds);
|
||||
|
||||
FD_SET(pipefd, &rfds);
|
||||
FD_SET(fd, &wfds);
|
||||
|
||||
/* When we PAUSE LINUX DVB outputs buffers, then audio/video buffers
|
||||
* will continue to be filled. Unfortunately, in such case after resume
|
||||
* select() will never return with fd set - bug in DVB drivers?
|
||||
* There are to workarounds possible:
|
||||
* 1. write to pipe at resume to return from select() immediately
|
||||
* 2. make timeout select(), limit max time spend in the select()
|
||||
* to for example 0,1s
|
||||
* (at now first workaround is used)
|
||||
*/
|
||||
//tv.tv_sec = 0;
|
||||
//tv.tv_usec = 100000; // 100ms
|
||||
|
||||
retval = select(maxFd + 1, &rfds, &wfds, NULL, NULL); //&tv);
|
||||
if (retval < 0)
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
//if (retval == 0)
|
||||
//{
|
||||
// //printf("RETURN FROM SELECT DUE TO TIMEOUT\n");
|
||||
// continue;
|
||||
//}
|
||||
|
||||
if (FD_ISSET(pipefd, &rfds))
|
||||
{
|
||||
FlushPipe(pipefd);
|
||||
//printf("RETURN FROM SELECT DUE TO pipefd SET\n");
|
||||
continue;
|
||||
}
|
||||
|
||||
if (FD_ISSET(fd, &wfds))
|
||||
{
|
||||
ret = write(fd, buf, size);
|
||||
if (ret < 0)
|
||||
{
|
||||
switch (errno)
|
||||
{
|
||||
case EINTR:
|
||||
case EAGAIN:
|
||||
continue;
|
||||
default:
|
||||
retval = -3;
|
||||
break;
|
||||
}
|
||||
if (retval < 0)
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
else if (ret == 0)
|
||||
{
|
||||
// printf("This should not happen. Select return fd ready to write, but write return 0, errno [%d]\n", errno);
|
||||
// wait 10ms before next try
|
||||
tv.tv_sec = 0;
|
||||
tv.tv_usec = 10000; // 10ms
|
||||
retval = select(pipefd + 1, &rfds, NULL, NULL, &tv);
|
||||
if (retval)
|
||||
FlushPipe(pipefd);
|
||||
continue;
|
||||
}
|
||||
|
||||
size -= ret;
|
||||
buf += ret;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
ssize_t write_with_retry(int fd, const void *buf, int size)
|
||||
{
|
||||
ssize_t ret;
|
||||
int retval = 0;
|
||||
while (size > 0 && 0 == PlaybackDieNow(0))
|
||||
{
|
||||
ret = write(fd, buf, size);
|
||||
if (ret < 0)
|
||||
{
|
||||
switch (errno)
|
||||
{
|
||||
case EINTR:
|
||||
case EAGAIN:
|
||||
usleep(1000);
|
||||
continue;
|
||||
default:
|
||||
retval = -3;
|
||||
break;
|
||||
}
|
||||
if (retval < 0)
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (ret < 0)
|
||||
{
|
||||
return ret;
|
||||
}
|
||||
|
||||
size -= ret;
|
||||
buf += ret;
|
||||
|
||||
if (size > 0)
|
||||
{
|
||||
if (usleep(1000))
|
||||
{
|
||||
writer_err("usleep error \n");
|
||||
}
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
ssize_t writev_with_retry(int fd, const struct iovec *iov, int ic)
|
||||
{
|
||||
ssize_t len = 0;
|
||||
int i = 0;
|
||||
for (i = 0; i < ic; ++i)
|
||||
{
|
||||
write_with_retry(fd, iov[i].iov_base, iov[i].iov_len);
|
||||
len += iov[i].iov_len;
|
||||
if (PlaybackDieNow(0))
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
return len;
|
||||
}
|
||||
|
||||
Writer_t *getWriter(char *encoding)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; AvailableWriter[i] != NULL; i++)
|
||||
{
|
||||
if (strcmp(AvailableWriter[i]->caps->textEncoding, encoding) == 0)
|
||||
{
|
||||
writer_printf(50, "%s: found writer \"%s\" for \"%s\"\n", __func__, AvailableWriter[i]->caps->name, encoding);
|
||||
return AvailableWriter[i];
|
||||
}
|
||||
}
|
||||
|
||||
writer_printf(1, "%s: no writer found for \"%s\"\n", __func__, encoding);
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
Writer_t *getDefaultVideoWriter()
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; AvailableWriter[i] != NULL; i++)
|
||||
{
|
||||
if (strcmp(AvailableWriter[i]->caps->textEncoding, "V_MPEG2") == 0)
|
||||
{
|
||||
writer_printf(50, "%s: found writer \"%s\"\n", __func__, AvailableWriter[i]->caps->name);
|
||||
return AvailableWriter[i];
|
||||
}
|
||||
}
|
||||
|
||||
writer_printf(1, "%s: no writer found\n", __func__);
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
Writer_t *getDefaultAudioWriter()
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; AvailableWriter[i] != NULL; i++)
|
||||
{
|
||||
if (strcmp(AvailableWriter[i]->caps->textEncoding, "A_MP3") == 0)
|
||||
{
|
||||
writer_printf(50, "%s: found writer \"%s\"\n", __func__, AvailableWriter[i]->caps->name);
|
||||
return AvailableWriter[i];
|
||||
}
|
||||
}
|
||||
|
||||
writer_printf(1, "%s: no writer found\n", __func__);
|
||||
|
||||
return NULL;
|
||||
}
|
383
libeplayer3/output/writer/sh4/aac.c
Normal file
383
libeplayer3/output/writer/sh4/aac.c
Normal file
@@ -0,0 +1,383 @@
|
||||
/*
|
||||
* linuxdvb output/writer handling.
|
||||
*
|
||||
* konfetti 2010 based on linuxdvb.c code from libeplayer2
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*
|
||||
*/
|
||||
|
||||
/* ***************************** */
|
||||
/* Includes */
|
||||
/* ***************************** */
|
||||
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
#include <unistd.h>
|
||||
#include <fcntl.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
#include <sys/ioctl.h>
|
||||
#include <linux/dvb/video.h>
|
||||
#include <linux/dvb/audio.h>
|
||||
#include <memory.h>
|
||||
#include <asm/types.h>
|
||||
#include <pthread.h>
|
||||
#include <errno.h>
|
||||
#include <sys/uio.h>
|
||||
|
||||
#include <libavutil/intreadwrite.h>
|
||||
#include "ffmpeg/latmenc.h"
|
||||
#include "stm_ioctls.h"
|
||||
|
||||
#include "common.h"
|
||||
#include "output.h"
|
||||
#include "debug.h"
|
||||
#include "misc.h"
|
||||
#include "pes.h"
|
||||
#include "writer.h"
|
||||
#include "aac.h"
|
||||
|
||||
/* ***************************** */
|
||||
/* Makros/Constants */
|
||||
/* ***************************** */
|
||||
|
||||
/* ***************************** */
|
||||
/* Types */
|
||||
/* ***************************** */
|
||||
|
||||
/* ***************************** */
|
||||
/* Variables */
|
||||
/* ***************************** */
|
||||
|
||||
/// ** AAC ADTS format **
|
||||
///
|
||||
/// AAAAAAAA AAAABCCD EEFFFFGH HHIJKLMM
|
||||
/// MMMMMMMM MMMNNNNN NNNNNNOO ........
|
||||
///
|
||||
/// Sign Length Position Description
|
||||
///
|
||||
/// A 12 (31-20) Sync code
|
||||
/// B 1 (19) ID
|
||||
/// C 2 (18-17) layer
|
||||
/// D 1 (16) protect absent
|
||||
/// E 2 (15-14) profile
|
||||
/// F 4 (13-10) sample freq index
|
||||
/// G 1 (9) private
|
||||
/// H 3 (8-6) channel config
|
||||
/// I 1 (5) original/copy
|
||||
/// J 1 (4) home
|
||||
/// K 1 (3) copyright id
|
||||
/// L 1 (2) copyright start
|
||||
/// M 13 (1-0,31-21) frame length
|
||||
/// N 11 (20-10) adts buffer fullness
|
||||
/// O 2 (9-8) num of raw data blocks in frame
|
||||
|
||||
/*
|
||||
LC: Audio: aac, 44100 Hz, stereo, s16, 192 kb/ ->ff f1 50 80 00 1f fc
|
||||
HE: Audio: aac, 48000 Hz, stereo, s16, 77 kb/s ->ff f1 4c 80 00 1f fc
|
||||
*/
|
||||
|
||||
/*
|
||||
ADIF = basic format called Audio Data Interchange Format (ADIF)
|
||||
consisting of a single header followed by the raw AAC audio data blocks
|
||||
ADTS = streaming format called Audio Data Transport Stream (ADTS)
|
||||
consisting of a series of frames, each frame having a header followed by the AAC audio data
|
||||
LOAS = Low Overhead Audio Stream (LOAS), a self-synchronizing streaming format
|
||||
*/
|
||||
|
||||
static unsigned char DefaultAACHeader[] =
|
||||
{
|
||||
0xff,
|
||||
0xf1,
|
||||
/*0x00, 0x00*/0x50, //((Profile & 0x03) << 6) | (SampleIndex << 2) | ((Channels >> 2) & 0x01);s
|
||||
0x80, //(Channels & 0x03) << 6;
|
||||
0x00,
|
||||
0x1f,
|
||||
0xfc
|
||||
};
|
||||
|
||||
LATMContext *pLATMCtx = NULL;
|
||||
|
||||
/* ***************************** */
|
||||
/* Prototypes */
|
||||
/* ***************************** */
|
||||
|
||||
/* ***************************** */
|
||||
/* MISC Functions */
|
||||
/* ***************************** */
|
||||
|
||||
static int reset()
|
||||
{
|
||||
if (pLATMCtx)
|
||||
{
|
||||
free(pLATMCtx);
|
||||
pLATMCtx = NULL;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int _writeData(void *_call, int type)
|
||||
{
|
||||
WriterAVCallData_t *call = (WriterAVCallData_t *) _call;
|
||||
|
||||
aac_printf(10, "\n _writeData type[%d]\n", type);
|
||||
|
||||
if (call == NULL)
|
||||
{
|
||||
aac_err("call data is NULL...\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
if ((call->data == NULL) || (call->len < 8))
|
||||
{
|
||||
aac_err("parsing Data with missing AAC header. ignoring...\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* simple validation */
|
||||
if (0 == type) // check ADTS header
|
||||
{
|
||||
if (0xFF != call->data[0] || 0xF0 != (0xF0 & call->data[1]))
|
||||
{
|
||||
aac_err("parsing Data with missing syncword. ignoring...\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
// STB can handle only AAC LC profile
|
||||
if (0 == (call->data[2] & 0xC0))
|
||||
{
|
||||
// change profile AAC Main -> AAC LC (Low Complexity)
|
||||
aac_printf(1, "change profile AAC Main -> AAC LC (Low Complexity) in the ADTS header");
|
||||
call->data[2] = (call->data[2] & 0x1F) | 0x40;
|
||||
}
|
||||
}
|
||||
else // check LOAS header
|
||||
{
|
||||
if (!(call->len > 2 && call->data[0] == 0x56 && (call->data[1] >> 4) == 0xe &&
|
||||
(AV_RB16(call->data + 1) & 0x1FFF) + 3 == call->len))
|
||||
{
|
||||
aac_err("parsing Data with wrong latm header. ignoring...\n");
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
unsigned char PesHeader[PES_MAX_HEADER_SIZE];
|
||||
|
||||
aac_printf(10, "AudioPts %lld\n", call->Pts);
|
||||
|
||||
unsigned int HeaderLength = InsertPesHeader(PesHeader, call->len, MPEG_AUDIO_PES_START_CODE, call->Pts, 0);
|
||||
|
||||
struct iovec iov[2];
|
||||
iov[0].iov_base = PesHeader;
|
||||
iov[0].iov_len = HeaderLength;
|
||||
iov[1].iov_base = call->data;
|
||||
iov[1].iov_len = call->len;
|
||||
return call->WriteV(call->fd, iov, 2);
|
||||
}
|
||||
|
||||
static int writeDataADTS(void *_call)
|
||||
{
|
||||
WriterAVCallData_t *call = (WriterAVCallData_t *) _call;
|
||||
|
||||
aac_printf(10, "\n");
|
||||
|
||||
if (call == NULL)
|
||||
{
|
||||
aac_err("call data is NULL...\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
if ((call->data == NULL) || (call->len <= 0))
|
||||
{
|
||||
aac_err("parsing NULL Data. ignoring...\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (call->fd < 0)
|
||||
{
|
||||
aac_err("file pointer < 0. ignoring ...\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
if ((call->private_data && 0 == strncmp("ADTS", call->private_data, call->private_size)) ||
|
||||
HasADTSHeader(call->data, call->len))
|
||||
{
|
||||
return _writeData(_call, 0);
|
||||
}
|
||||
|
||||
uint32_t PacketLength = call->len + AAC_HEADER_LENGTH;
|
||||
uint8_t PesHeader[PES_MAX_HEADER_SIZE + AAC_HEADER_LENGTH];
|
||||
uint32_t headerSize = InsertPesHeader(PesHeader, PacketLength, MPEG_AUDIO_PES_START_CODE, call->Pts, 0);
|
||||
uint8_t *pExtraData = &PesHeader[headerSize];
|
||||
|
||||
aac_printf(10, "AudioPts %lld\n", call->Pts);
|
||||
if (call->private_data == NULL)
|
||||
{
|
||||
aac_printf(10, "private_data = NULL\n");
|
||||
memcpy(pExtraData, DefaultAACHeader, AAC_HEADER_LENGTH);
|
||||
}
|
||||
else
|
||||
{
|
||||
memcpy(pExtraData, call->private_data, AAC_HEADER_LENGTH);
|
||||
}
|
||||
|
||||
pExtraData[3] &= 0xC0;
|
||||
/* frame size over last 2 bits */
|
||||
pExtraData[3] |= (PacketLength & 0x1800) >> 11;
|
||||
/* frame size continued over full byte */
|
||||
pExtraData[4] = (PacketLength & 0x1FF8) >> 3;
|
||||
/* frame size continued first 3 bits */
|
||||
pExtraData[5] = (PacketLength & 7) << 5;
|
||||
/* buffer fullness(0x7FF for VBR) over 5 last bits */
|
||||
pExtraData[5] |= 0x1F;
|
||||
/* buffer fullness(0x7FF for VBR) continued over 6 first bits + 2 zeros for
|
||||
* number of raw data blocks */
|
||||
pExtraData[6] = 0xFC;
|
||||
|
||||
struct iovec iov[2];
|
||||
iov[0].iov_base = PesHeader;
|
||||
iov[0].iov_len = headerSize + AAC_HEADER_LENGTH;
|
||||
iov[1].iov_base = call->data;
|
||||
iov[1].iov_len = call->len;
|
||||
|
||||
return call->WriteV(call->fd, iov, 2);
|
||||
}
|
||||
|
||||
static int writeDataLATM(void *_call)
|
||||
{
|
||||
WriterAVCallData_t *call = (WriterAVCallData_t *) _call;
|
||||
|
||||
aac_printf(10, "\n");
|
||||
|
||||
if (call == NULL)
|
||||
{
|
||||
aac_err("call data is NULL...\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
if ((call->data == NULL) || (call->len <= 0))
|
||||
{
|
||||
aac_err("parsing NULL Data. ignoring...\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (call->private_data && 0 == strncmp("LATM", call->private_data, call->private_size))
|
||||
{
|
||||
return _writeData(_call, 1);
|
||||
}
|
||||
|
||||
aac_printf(10, "AudioPts %lld\n", call->Pts);
|
||||
|
||||
if (!pLATMCtx)
|
||||
{
|
||||
pLATMCtx = malloc(sizeof(LATMContext));
|
||||
memset(pLATMCtx, 0x00, sizeof(LATMContext));
|
||||
pLATMCtx->mod = 14;
|
||||
pLATMCtx->counter = 0;
|
||||
}
|
||||
|
||||
if (!pLATMCtx)
|
||||
{
|
||||
aac_err("parsing NULL pLATMCtx. ignoring...\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
unsigned char PesHeader[PES_MAX_HEADER_SIZE];
|
||||
int ret = latmenc_decode_extradata(pLATMCtx, call->private_data, call->private_size);
|
||||
if (ret)
|
||||
{
|
||||
//printf("%02x %02x %02x %02x %02x %02x %02x %02x\n", (int)call->data[0], (int)call->data[1], (int)call->data[2], (int)call->data[3], \
|
||||
// (int)call->data[4], (int)call->data[5], (int)call->data[6], (int)call->data[7]);
|
||||
aac_err("latm_decode_extradata failed. ignoring...\n");
|
||||
return 0;
|
||||
}
|
||||
ret = latmenc_write_packet(pLATMCtx, call->data, call->len, call->private_data, call->private_size);
|
||||
if (ret)
|
||||
{
|
||||
aac_err("latm_write_packet failed. ignoring...\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
unsigned int HeaderLength = InsertPesHeader(PesHeader, pLATMCtx->len + 3, MPEG_AUDIO_PES_START_CODE, call->Pts, 0);
|
||||
|
||||
struct iovec iov[3];
|
||||
iov[0].iov_base = PesHeader;
|
||||
iov[0].iov_len = HeaderLength;
|
||||
|
||||
iov[1].iov_base = pLATMCtx->loas_header;
|
||||
iov[1].iov_len = 3;
|
||||
|
||||
iov[2].iov_base = pLATMCtx->buffer;
|
||||
iov[2].iov_len = pLATMCtx->len;
|
||||
|
||||
return call->WriteV(call->fd, iov, 3);
|
||||
}
|
||||
|
||||
/* ***************************** */
|
||||
/* Writer Definition */
|
||||
/* ***************************** */
|
||||
|
||||
static WriterCaps_t caps =
|
||||
{
|
||||
"aac",
|
||||
eAudio,
|
||||
"A_AAC",
|
||||
AUDIO_ENCODING_AAC,
|
||||
-1,
|
||||
-1
|
||||
};
|
||||
|
||||
struct Writer_s WriterAudioAAC =
|
||||
{
|
||||
&reset,
|
||||
&writeDataADTS,
|
||||
&caps
|
||||
};
|
||||
|
||||
static WriterCaps_t caps_aac_latm =
|
||||
{
|
||||
"aac",
|
||||
eAudio,
|
||||
"A_AAC_LATM",
|
||||
AUDIO_ENCODING_AAC,
|
||||
-1, // it is some misunderstanding, this should be AUDIOTYPE_AAC_LATM
|
||||
-1
|
||||
};
|
||||
|
||||
struct Writer_s WriterAudioAACLATM =
|
||||
{
|
||||
&reset,
|
||||
&writeDataLATM,
|
||||
&caps_aac_latm
|
||||
};
|
||||
|
||||
static WriterCaps_t caps_aacplus =
|
||||
{
|
||||
"aac",
|
||||
eAudio,
|
||||
"A_AAC_PLUS",
|
||||
AUDIO_ENCODING_AAC,
|
||||
-1,
|
||||
-1
|
||||
};
|
||||
|
||||
struct Writer_s WriterAudioAACPLUS =
|
||||
{
|
||||
&reset,
|
||||
&writeDataADTS,
|
||||
&caps_aacplus
|
||||
};
|
150
libeplayer3/output/writer/sh4/ac3.c
Normal file
150
libeplayer3/output/writer/sh4/ac3.c
Normal file
@@ -0,0 +1,150 @@
|
||||
/*
|
||||
* linuxdvb output/writer handling.
|
||||
*
|
||||
* konfetti 2010 based on linuxdvb.c code from libeplayer2
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*
|
||||
*/
|
||||
|
||||
/* ***************************** */
|
||||
/* Includes */
|
||||
/* ***************************** */
|
||||
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
#include <unistd.h>
|
||||
#include <fcntl.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
#include <sys/ioctl.h>
|
||||
#include <sys/uio.h>
|
||||
#include <linux/dvb/video.h>
|
||||
#include <linux/dvb/audio.h>
|
||||
#include <memory.h>
|
||||
#include <asm/types.h>
|
||||
#include <pthread.h>
|
||||
#include <errno.h>
|
||||
|
||||
#include "stm_ioctls.h"
|
||||
#include "common.h"
|
||||
#include "output.h"
|
||||
#include "debug.h"
|
||||
#include "misc.h"
|
||||
#include "pes.h"
|
||||
#include "writer.h"
|
||||
|
||||
/* ***************************** */
|
||||
/* Makros/Constants */
|
||||
/* ***************************** */
|
||||
#define AC3_HEADER_LENGTH 7
|
||||
|
||||
/* ***************************** */
|
||||
/* Types */
|
||||
/* ***************************** */
|
||||
|
||||
/* ***************************** */
|
||||
/* Variables */
|
||||
/* ***************************** */
|
||||
|
||||
/* ***************************** */
|
||||
/* Prototypes */
|
||||
/* ***************************** */
|
||||
|
||||
/* ***************************** */
|
||||
/* MISC Functions */
|
||||
/* ***************************** */
|
||||
|
||||
static int reset()
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int writeData(void *_call)
|
||||
{
|
||||
WriterAVCallData_t *call = (WriterAVCallData_t *) _call;
|
||||
|
||||
ac3_printf(10, "\n");
|
||||
|
||||
unsigned char PesHeader[PES_MAX_HEADER_SIZE];
|
||||
|
||||
if (call == NULL)
|
||||
{
|
||||
ac3_err("call data is NULL...\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
ac3_printf(10, "AudioPts %lld\n", call->Pts);
|
||||
|
||||
if ((call->data == NULL) || (call->len <= 0))
|
||||
{
|
||||
ac3_err("parsing NULL Data. ignoring...\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (call->fd < 0)
|
||||
{
|
||||
ac3_err("file pointer < 0. ignoring ...\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
struct iovec iov[2];
|
||||
|
||||
iov[0].iov_base = PesHeader;
|
||||
iov[0].iov_len = InsertPesHeader(PesHeader, call->len, PRIVATE_STREAM_1_PES_START_CODE, call->Pts, 0);
|
||||
iov[1].iov_base = call->data;
|
||||
iov[1].iov_len = call->len;
|
||||
|
||||
return call->WriteV(call->fd, iov, 2);
|
||||
}
|
||||
|
||||
/* ***************************** */
|
||||
/* Writer Definition */
|
||||
/* ***************************** */
|
||||
|
||||
static WriterCaps_t caps_ac3 =
|
||||
{
|
||||
"ac3",
|
||||
eAudio,
|
||||
"A_AC3",
|
||||
AUDIO_ENCODING_AC3,
|
||||
-1,
|
||||
-1
|
||||
};
|
||||
|
||||
struct Writer_s WriterAudioAC3 =
|
||||
{
|
||||
&reset,
|
||||
&writeData,
|
||||
&caps_ac3
|
||||
};
|
||||
|
||||
static WriterCaps_t caps_eac3 =
|
||||
{
|
||||
"ac3",
|
||||
eAudio,
|
||||
"A_EAC3",
|
||||
AUDIO_ENCODING_AC3,
|
||||
-1,
|
||||
-1
|
||||
};
|
||||
|
||||
struct Writer_s WriterAudioEAC3 =
|
||||
{
|
||||
&reset,
|
||||
&writeData,
|
||||
&caps_eac3
|
||||
};
|
227
libeplayer3/output/writer/sh4/divx.c
Normal file
227
libeplayer3/output/writer/sh4/divx.c
Normal file
@@ -0,0 +1,227 @@
|
||||
/*
|
||||
* linuxdvb output/writer handling.
|
||||
*
|
||||
* konfetti 2010 based on linuxdvb.c code from libeplayer2
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*
|
||||
*/
|
||||
|
||||
/* ***************************** */
|
||||
/* Includes */
|
||||
/* ***************************** */
|
||||
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
#include <unistd.h>
|
||||
#include <fcntl.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
#include <sys/ioctl.h>
|
||||
#include <sys/uio.h>
|
||||
#include <linux/dvb/video.h>
|
||||
#include <linux/dvb/audio.h>
|
||||
#include <memory.h>
|
||||
#include <asm/types.h>
|
||||
#include <pthread.h>
|
||||
#include <errno.h>
|
||||
|
||||
#include "stm_ioctls.h"
|
||||
#include "common.h"
|
||||
#include "output.h"
|
||||
#include "debug.h"
|
||||
#include "misc.h"
|
||||
#include "pes.h"
|
||||
#include "writer.h"
|
||||
|
||||
/* ***************************** */
|
||||
/* Makros/Constants */
|
||||
/* ***************************** */
|
||||
|
||||
/* ***************************** */
|
||||
/* Types */
|
||||
/* ***************************** */
|
||||
|
||||
/* ***************************** */
|
||||
/* Variables */
|
||||
/* ***************************** */
|
||||
|
||||
static int initialHeader = 1;
|
||||
|
||||
/* ***************************** */
|
||||
/* Prototypes */
|
||||
/* ***************************** */
|
||||
|
||||
/* ***************************** */
|
||||
/* MISC Functions */
|
||||
/* ***************************** */
|
||||
|
||||
static int reset()
|
||||
{
|
||||
initialHeader = 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static uint8_t updateCodecData(uint8_t *data, int32_t size)
|
||||
{
|
||||
static uint8_t *oldData = NULL;
|
||||
static int32_t oldSize = 0;
|
||||
|
||||
uint8_t update = 0;
|
||||
if (data != NULL && size > 0)
|
||||
{
|
||||
if (size != oldSize)
|
||||
{
|
||||
update = 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
uint32_t i = 0;
|
||||
for (i = 0; i < size; i++)
|
||||
{
|
||||
if (data[i] != oldData[i])
|
||||
{
|
||||
update = 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (update)
|
||||
{
|
||||
if (oldData != NULL)
|
||||
{
|
||||
free(oldData);
|
||||
}
|
||||
oldData = malloc(size);
|
||||
memcpy(oldData, data, size);
|
||||
oldSize = size;
|
||||
}
|
||||
|
||||
return update;
|
||||
}
|
||||
|
||||
static int writeData(void *_call)
|
||||
{
|
||||
WriterAVCallData_t *call = (WriterAVCallData_t *) _call;
|
||||
|
||||
unsigned char PesHeader[PES_MAX_HEADER_SIZE];
|
||||
|
||||
divx_printf(10, "\n");
|
||||
|
||||
if (call == NULL)
|
||||
{
|
||||
divx_err("call data is NULL...\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
if ((call->data == NULL) || (call->len <= 0))
|
||||
{
|
||||
divx_err("parsing NULL Data. ignoring...\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (call->fd < 0)
|
||||
{
|
||||
divx_err("file pointer < 0. ignoring ...\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
divx_printf(10, "VideoPts %lld\n", call->Pts);
|
||||
|
||||
struct iovec iov[4];
|
||||
int ic = 0;
|
||||
iov[ic].iov_base = PesHeader;
|
||||
iov[ic++].iov_len = InsertPesHeader(PesHeader, call->len, MPEG_VIDEO_PES_START_CODE, call->Pts, 0);
|
||||
|
||||
if (updateCodecData(call->private_data, call->private_size))
|
||||
{
|
||||
iov[ic].iov_base = call->private_data;
|
||||
iov[ic++].iov_len = call->private_size;
|
||||
}
|
||||
|
||||
iov[ic].iov_base = call->data;
|
||||
iov[ic++].iov_len = call->len;
|
||||
|
||||
int len = call->WriteV(call->fd, iov, ic);
|
||||
|
||||
divx_printf(10, "xvid_Write < len=%d\n", len);
|
||||
|
||||
return len;
|
||||
}
|
||||
|
||||
/* ***************************** */
|
||||
/* Writer Definition */
|
||||
/* ***************************** */
|
||||
|
||||
static WriterCaps_t mpeg4p2_caps =
|
||||
{
|
||||
"mpeg4p2",
|
||||
eVideo,
|
||||
"V_MPEG4",
|
||||
VIDEO_ENCODING_MPEG4P2,
|
||||
-1,
|
||||
-1
|
||||
};
|
||||
|
||||
struct Writer_s WriterVideoMPEG4 =
|
||||
{
|
||||
&reset,
|
||||
&writeData,
|
||||
&mpeg4p2_caps
|
||||
};
|
||||
|
||||
struct Writer_s WriterVideoMSCOMP =
|
||||
{
|
||||
&reset,
|
||||
&writeData,
|
||||
&mpeg4p2_caps
|
||||
};
|
||||
|
||||
static WriterCaps_t fourcc_caps =
|
||||
{
|
||||
"fourcc",
|
||||
eVideo,
|
||||
"V_MS/VFW/FOURCC",
|
||||
VIDEO_ENCODING_MPEG4P2,
|
||||
-1,
|
||||
-1
|
||||
};
|
||||
|
||||
struct Writer_s WriterVideoFOURCC =
|
||||
{
|
||||
&reset,
|
||||
&writeData,
|
||||
&fourcc_caps
|
||||
};
|
||||
|
||||
static WriterCaps_t divx_caps =
|
||||
{
|
||||
"divx",
|
||||
eVideo,
|
||||
"V_MKV/XVID",
|
||||
VIDEO_ENCODING_MPEG4P2,
|
||||
-1,
|
||||
-1
|
||||
};
|
||||
|
||||
struct Writer_s WriterVideoDIVX =
|
||||
{
|
||||
&reset,
|
||||
&writeData,
|
||||
&divx_caps
|
||||
};
|
257
libeplayer3/output/writer/sh4/divx2.c
Normal file
257
libeplayer3/output/writer/sh4/divx2.c
Normal file
@@ -0,0 +1,257 @@
|
||||
/*
|
||||
* linuxdvb output/writer handling.
|
||||
*
|
||||
* konfetti 2010 based on linuxdvb.c code from libeplayer2
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*
|
||||
*/
|
||||
|
||||
/* ***************************** */
|
||||
/* Includes */
|
||||
/* ***************************** */
|
||||
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
#include <unistd.h>
|
||||
#include <fcntl.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
#include <sys/ioctl.h>
|
||||
#include <sys/uio.h>
|
||||
#include <linux/dvb/video.h>
|
||||
#include <linux/dvb/audio.h>
|
||||
#include <memory.h>
|
||||
#include <asm/types.h>
|
||||
#include <pthread.h>
|
||||
#include <errno.h>
|
||||
|
||||
#include "stm_ioctls.h"
|
||||
#include "common.h"
|
||||
#include "output.h"
|
||||
#include "debug.h"
|
||||
#include "misc.h"
|
||||
#include "pes.h"
|
||||
#include "writer.h"
|
||||
|
||||
/* ***************************** */
|
||||
/* Makros/Constants */
|
||||
/* ***************************** */
|
||||
|
||||
/* ***************************** */
|
||||
/* Types */
|
||||
/* ***************************** */
|
||||
|
||||
/* ***************************** */
|
||||
/* Variables */
|
||||
/* ***************************** */
|
||||
|
||||
static int initialHeader = 1;
|
||||
|
||||
/* ***************************** */
|
||||
/* Prototypes */
|
||||
/* ***************************** */
|
||||
|
||||
/* ***************************** */
|
||||
/* MISC Functions */
|
||||
/* ***************************** */
|
||||
|
||||
static int reset()
|
||||
{
|
||||
initialHeader = 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static uint8_t updateCodecData(uint8_t *data, int32_t size)
|
||||
{
|
||||
static uint8_t *oldData = NULL;
|
||||
static int32_t oldSize = 0;
|
||||
|
||||
uint8_t update = 0;
|
||||
if (data != NULL && size > 0)
|
||||
{
|
||||
if (size != oldSize)
|
||||
{
|
||||
update = 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
uint32_t i = 0;
|
||||
for (i = 0; i < size; i++)
|
||||
{
|
||||
if (data[i] != oldData[i])
|
||||
{
|
||||
update = 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (update)
|
||||
{
|
||||
if (oldData != NULL)
|
||||
{
|
||||
free(oldData);
|
||||
}
|
||||
oldData = malloc(size);
|
||||
memcpy(oldData, data, size);
|
||||
oldSize = size;
|
||||
}
|
||||
|
||||
return update;
|
||||
}
|
||||
|
||||
static int writeData(void *_call)
|
||||
{
|
||||
WriterAVCallData_t *call = (WriterAVCallData_t *) _call;
|
||||
|
||||
unsigned char PesHeader[PES_MAX_HEADER_SIZE];
|
||||
unsigned char FakeHeaders[64]; // 64bytes should be enough to make the fake headers
|
||||
unsigned int FakeHeaderLength;
|
||||
unsigned char Version = 5;
|
||||
unsigned int FakeStartCode = (Version << 8) | PES_VERSION_FAKE_START_CODE;
|
||||
unsigned int usecPerFrame = 41708; /* Hellmaster1024: default value */
|
||||
BitPacker_t ld = {FakeHeaders, 0, 32};
|
||||
|
||||
divx_printf(10, "\n");
|
||||
|
||||
if (call == NULL)
|
||||
{
|
||||
divx_err("call data is NULL...\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
if ((call->data == NULL) || (call->len <= 0))
|
||||
{
|
||||
divx_err("parsing NULL Data. ignoring...\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (call->fd < 0)
|
||||
{
|
||||
divx_err("file pointer < 0. ignoring ...\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
divx_printf(10, "AudioPts %lld\n", call->Pts);
|
||||
|
||||
usecPerFrame = 1000000000 / call->FrameRate;
|
||||
divx_printf(10, "Microsecends per frame = %d\n", usecPerFrame);
|
||||
|
||||
memset(FakeHeaders, 0, sizeof(FakeHeaders));
|
||||
|
||||
/* Create info record for frame parser */
|
||||
/* divx4 & 5
|
||||
VOS
|
||||
PutBits(&ld, 0x0, 8);
|
||||
PutBits(&ld, 0x0, 8);
|
||||
*/
|
||||
PutBits(&ld, 0x1b0, 32); // startcode
|
||||
PutBits(&ld, 0, 8); // profile = reserved
|
||||
PutBits(&ld, 0x1b2, 32); // startcode (user data)
|
||||
PutBits(&ld, 0x53545443, 32); // STTC - an embedded ST timecode from an avi file
|
||||
PutBits(&ld, usecPerFrame, 32);
|
||||
// microseconds per frame
|
||||
FlushBits(&ld);
|
||||
|
||||
FakeHeaderLength = (ld.Ptr - (FakeHeaders));
|
||||
|
||||
struct iovec iov[4];
|
||||
int ic = 0;
|
||||
iov[ic].iov_base = PesHeader;
|
||||
iov[ic++].iov_len = InsertPesHeader(PesHeader, call->len, MPEG_VIDEO_PES_START_CODE, call->Pts, FakeStartCode);
|
||||
iov[ic].iov_base = FakeHeaders;
|
||||
iov[ic++].iov_len = FakeHeaderLength;
|
||||
|
||||
if (initialHeader)
|
||||
{
|
||||
iov[ic].iov_base = call->private_data;
|
||||
iov[ic++].iov_len = call->private_size;
|
||||
initialHeader = 0;
|
||||
}
|
||||
|
||||
iov[ic].iov_base = call->data;
|
||||
iov[ic++].iov_len = call->len;
|
||||
|
||||
int len = call->WriteV(call->fd, iov, ic);
|
||||
|
||||
divx_printf(10, "xvid_Write < len=%d\n", len);
|
||||
|
||||
return len;
|
||||
}
|
||||
|
||||
/* ***************************** */
|
||||
/* Writer Definition */
|
||||
/* ***************************** */
|
||||
|
||||
static WriterCaps_t mpeg4p2_caps =
|
||||
{
|
||||
"mpeg4p2",
|
||||
eVideo,
|
||||
"V_MPEG4",
|
||||
VIDEO_ENCODING_MPEG4P2,
|
||||
-1,
|
||||
-1
|
||||
};
|
||||
|
||||
struct Writer_s WriterVideoMPEG4 =
|
||||
{
|
||||
&reset,
|
||||
&writeData,
|
||||
&mpeg4p2_caps
|
||||
};
|
||||
|
||||
struct Writer_s WriterVideoMSCOMP =
|
||||
{
|
||||
&reset,
|
||||
&writeData,
|
||||
&mpeg4p2_caps
|
||||
};
|
||||
|
||||
static WriterCaps_t fourcc_caps =
|
||||
{
|
||||
"fourcc",
|
||||
eVideo,
|
||||
"V_MS/VFW/FOURCC",
|
||||
VIDEO_ENCODING_MPEG4P2,
|
||||
-1,
|
||||
-1
|
||||
};
|
||||
|
||||
struct Writer_s WriterVideoFOURCC =
|
||||
{
|
||||
&reset,
|
||||
&writeData,
|
||||
&fourcc_caps
|
||||
};
|
||||
|
||||
static WriterCaps_t divx_caps =
|
||||
{
|
||||
"divx",
|
||||
eVideo,
|
||||
"V_MKV/XVID",
|
||||
VIDEO_ENCODING_MPEG4P2,
|
||||
-1,
|
||||
-1
|
||||
};
|
||||
|
||||
struct Writer_s WriterVideoDIVX =
|
||||
{
|
||||
&reset,
|
||||
&writeData,
|
||||
&divx_caps
|
||||
};
|
166
libeplayer3/output/writer/sh4/dts.c
Normal file
166
libeplayer3/output/writer/sh4/dts.c
Normal file
@@ -0,0 +1,166 @@
|
||||
/*
|
||||
* linuxdvb output/writer handling.
|
||||
*
|
||||
* konfetti 2010 based on linuxdvb.c code from libeplayer2
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*
|
||||
*/
|
||||
|
||||
/* ***************************** */
|
||||
/* Includes */
|
||||
/* ***************************** */
|
||||
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
#include <unistd.h>
|
||||
#include <fcntl.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
#include <sys/ioctl.h>
|
||||
#include <sys/uio.h>
|
||||
#include <linux/dvb/video.h>
|
||||
#include <linux/dvb/audio.h>
|
||||
#include <memory.h>
|
||||
#include <asm/types.h>
|
||||
#include <pthread.h>
|
||||
#include <errno.h>
|
||||
|
||||
#include "stm_ioctls.h"
|
||||
#include "common.h"
|
||||
#include "output.h"
|
||||
#include "debug.h"
|
||||
#include "misc.h"
|
||||
#include "pes.h"
|
||||
#include "writer.h"
|
||||
|
||||
/* ***************************** */
|
||||
/* Makros/Constants */
|
||||
/* ***************************** */
|
||||
|
||||
#define PES_AUDIO_PRIVATE_HEADER_SIZE 16 // consider maximum private header size.
|
||||
#define PES_AUDIO_HEADER_SIZE (32 + PES_AUDIO_PRIVATE_HEADER_SIZE)
|
||||
#define PES_AUDIO_PACKET_SIZE 2028
|
||||
#define SPDIF_AUDIO_PACKET_SIZE (1024 * sizeof(unsigned int) * 2) // stereo 32bit samples.
|
||||
|
||||
/* ***************************** */
|
||||
/* Types */
|
||||
/* ***************************** */
|
||||
|
||||
/* ***************************** */
|
||||
/* Variables */
|
||||
/* ***************************** */
|
||||
|
||||
/* ***************************** */
|
||||
/* Prototypes */
|
||||
/* ***************************** */
|
||||
|
||||
/* ***************************** */
|
||||
/* MISC Functions */
|
||||
/* ***************************** */
|
||||
|
||||
static int reset()
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int32_t writeData(void *_call)
|
||||
{
|
||||
WriterAVCallData_t *call = (WriterAVCallData_t *) _call;
|
||||
|
||||
uint8_t PesHeader[PES_AUDIO_HEADER_SIZE];
|
||||
|
||||
dts_printf(10, "\n");
|
||||
|
||||
if (call == NULL)
|
||||
{
|
||||
dts_err("call data is NULL...\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
dts_printf(10, "AudioPts %lld\n", call->Pts);
|
||||
|
||||
if ((call->data == NULL) || (call->len <= 0))
|
||||
{
|
||||
dts_err("parsing NULL Data. ignoring...\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (call->fd < 0)
|
||||
{
|
||||
dts_err("file pointer < 0. ignoring ...\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
uint8_t *Data = call->data;
|
||||
int32_t Size = call->len;
|
||||
|
||||
#ifdef CHECK_FOR_DTS_HD
|
||||
int32_t pos = 0;
|
||||
while ((pos + 4) <= Size)
|
||||
{
|
||||
// check for DTS-HD
|
||||
if (!strcmp((char *)(Data + pos), "\x64\x58\x20\x25"))
|
||||
{
|
||||
Size = pos;
|
||||
break;
|
||||
}
|
||||
++pos;
|
||||
}
|
||||
#endif
|
||||
|
||||
// #define DO_BYTESWAP
|
||||
#ifdef DO_BYTESWAP
|
||||
/* 16-bit byte swap all data before injecting it */
|
||||
for (i = 0; i < Size; i += 2)
|
||||
{
|
||||
uint8_t Tmp = Data[i];
|
||||
Data[i] = Data[i + 1];
|
||||
Data[i + 1] = Tmp;
|
||||
}
|
||||
#endif
|
||||
|
||||
struct iovec iov[2];
|
||||
iov[0].iov_base = PesHeader;
|
||||
iov[0].iov_len = InsertPesHeader(PesHeader, Size, MPEG_AUDIO_PES_START_CODE, call->Pts, 0);
|
||||
iov[1].iov_base = Data;
|
||||
iov[1].iov_len = Size;
|
||||
|
||||
int32_t len = call->WriteV(call->fd, iov, 2);
|
||||
dts_printf(10, "< len %d\n", len);
|
||||
return len;
|
||||
}
|
||||
|
||||
/* ***************************** */
|
||||
/* Writer Definition */
|
||||
/* ***************************** */
|
||||
|
||||
static WriterCaps_t caps =
|
||||
{
|
||||
"dts",
|
||||
eAudio,
|
||||
"A_DTS",
|
||||
AUDIO_ENCODING_DTS,
|
||||
-1,
|
||||
-1
|
||||
};
|
||||
|
||||
struct Writer_s WriterAudioDTS =
|
||||
{
|
||||
&reset,
|
||||
&writeData,
|
||||
&caps
|
||||
};
|
164
libeplayer3/output/writer/sh4/h263.c
Normal file
164
libeplayer3/output/writer/sh4/h263.c
Normal file
@@ -0,0 +1,164 @@
|
||||
/*
|
||||
* linuxdvb output/writer handling.
|
||||
*
|
||||
* crow 2010
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*
|
||||
*/
|
||||
|
||||
/* ***************************** */
|
||||
/* Includes */
|
||||
/* ***************************** */
|
||||
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
#include <unistd.h>
|
||||
#include <fcntl.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
#include <sys/ioctl.h>
|
||||
#include <linux/dvb/video.h>
|
||||
#include <linux/dvb/audio.h>
|
||||
#include <memory.h>
|
||||
#include <asm/types.h>
|
||||
#include <pthread.h>
|
||||
#include <errno.h>
|
||||
#include <sys/uio.h>
|
||||
|
||||
#include "stm_ioctls.h"
|
||||
#include "common.h"
|
||||
#include "output.h"
|
||||
#include "debug.h"
|
||||
#include "misc.h"
|
||||
#include "pes.h"
|
||||
#include "writer.h"
|
||||
|
||||
/* ***************************** */
|
||||
/* Makros/Constants */
|
||||
/* ***************************** */
|
||||
|
||||
/* ***************************** */
|
||||
/* Types */
|
||||
/* ***************************** */
|
||||
|
||||
/* ***************************** */
|
||||
/* Variables */
|
||||
/* ***************************** */
|
||||
|
||||
/* ***************************** */
|
||||
/* Prototypes */
|
||||
/* ***************************** */
|
||||
|
||||
/* ***************************** */
|
||||
/* MISC Functions */
|
||||
/* ***************************** */
|
||||
|
||||
static int reset()
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int writeData(void *_call)
|
||||
{
|
||||
WriterAVCallData_t *call = (WriterAVCallData_t *) _call;
|
||||
|
||||
unsigned char PesHeader[PES_MAX_HEADER_SIZE];
|
||||
int len = 0;
|
||||
|
||||
h263_printf(10, "\n");
|
||||
|
||||
if (call == NULL)
|
||||
{
|
||||
h263_err("call data is NULL...\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
h263_printf(10, "VideoPts %lld\n", call->Pts);
|
||||
|
||||
if ((call->data == NULL) || (call->len <= 0))
|
||||
{
|
||||
h263_err("NULL Data. ignoring...\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (call->fd < 0)
|
||||
{
|
||||
h263_err("file pointer < 0. ignoring ...\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
int HeaderLength = InsertPesHeader(PesHeader, call->len, H263_VIDEO_PES_START_CODE, call->Pts, 0);
|
||||
|
||||
int PrivateHeaderLength = InsertVideoPrivateDataHeader(&PesHeader[HeaderLength], call->len);
|
||||
|
||||
int PesLength = PesHeader[PES_LENGTH_BYTE_0] + (PesHeader[PES_LENGTH_BYTE_1] << 8) + PrivateHeaderLength;
|
||||
|
||||
PesHeader[PES_LENGTH_BYTE_0] = PesLength & 0xff;
|
||||
PesHeader[PES_LENGTH_BYTE_1] = (PesLength >> 8) & 0xff;
|
||||
PesHeader[PES_HEADER_DATA_LENGTH_BYTE] += PrivateHeaderLength;
|
||||
PesHeader[PES_FLAGS_BYTE] |= PES_EXTENSION_DATA_PRESENT;
|
||||
|
||||
HeaderLength += PrivateHeaderLength;
|
||||
|
||||
struct iovec iov[2];
|
||||
iov[0].iov_base = PesHeader;
|
||||
iov[0].iov_len = HeaderLength;
|
||||
iov[1].iov_base = call->data;
|
||||
iov[1].iov_len = call->len;
|
||||
len = call->WriteV(call->fd, iov, 2);
|
||||
|
||||
h263_printf(10, "< len %d\n", len);
|
||||
return len;
|
||||
}
|
||||
|
||||
/* ***************************** */
|
||||
/* Writer Definition */
|
||||
/* ***************************** */
|
||||
|
||||
static WriterCaps_t caps_h263 =
|
||||
{
|
||||
"h263",
|
||||
eVideo,
|
||||
"V_H263",
|
||||
VIDEO_ENCODING_H263,
|
||||
-1,
|
||||
-1
|
||||
};
|
||||
|
||||
struct Writer_s WriterVideoH263 =
|
||||
{
|
||||
&reset,
|
||||
&writeData,
|
||||
&caps_h263
|
||||
};
|
||||
|
||||
static WriterCaps_t caps_flv =
|
||||
{
|
||||
"FLV",
|
||||
eVideo,
|
||||
"V_FLV",
|
||||
VIDEO_ENCODING_FLV1,
|
||||
-1,
|
||||
-1
|
||||
};
|
||||
|
||||
struct Writer_s WriterVideoFLV =
|
||||
{
|
||||
&reset,
|
||||
&writeData,
|
||||
&caps_flv
|
||||
};
|
506
libeplayer3/output/writer/sh4/h264.c
Normal file
506
libeplayer3/output/writer/sh4/h264.c
Normal file
@@ -0,0 +1,506 @@
|
||||
/*
|
||||
* linuxdvb output/writer handling.
|
||||
*
|
||||
* konfetti 2010 based on linuxdvb.c code from libeplayer2
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*
|
||||
*/
|
||||
|
||||
/* ***************************** */
|
||||
/* Includes */
|
||||
/* ***************************** */
|
||||
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
#include <unistd.h>
|
||||
#include <fcntl.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
#include <sys/ioctl.h>
|
||||
#include <sys/uio.h>
|
||||
#include <linux/dvb/video.h>
|
||||
#include <linux/dvb/audio.h>
|
||||
#include <memory.h>
|
||||
#include <asm/types.h>
|
||||
#include <pthread.h>
|
||||
#include <errno.h>
|
||||
#include <assert.h>
|
||||
#include <stdint.h>
|
||||
|
||||
#include "stm_ioctls.h"
|
||||
#include "common.h"
|
||||
#include "output.h"
|
||||
#include "debug.h"
|
||||
#include "misc.h"
|
||||
#include "pes.h"
|
||||
#include "writer.h"
|
||||
|
||||
/* ***************************** */
|
||||
/* Makros/Constants */
|
||||
/* ***************************** */
|
||||
|
||||
#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;
|
||||
|
||||
/* ***************************** */
|
||||
/* Variables */
|
||||
/* ***************************** */
|
||||
|
||||
const uint8_t Head[] = {0, 0, 0, 1};
|
||||
static int32_t initialHeader = 1;
|
||||
static uint32_t NalLengthBytes = 1;
|
||||
static int avc3 = 0;
|
||||
/* ***************************** */
|
||||
/* Prototypes */
|
||||
/* ***************************** */
|
||||
|
||||
/* ***************************** */
|
||||
/* MISC Functions */
|
||||
/* ***************************** */
|
||||
|
||||
// Please see: https://bugzilla.mozilla.org/show_bug.cgi?id=1105771
|
||||
static int32_t UpdateExtraData(uint8_t **ppExtraData, uint32_t *pExtraDataSize, uint8_t *pData, uint32_t dataSize)
|
||||
{
|
||||
uint8_t *aExtraData = *ppExtraData;
|
||||
|
||||
if (aExtraData[0] != 1 || !pData)
|
||||
{
|
||||
// Not AVCC or nothing to update with.
|
||||
return -1;
|
||||
}
|
||||
|
||||
int32_t nalsize = (aExtraData[4] & 3) + 1;
|
||||
|
||||
uint8_t sps[256];
|
||||
uint8_t spsIdx = 0;
|
||||
|
||||
uint8_t numSps = 0;
|
||||
|
||||
uint8_t pps[256];
|
||||
uint8_t ppsIdx = 0;
|
||||
|
||||
uint8_t numPps = 0;
|
||||
|
||||
if (nalsize != 4)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
// Find SPS and PPS NALUs in AVCC data
|
||||
uint8_t *d = pData;
|
||||
while (d + 4 < pData + dataSize)
|
||||
{
|
||||
uint32_t nalLen = ReadUint32(d);
|
||||
|
||||
uint8_t nalType = d[4] & 0x1f;
|
||||
if (nalType == 7)
|
||||
{
|
||||
/* SPS */
|
||||
|
||||
// 16 bits size
|
||||
sps[spsIdx++] = (uint8_t)(0xFF & (nalLen >> 8));
|
||||
sps[spsIdx++] = (uint8_t)(0xFF & nalLen);
|
||||
|
||||
if (spsIdx + nalLen >= sizeof(sps))
|
||||
{
|
||||
h264_err("SPS no free space to copy...\n");
|
||||
return -1;
|
||||
}
|
||||
memcpy(&(sps[spsIdx]), d + 4, nalLen);
|
||||
spsIdx += nalLen;
|
||||
|
||||
numSps += 1;
|
||||
|
||||
h264_printf(10, "SPS len[%u]...\n", nalLen);
|
||||
}
|
||||
else if (nalType == 8)
|
||||
{
|
||||
/* PPS */
|
||||
|
||||
// 16 bits size
|
||||
pps[ppsIdx++] = (uint8_t)(0xFF & (nalLen >> 8));
|
||||
pps[ppsIdx++] = (uint8_t)(0xFF & nalLen);
|
||||
|
||||
if (ppsIdx + nalLen >= sizeof(sps))
|
||||
{
|
||||
h264_err("PPS not free space to copy...\n");
|
||||
return -1;
|
||||
}
|
||||
memcpy(&(pps[ppsIdx]), d + 4, nalLen);
|
||||
ppsIdx += nalLen;
|
||||
|
||||
numPps += 1;
|
||||
|
||||
h264_printf(10, "PPS len[%u]...\n", nalLen);
|
||||
}
|
||||
d += 4 + nalLen;
|
||||
}
|
||||
uint32_t idx = 0;
|
||||
*ppExtraData = malloc(7 + spsIdx + ppsIdx);
|
||||
aExtraData = *ppExtraData;
|
||||
aExtraData[idx++] = 0x1; // version
|
||||
aExtraData[idx++] = sps[3]; // profile
|
||||
aExtraData[idx++] = sps[4]; // profile compat
|
||||
aExtraData[idx++] = sps[5]; // level
|
||||
aExtraData[idx++] = 0xff; // nal size - 1
|
||||
|
||||
aExtraData[idx++] = 0xe0 | numSps;
|
||||
if (numSps)
|
||||
{
|
||||
memcpy(&(aExtraData[idx]), sps, spsIdx);
|
||||
idx += spsIdx;
|
||||
}
|
||||
|
||||
aExtraData[idx++] = numPps;
|
||||
if (numPps)
|
||||
{
|
||||
memcpy(&(aExtraData[idx]), pps, ppsIdx);
|
||||
idx += ppsIdx;
|
||||
}
|
||||
|
||||
h264_printf(10, "aExtraData len[%u]...\n", idx);
|
||||
*pExtraDataSize = idx;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int32_t reset()
|
||||
{
|
||||
initialHeader = 1;
|
||||
avc3 = 0;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int32_t writeData(void *_call)
|
||||
{
|
||||
WriterAVCallData_t *call = (WriterAVCallData_t *) _call;
|
||||
|
||||
uint8_t PesHeader[PES_MAX_HEADER_SIZE];
|
||||
uint64_t VideoPts;
|
||||
uint32_t TimeDelta;
|
||||
uint32_t TimeScale;
|
||||
int32_t len = 0;
|
||||
int32_t ic = 0;
|
||||
struct iovec iov[128];
|
||||
h264_printf(10, "\n");
|
||||
|
||||
if (call == NULL)
|
||||
{
|
||||
h264_err("call data is NULL...\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
TimeDelta = call->FrameRate;
|
||||
TimeScale = call->FrameScale;
|
||||
VideoPts = call->Pts;
|
||||
|
||||
h264_printf(10, "VideoPts %lld - %d %d\n", call->Pts, TimeDelta, TimeScale);
|
||||
|
||||
if ((call->data == NULL) || (call->len <= 0))
|
||||
{
|
||||
h264_err("NULL Data. ignoring...\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (call->fd < 0)
|
||||
{
|
||||
h264_err("file pointer < 0. ignoring ...\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* AnnexA */
|
||||
if (!avc3 && ((1 < call->private_size && 0 == call->private_data[0]) ||
|
||||
(call->len > 3) && ((call->data[0] == 0x00 && call->data[1] == 0x00 && call->data[2] == 0x00 && call->data[3] == 0x01) ||
|
||||
(call->data[0] == 0xff && call->data[1] == 0xff && call->data[2] == 0xff && call->data[3] == 0xff))))
|
||||
{
|
||||
uint32_t PacketLength = 0;
|
||||
uint32_t FakeStartCode = /*(call->Version << 8) | */PES_VERSION_FAKE_START_CODE;
|
||||
|
||||
iov[ic++].iov_base = PesHeader;
|
||||
initialHeader = 0;
|
||||
if (initialHeader)
|
||||
{
|
||||
initialHeader = 0;
|
||||
iov[ic].iov_base = call->private_data;
|
||||
iov[ic++].iov_len = call->private_size;
|
||||
PacketLength += call->private_size;
|
||||
}
|
||||
|
||||
iov[ic].iov_base = "";
|
||||
iov[ic++].iov_len = 1;
|
||||
|
||||
iov[ic].iov_base = call->data;
|
||||
iov[ic++].iov_len = call->len;
|
||||
PacketLength += call->len;
|
||||
|
||||
/*Hellmaster1024: some packets will only be accepted by the player if we send one byte more than
|
||||
data is available. The content of this byte does not matter. It will be ignored
|
||||
by the player */
|
||||
iov[ic].iov_base = "\0";
|
||||
iov[ic++].iov_len = 1;
|
||||
|
||||
iov[0].iov_len = InsertPesHeader(PesHeader, -1, MPEG_VIDEO_PES_START_CODE, VideoPts, FakeStartCode);
|
||||
int ret = call->WriteV(call->fd, iov, ic);
|
||||
return ret;
|
||||
}
|
||||
else if (!call->private_data || call->private_size < 7 || 1 != call->private_data[0])
|
||||
{
|
||||
h264_err("No valid private data available!\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (initialHeader)
|
||||
{
|
||||
uint8_t *private_data = call->private_data;
|
||||
uint32_t private_size = call->private_size;
|
||||
avcC_t *avcCHeader = (avcC_t *)private_data;
|
||||
unsigned int i;
|
||||
unsigned int ParamSets;
|
||||
unsigned int ParamOffset;
|
||||
unsigned int InitialHeaderLength = 0;
|
||||
unsigned int ParametersLength;
|
||||
|
||||
ParametersLength = 0;
|
||||
|
||||
unsigned char HeaderData[19];
|
||||
|
||||
if (private_size <= sizeof(avcC_t))
|
||||
{
|
||||
UpdateExtraData(&private_data, &private_size, call->data, call->len);
|
||||
if (private_data != call->private_data)
|
||||
{
|
||||
avc3 = 1;
|
||||
avcCHeader = (avcC_t *)private_data;
|
||||
}
|
||||
}
|
||||
|
||||
HeaderData[ParametersLength++] = 0x00; // Start code
|
||||
HeaderData[ParametersLength++] = 0x00;
|
||||
HeaderData[ParametersLength++] = 0x01;
|
||||
HeaderData[ParametersLength++] = NALU_TYPE_PLAYER2_CONTAINER_PARAMETERS;
|
||||
// Container message version - changes when/if we vary the format of the message
|
||||
HeaderData[ParametersLength++] = CONTAINER_PARAMETERS_VERSION;
|
||||
HeaderData[ParametersLength++] = 0xff; // Field separator
|
||||
|
||||
if (TimeDelta == 0xffffffff)
|
||||
TimeDelta = (TimeScale > 1000) ? 1001 : 1;
|
||||
|
||||
HeaderData[ParametersLength++] = (TimeScale >> 24) & 0xff; // Output the timescale
|
||||
HeaderData[ParametersLength++] = (TimeScale >> 16) & 0xff;
|
||||
HeaderData[ParametersLength++] = 0xff;
|
||||
HeaderData[ParametersLength++] = (TimeScale >> 8) & 0xff;
|
||||
HeaderData[ParametersLength++] = TimeScale & 0xff;
|
||||
HeaderData[ParametersLength++] = 0xff;
|
||||
|
||||
HeaderData[ParametersLength++] = (TimeDelta >> 24) & 0xff; // Output frame period
|
||||
HeaderData[ParametersLength++] = (TimeDelta >> 16) & 0xff;
|
||||
HeaderData[ParametersLength++] = 0xff;
|
||||
HeaderData[ParametersLength++] = (TimeDelta >> 8) & 0xff;
|
||||
HeaderData[ParametersLength++] = TimeDelta & 0xff;
|
||||
HeaderData[ParametersLength++] = 0xff;
|
||||
HeaderData[ParametersLength++] = 0x80; // Rsbp trailing bits
|
||||
|
||||
assert(ParametersLength <= sizeof(HeaderData));
|
||||
|
||||
ic = 0;
|
||||
iov[ic].iov_base = PesHeader;
|
||||
iov[ic++].iov_len = InsertPesHeader(PesHeader, ParametersLength, MPEG_VIDEO_PES_START_CODE, INVALID_PTS_VALUE, 0);
|
||||
iov[ic].iov_base = HeaderData;
|
||||
iov[ic++].iov_len = ParametersLength;
|
||||
len = call->WriteV(call->fd, iov, ic);
|
||||
if (len < 0)
|
||||
{
|
||||
return len;
|
||||
}
|
||||
|
||||
NalLengthBytes = (avcCHeader->NalLengthMinusOne & 0x03) + 1;
|
||||
ParamSets = avcCHeader->NumParamSets & 0x1f;
|
||||
|
||||
h264_printf(20, "avcC contents:\n");
|
||||
h264_printf(20, " version: %d\n", avcCHeader->Version);
|
||||
h264_printf(20, " profile: %d\n", avcCHeader->Profile);
|
||||
h264_printf(20, " profile compatibility: %d\n", avcCHeader->Compatibility);
|
||||
h264_printf(20, " level: %d\n", avcCHeader->Level);
|
||||
h264_printf(20, " nal length bytes: %d\n", NalLengthBytes);
|
||||
h264_printf(20, " number of sequence param sets: %d\n", ParamSets);
|
||||
|
||||
ParamOffset = 0;
|
||||
ic = 0;
|
||||
iov[ic++].iov_base = PesHeader;
|
||||
for (i = 0; i < ParamSets; i++)
|
||||
{
|
||||
unsigned int PsLength = (avcCHeader->Params[ParamOffset] << 8) + avcCHeader->Params[ParamOffset + 1];
|
||||
|
||||
h264_printf(20, " sps %d has length %d\n", i, PsLength);
|
||||
|
||||
iov[ic].iov_base = (char *)Head;
|
||||
iov[ic++].iov_len = sizeof(Head);
|
||||
InitialHeaderLength += sizeof(Head);
|
||||
iov[ic].iov_base = &avcCHeader->Params[ParamOffset + 2];
|
||||
iov[ic++].iov_len = PsLength;
|
||||
InitialHeaderLength += PsLength;
|
||||
ParamOffset += PsLength + 2;
|
||||
}
|
||||
|
||||
ParamSets = avcCHeader->Params[ParamOffset];
|
||||
|
||||
h264_printf(20, " number of picture param sets: %d\n", ParamSets);
|
||||
|
||||
ParamOffset++;
|
||||
for (i = 0; i < ParamSets; i++)
|
||||
{
|
||||
unsigned int PsLength = (avcCHeader->Params[ParamOffset] << 8) + avcCHeader->Params[ParamOffset + 1];
|
||||
|
||||
h264_printf(20, " pps %d has length %d\n", i, PsLength);
|
||||
|
||||
iov[ic].iov_base = (char *) Head;
|
||||
iov[ic++].iov_len = sizeof(Head);
|
||||
InitialHeaderLength += sizeof(Head);
|
||||
iov[ic].iov_base = &avcCHeader->Params[ParamOffset + 2];
|
||||
iov[ic++].iov_len = PsLength;
|
||||
InitialHeaderLength += PsLength;
|
||||
ParamOffset += PsLength + 2;
|
||||
}
|
||||
|
||||
iov[0].iov_len = InsertPesHeader(PesHeader, InitialHeaderLength, MPEG_VIDEO_PES_START_CODE, INVALID_PTS_VALUE, 0);
|
||||
ssize_t l = call->WriteV(call->fd, iov, ic);
|
||||
|
||||
if (private_data != call->private_data)
|
||||
{
|
||||
free(private_data);
|
||||
}
|
||||
|
||||
if (l < 0)
|
||||
{
|
||||
return l;
|
||||
}
|
||||
|
||||
len += l;
|
||||
initialHeader = 0;
|
||||
}
|
||||
|
||||
unsigned int SampleSize = call->len;
|
||||
unsigned int NalStart = 0;
|
||||
unsigned int VideoPosition = 0;
|
||||
|
||||
do
|
||||
{
|
||||
unsigned int NalLength;
|
||||
unsigned char NalData[4];
|
||||
int NalPresent = 1;
|
||||
|
||||
memcpy(NalData, call->data + VideoPosition, NalLengthBytes);
|
||||
VideoPosition += NalLengthBytes;
|
||||
NalStart += NalLengthBytes;
|
||||
switch (NalLengthBytes)
|
||||
{
|
||||
case 1:
|
||||
NalLength = (NalData[0]);
|
||||
break;
|
||||
case 2:
|
||||
NalLength = (NalData[0] << 8) | (NalData[1]);
|
||||
break;
|
||||
case 3:
|
||||
NalLength = (NalData[0] << 16) | (NalData[1] << 8) | (NalData[2]);
|
||||
break;
|
||||
default:
|
||||
NalLength = (NalData[0] << 24) | (NalData[1] << 16) | (NalData[2] << 8) | (NalData[3]);
|
||||
break;
|
||||
}
|
||||
|
||||
h264_printf(20, "NalStart = %u + NalLength = %u > SampleSize = %u\n", NalStart, NalLength, SampleSize);
|
||||
|
||||
if (NalStart + NalLength > SampleSize)
|
||||
{
|
||||
h264_printf(20, "nal length past end of buffer - size %u frame offset %u left %u\n",
|
||||
NalLength, NalStart, SampleSize - NalStart);
|
||||
|
||||
NalStart = SampleSize;
|
||||
}
|
||||
else
|
||||
{
|
||||
NalStart += NalLength;
|
||||
ic = 0;
|
||||
iov[ic++].iov_base = PesHeader;
|
||||
|
||||
if (NalPresent)
|
||||
{
|
||||
NalPresent = 0;
|
||||
iov[ic].iov_base = (char *)Head;
|
||||
iov[ic++].iov_len = sizeof(Head);
|
||||
}
|
||||
|
||||
iov[ic].iov_base = call->data + VideoPosition;
|
||||
iov[ic++].iov_len = NalLength;
|
||||
VideoPosition += NalLength;
|
||||
|
||||
h264_printf(20, " pts=%llu\n", VideoPts);
|
||||
|
||||
iov[0].iov_len = InsertPesHeader(PesHeader, NalLength, MPEG_VIDEO_PES_START_CODE, VideoPts, 0);
|
||||
ssize_t l = call->WriteV(call->fd, iov, ic);
|
||||
if (l < 0)
|
||||
return l;
|
||||
len += l;
|
||||
|
||||
VideoPts = INVALID_PTS_VALUE;
|
||||
}
|
||||
}
|
||||
while (NalStart < SampleSize);
|
||||
|
||||
if (len < 0)
|
||||
{
|
||||
h264_err("error writing data errno = %d\n", errno);
|
||||
h264_err("%s\n", strerror(errno));
|
||||
}
|
||||
|
||||
h264_printf(10, "< len %d\n", len);
|
||||
return len;
|
||||
}
|
||||
|
||||
/* ***************************** */
|
||||
/* Writer Definition */
|
||||
/* ***************************** */
|
||||
|
||||
static WriterCaps_t caps =
|
||||
{
|
||||
"h264",
|
||||
eVideo,
|
||||
"V_MPEG4/ISO/AVC",
|
||||
VIDEO_ENCODING_H264,
|
||||
-1,
|
||||
-1
|
||||
};
|
||||
|
||||
struct Writer_s WriterVideoH264 =
|
||||
{
|
||||
&reset,
|
||||
&writeData,
|
||||
&caps
|
||||
};
|
163
libeplayer3/output/writer/sh4/mp3.c
Normal file
163
libeplayer3/output/writer/sh4/mp3.c
Normal file
@@ -0,0 +1,163 @@
|
||||
/*
|
||||
* linuxdvb output/writer handling.
|
||||
*
|
||||
* konfetti 2010 based on linuxdvb.c code from libeplayer2
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*
|
||||
*/
|
||||
|
||||
/* ***************************** */
|
||||
/* Includes */
|
||||
/* ***************************** */
|
||||
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
#include <unistd.h>
|
||||
#include <fcntl.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
#include <sys/ioctl.h>
|
||||
#include <sys/uio.h>
|
||||
#include <linux/dvb/video.h>
|
||||
#include <linux/dvb/audio.h>
|
||||
#include <memory.h>
|
||||
#include <asm/types.h>
|
||||
#include <pthread.h>
|
||||
#include <errno.h>
|
||||
|
||||
#include "stm_ioctls.h"
|
||||
#include "common.h"
|
||||
#include "output.h"
|
||||
#include "debug.h"
|
||||
#include "misc.h"
|
||||
#include "pes.h"
|
||||
#include "writer.h"
|
||||
|
||||
/* ***************************** */
|
||||
/* Makros/Constants */
|
||||
/* ***************************** */
|
||||
|
||||
/* ***************************** */
|
||||
/* Types */
|
||||
/* ***************************** */
|
||||
|
||||
/* ***************************** */
|
||||
/* Variables */
|
||||
/* ***************************** */
|
||||
|
||||
/* ***************************** */
|
||||
/* Prototypes */
|
||||
/* ***************************** */
|
||||
|
||||
/* ***************************** */
|
||||
/* MISC Functions */
|
||||
/* ***************************** */
|
||||
|
||||
static int reset()
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int writeData(void *_call)
|
||||
{
|
||||
WriterAVCallData_t *call = (WriterAVCallData_t *) _call;
|
||||
|
||||
unsigned char PesHeader[PES_MAX_HEADER_SIZE];
|
||||
|
||||
mp3_printf(10, "\n");
|
||||
|
||||
if (call == NULL)
|
||||
{
|
||||
mp3_err("call data is NULL...\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
mp3_printf(10, "AudioPts %lld\n", call->Pts);
|
||||
|
||||
if ((call->data == NULL) || (call->len <= 0))
|
||||
{
|
||||
mp3_err("parsing NULL Data. ignoring...\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (call->fd < 0)
|
||||
{
|
||||
mp3_err("file pointer < 0. ignoring ...\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
struct iovec iov[2];
|
||||
iov[0].iov_base = PesHeader;
|
||||
iov[0].iov_len = InsertPesHeader(PesHeader, call->len, MPEG_AUDIO_PES_START_CODE, call->Pts, 0);
|
||||
iov[1].iov_base = call->data;
|
||||
iov[1].iov_len = call->len;
|
||||
|
||||
int len = call->WriteV(call->fd, iov, 2);
|
||||
|
||||
mp3_printf(10, "mp3_Write-< len=%d\n", len);
|
||||
return len;
|
||||
}
|
||||
|
||||
/* ***************************** */
|
||||
/* Writer Definition */
|
||||
/* ***************************** */
|
||||
|
||||
static WriterCaps_t caps_mp3 =
|
||||
{
|
||||
"mp3",
|
||||
eAudio,
|
||||
"A_MP3",
|
||||
AUDIO_ENCODING_MP3
|
||||
};
|
||||
|
||||
struct Writer_s WriterAudioMP3 =
|
||||
{
|
||||
&reset,
|
||||
&writeData,
|
||||
&caps_mp3
|
||||
};
|
||||
|
||||
static WriterCaps_t caps_mpegl3 =
|
||||
{
|
||||
"mpeg/l3",
|
||||
eAudio,
|
||||
"A_MPEG/L3",
|
||||
AUDIO_ENCODING_MPEG2
|
||||
};
|
||||
|
||||
struct Writer_s WriterAudioMPEGL3 =
|
||||
{
|
||||
&reset,
|
||||
&writeData,
|
||||
&caps_mpegl3
|
||||
};
|
||||
|
||||
static WriterCaps_t caps_vorbis =
|
||||
{
|
||||
"vorbis",
|
||||
eAudio,
|
||||
"A_VORBIS",
|
||||
AUDIO_ENCODING_VORBIS
|
||||
};
|
||||
|
||||
struct Writer_s WriterAudioVORBIS =
|
||||
{
|
||||
&reset,
|
||||
&writeData,
|
||||
&caps_vorbis
|
||||
};
|
||||
|
172
libeplayer3/output/writer/sh4/mpeg2.c
Normal file
172
libeplayer3/output/writer/sh4/mpeg2.c
Normal file
@@ -0,0 +1,172 @@
|
||||
/*
|
||||
* linuxdvb output/writer handling.
|
||||
*
|
||||
* konfetti 2010 based on linuxdvb.c code from libeplayer2
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*
|
||||
*/
|
||||
|
||||
/* ***************************** */
|
||||
/* Includes */
|
||||
/* ***************************** */
|
||||
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
#include <unistd.h>
|
||||
#include <fcntl.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
#include <sys/ioctl.h>
|
||||
#include <sys/uio.h>
|
||||
#include <linux/dvb/video.h>
|
||||
#include <linux/dvb/audio.h>
|
||||
#include <memory.h>
|
||||
#include <asm/types.h>
|
||||
#include <pthread.h>
|
||||
#include <errno.h>
|
||||
|
||||
#include "stm_ioctls.h"
|
||||
#include "common.h"
|
||||
#include "output.h"
|
||||
#include "debug.h"
|
||||
#include "misc.h"
|
||||
#include "pes.h"
|
||||
#include "writer.h"
|
||||
|
||||
/* ***************************** */
|
||||
/* Makros/Constants */
|
||||
/* ***************************** */
|
||||
|
||||
/* ***************************** */
|
||||
/* Types */
|
||||
/* ***************************** */
|
||||
|
||||
/* ***************************** */
|
||||
/* Variables */
|
||||
/* ***************************** */
|
||||
|
||||
/* ***************************** */
|
||||
/* Prototypes */
|
||||
/* ***************************** */
|
||||
|
||||
/* ***************************** */
|
||||
/* MISC Functions */
|
||||
/* ***************************** */
|
||||
|
||||
static int reset()
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int writeData(void *_call)
|
||||
{
|
||||
WriterAVCallData_t *call = (WriterAVCallData_t *) _call;
|
||||
|
||||
unsigned char PesHeader[PES_MAX_HEADER_SIZE];
|
||||
|
||||
int len = 0;
|
||||
unsigned int Position = 0;
|
||||
|
||||
mpeg2_printf(10, "\n");
|
||||
|
||||
if (call == NULL)
|
||||
{
|
||||
mpeg2_err("call data is NULL...\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
mpeg2_printf(10, "VideoPts %lld\n", call->Pts);
|
||||
|
||||
if ((call->data == NULL) || (call->len <= 0))
|
||||
{
|
||||
mpeg2_err("parsing NULL Data. ignoring...\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (call->fd < 0)
|
||||
{
|
||||
mpeg2_err("file pointer < 0. ignoring ...\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
while (Position < call->len)
|
||||
{
|
||||
int32_t PacketLength = (call->len - Position) <= MAX_PES_PACKET_SIZE ?
|
||||
(call->len - Position) : MAX_PES_PACKET_SIZE;
|
||||
|
||||
int32_t Remaining = call->len - Position - PacketLength;
|
||||
|
||||
mpeg2_printf(20, "PacketLength=%d, Remaining=%d, Position=%d\n", PacketLength, Remaining, Position);
|
||||
|
||||
struct iovec iov[2];
|
||||
iov[0].iov_base = PesHeader;
|
||||
iov[0].iov_len = InsertPesHeader(PesHeader, PacketLength, 0xe0, call->Pts, 0);
|
||||
iov[1].iov_base = call->data + Position;
|
||||
iov[1].iov_len = PacketLength;
|
||||
|
||||
ssize_t l = call->WriteV(call->fd, iov, 2);
|
||||
if (l < 0)
|
||||
{
|
||||
len = l;
|
||||
break;
|
||||
}
|
||||
len += l;
|
||||
|
||||
Position += PacketLength;
|
||||
call->Pts = INVALID_PTS_VALUE;
|
||||
}
|
||||
|
||||
mpeg2_printf(10, "< len %d\n", len);
|
||||
return len;
|
||||
}
|
||||
|
||||
/* ***************************** */
|
||||
/* Writer Definition */
|
||||
/* ***************************** */
|
||||
static WriterCaps_t caps =
|
||||
{
|
||||
"mpeg2",
|
||||
eVideo,
|
||||
"V_MPEG2",
|
||||
VIDEO_ENCODING_AUTO,
|
||||
-1,
|
||||
-1,
|
||||
};
|
||||
|
||||
struct Writer_s WriterVideoMPEG2 =
|
||||
{
|
||||
&reset,
|
||||
&writeData,
|
||||
&caps
|
||||
};
|
||||
|
||||
static WriterCaps_t h264_caps =
|
||||
{
|
||||
"mpges_h264",
|
||||
eVideo,
|
||||
"V_MPEG2/H264",
|
||||
VIDEO_ENCODING_H264,
|
||||
-1,
|
||||
-1
|
||||
};
|
||||
|
||||
struct Writer_s WriterVideoMPEGH264 =
|
||||
{
|
||||
&reset,
|
||||
&writeData,
|
||||
&h264_caps
|
||||
};
|
357
libeplayer3/output/writer/sh4/pcm.c
Normal file
357
libeplayer3/output/writer/sh4/pcm.c
Normal file
@@ -0,0 +1,357 @@
|
||||
/*
|
||||
* linuxdvb output/writer handling.
|
||||
*
|
||||
* konfetti 2010 based on linuxdvb.c code from libeplayer2
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*
|
||||
*/
|
||||
|
||||
/* ***************************** */
|
||||
/* Includes */
|
||||
/* ***************************** */
|
||||
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
#include <unistd.h>
|
||||
#include <fcntl.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
#include <sys/ioctl.h>
|
||||
#include <sys/uio.h>
|
||||
#include <linux/dvb/video.h>
|
||||
#include <linux/dvb/audio.h>
|
||||
#include <memory.h>
|
||||
#include <asm/types.h>
|
||||
#include <pthread.h>
|
||||
#include <errno.h>
|
||||
|
||||
#include <libavcodec/avcodec.h>
|
||||
|
||||
#include "stm_ioctls.h"
|
||||
#include "common.h"
|
||||
#include "output.h"
|
||||
#include "debug.h"
|
||||
#include "misc.h"
|
||||
#include "pes.h"
|
||||
#include "writer.h"
|
||||
#include "pcm.h"
|
||||
|
||||
/* ***************************** */
|
||||
/* Makros/Constants */
|
||||
/* ***************************** */
|
||||
|
||||
/* ***************************** */
|
||||
/* Types */
|
||||
/* ***************************** */
|
||||
|
||||
/* ***************************** */
|
||||
/* Variables */
|
||||
/* ***************************** */
|
||||
|
||||
static int32_t initialHeader = 1;
|
||||
static uint32_t SubFrameLen = 0;
|
||||
static uint32_t SubFramesPerPES = 0;
|
||||
|
||||
// reference: search for TypeLpcmDVDAudio in player/frame_parser/frame_parser_audio_lpcm.cpp
|
||||
static const uint8_t clpcm_prv[14] =
|
||||
{
|
||||
0xA0, //sub_stream_id
|
||||
0, 0, //resvd and UPC_EAN_ISRC stuff, unused
|
||||
0x0A, //private header length
|
||||
0, 9, //first_access_unit_pointer
|
||||
0x00, //emph,rsvd,stereo,downmix
|
||||
0x0F, //quantisation word length 1,2
|
||||
0x0F, //audio sampling freqency 1,2
|
||||
0, //resvd, multi channel type
|
||||
0, //bit shift on channel GR2, assignment
|
||||
0x80, //dynamic range control
|
||||
0, 0 //resvd for copyright management
|
||||
};
|
||||
|
||||
static uint8_t lpcm_prv[14];
|
||||
static uint8_t breakBuffer[8192];
|
||||
static uint32_t breakBufferFillSize = 0;
|
||||
|
||||
/* ***************************** */
|
||||
/* Prototypes */
|
||||
/* ***************************** */
|
||||
|
||||
/* ***************************** */
|
||||
/* MISC Functions */
|
||||
/* ***************************** */
|
||||
|
||||
static int32_t prepareClipPlay(int32_t uNoOfChannels, int32_t uSampleRate, int32_t uBitsPerSample, uint8_t bLittleEndian __attribute__((unused)))
|
||||
{
|
||||
printf("rate: %d ch: %d bits: %d (%d bps)\n",
|
||||
uSampleRate/*Format->dwSamplesPerSec*/,
|
||||
uNoOfChannels/*Format->wChannels*/,
|
||||
uBitsPerSample/*Format->wBitsPerSample*/,
|
||||
(uBitsPerSample/*Format->wBitsPerSample*/ / 8)
|
||||
);
|
||||
|
||||
SubFrameLen = 0;
|
||||
SubFramesPerPES = 0;
|
||||
breakBufferFillSize = 0;
|
||||
|
||||
memcpy(lpcm_prv, clpcm_prv, sizeof(lpcm_prv));
|
||||
|
||||
//figure out size of subframe
|
||||
//and set up sample rate
|
||||
switch (uSampleRate)
|
||||
{
|
||||
case 48000:
|
||||
SubFrameLen = 40;
|
||||
break;
|
||||
case 96000:
|
||||
lpcm_prv[8] |= 0x10;
|
||||
SubFrameLen = 80;
|
||||
break;
|
||||
case 192000:
|
||||
lpcm_prv[8] |= 0x20;
|
||||
SubFrameLen = 160;
|
||||
break;
|
||||
case 44100:
|
||||
lpcm_prv[8] |= 0x80;
|
||||
SubFrameLen = 40;
|
||||
break;
|
||||
case 88200:
|
||||
lpcm_prv[8] |= 0x90;
|
||||
SubFrameLen = 80;
|
||||
break;
|
||||
case 176400:
|
||||
lpcm_prv[8] |= 0xA0;
|
||||
SubFrameLen = 160;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
SubFrameLen *= uNoOfChannels;
|
||||
SubFrameLen *= (uBitsPerSample / 8);
|
||||
|
||||
//rewrite PES size to have as many complete subframes per PES as we can
|
||||
// FIXME: PES header size was hardcoded to 18 in previous code. Actual size returned by InsertPesHeader is 14.
|
||||
SubFramesPerPES = ((2048 - 18) - sizeof(lpcm_prv)) / SubFrameLen;
|
||||
SubFrameLen *= SubFramesPerPES;
|
||||
|
||||
//set number of channels
|
||||
lpcm_prv[10] = uNoOfChannels - 1;
|
||||
|
||||
switch (uBitsPerSample)
|
||||
{
|
||||
case 24:
|
||||
lpcm_prv[7] |= 0x20;
|
||||
case 16:
|
||||
break;
|
||||
default:
|
||||
printf("inappropriate bits per sample (%d) - must be 16 or 24\n", uBitsPerSample);
|
||||
return 1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int32_t reset()
|
||||
{
|
||||
initialHeader = 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int32_t writeData(void *_call)
|
||||
{
|
||||
WriterAVCallData_t *call = (WriterAVCallData_t *) _call;
|
||||
|
||||
unsigned char PesHeader[PES_MAX_HEADER_SIZE];
|
||||
|
||||
pcm_printf(10, "\n");
|
||||
|
||||
if (!call)
|
||||
{
|
||||
pcm_err("call data is NULL...\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
pcm_printf(10, "AudioPts %lld\n", call->Pts);
|
||||
|
||||
if (!call->data || (call->len <= 0))
|
||||
{
|
||||
pcm_err("parsing NULL Data. ignoring...\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (call->fd < 0)
|
||||
{
|
||||
pcm_err("file pointer < 0. ignoring ...\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
pcmPrivateData_t *pcmPrivateData = (pcmPrivateData_t *)call->private_data;
|
||||
|
||||
if (initialHeader)
|
||||
{
|
||||
uint32_t codecID = (uint32_t)pcmPrivateData->ffmpeg_codec_id;
|
||||
uint8_t LE = 0;
|
||||
switch (codecID)
|
||||
{
|
||||
case AV_CODEC_ID_PCM_S8:
|
||||
case AV_CODEC_ID_PCM_U8:
|
||||
break;
|
||||
case AV_CODEC_ID_PCM_S16LE:
|
||||
case AV_CODEC_ID_PCM_U16LE:
|
||||
LE = 1;
|
||||
case AV_CODEC_ID_PCM_S16BE:
|
||||
case AV_CODEC_ID_PCM_U16BE:
|
||||
break;
|
||||
case AV_CODEC_ID_PCM_S24LE:
|
||||
case AV_CODEC_ID_PCM_U24LE:
|
||||
LE = 1;
|
||||
case AV_CODEC_ID_PCM_S24BE:
|
||||
case AV_CODEC_ID_PCM_U24BE:
|
||||
break;
|
||||
case AV_CODEC_ID_PCM_S32LE:
|
||||
case AV_CODEC_ID_PCM_U32LE:
|
||||
LE = 1;
|
||||
case AV_CODEC_ID_PCM_S32BE:
|
||||
case AV_CODEC_ID_PCM_U32BE:
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
initialHeader = 0;
|
||||
prepareClipPlay(pcmPrivateData->channels, pcmPrivateData->sample_rate, pcmPrivateData->bits_per_coded_sample, LE);
|
||||
}
|
||||
|
||||
uint8_t *buffer = call->data;
|
||||
uint32_t size = call->len;
|
||||
|
||||
uint32_t n;
|
||||
uint8_t *injectBuffer = malloc(SubFrameLen);
|
||||
uint32_t pos;
|
||||
|
||||
for (pos = 0; pos < size;)
|
||||
{
|
||||
//printf("PCM %s - Position=%d\n", __FUNCTION__, pos);
|
||||
if ((size - pos) < SubFrameLen)
|
||||
{
|
||||
breakBufferFillSize = size - pos;
|
||||
memcpy(breakBuffer, &buffer[pos], sizeof(uint8_t) * breakBufferFillSize);
|
||||
//printf("PCM %s - Unplayed=%d\n", __FUNCTION__, breakBufferFillSize);
|
||||
break;
|
||||
}
|
||||
|
||||
//get first PES's worth
|
||||
if (breakBufferFillSize > 0)
|
||||
{
|
||||
memcpy(injectBuffer, breakBuffer, sizeof(uint8_t)*breakBufferFillSize);
|
||||
memcpy(&injectBuffer[breakBufferFillSize], &buffer[pos], sizeof(unsigned char) * (SubFrameLen - breakBufferFillSize));
|
||||
pos += (SubFrameLen - breakBufferFillSize);
|
||||
breakBufferFillSize = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
memcpy(injectBuffer, &buffer[pos], sizeof(uint8_t)*SubFrameLen);
|
||||
pos += SubFrameLen;
|
||||
}
|
||||
|
||||
struct iovec iov[3];
|
||||
iov[0].iov_base = PesHeader;
|
||||
iov[1].iov_base = lpcm_prv;
|
||||
iov[1].iov_len = sizeof(lpcm_prv);
|
||||
|
||||
iov[2].iov_base = injectBuffer;
|
||||
iov[2].iov_len = SubFrameLen;
|
||||
|
||||
//write the PCM data
|
||||
if (16 == pcmPrivateData->bits_per_coded_sample)
|
||||
{
|
||||
for (n = 0; n < SubFrameLen; n += 2)
|
||||
{
|
||||
uint8_t tmp;
|
||||
tmp = injectBuffer[n];
|
||||
injectBuffer[n] = injectBuffer[n + 1];
|
||||
injectBuffer[n + 1] = tmp;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// 0 1 2 3 4 5 6 7 8 9 10 11
|
||||
// A1c A1b A1a-B1c B1b B1a-A2c A2b A2a-B2c B2b B2a
|
||||
// to A1a A1b B1a B1b.A2a A2b B2a B2b-A1c B1c A2c B2c
|
||||
for (n = 0; n < SubFrameLen; n += 12)
|
||||
{
|
||||
unsigned char t, *p = &injectBuffer[n];
|
||||
t = p[0];
|
||||
p[ 0] = p[ 2];
|
||||
p[ 2] = p[ 5];
|
||||
p[ 5] = p[ 7];
|
||||
p[ 7] = p[11];
|
||||
p[11] = p[ 9];
|
||||
p[ 9] = p[ 3];
|
||||
p[ 3] = p[ 4];
|
||||
p[ 4] = p[ 8];
|
||||
p[ 8] = t;
|
||||
}
|
||||
}
|
||||
|
||||
//increment err... subframe count?
|
||||
lpcm_prv[1] = ((lpcm_prv[1] + SubFramesPerPES) & 0x1F);
|
||||
|
||||
iov[0].iov_len = InsertPesHeader(PesHeader, iov[1].iov_len + iov[2].iov_len, PCM_PES_START_CODE, call->Pts, 0);
|
||||
int32_t len = call->WriteV(call->fd, iov, 3);
|
||||
if (len < 0)
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
free(injectBuffer);
|
||||
|
||||
return size;
|
||||
}
|
||||
|
||||
/* ***************************** */
|
||||
/* Writer Definition */
|
||||
/* ***************************** */
|
||||
|
||||
static WriterCaps_t caps_pcm =
|
||||
{
|
||||
"pcm",
|
||||
eAudio,
|
||||
"A_PCM",
|
||||
AUDIO_ENCODING_LPCMA
|
||||
};
|
||||
|
||||
struct Writer_s WriterAudioPCM =
|
||||
{
|
||||
&reset,
|
||||
&writeData,
|
||||
&caps_pcm
|
||||
};
|
||||
|
||||
static WriterCaps_t caps_ipcm =
|
||||
{
|
||||
"ipcm",
|
||||
eAudio,
|
||||
"A_IPCM",
|
||||
AUDIO_ENCODING_LPCMA
|
||||
};
|
||||
|
||||
struct Writer_s WriterAudioIPCM =
|
||||
{
|
||||
&reset,
|
||||
&writeData,
|
||||
&caps_ipcm
|
||||
};
|
167
libeplayer3/output/writer/sh4/pes.c
Normal file
167
libeplayer3/output/writer/sh4/pes.c
Normal file
@@ -0,0 +1,167 @@
|
||||
/*
|
||||
* linuxdvb output/writer handling.
|
||||
*
|
||||
* konfetti 2010 based on linuxdvb.c code from libeplayer2
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*
|
||||
*/
|
||||
|
||||
/* ***************************** */
|
||||
/* Includes */
|
||||
/* ***************************** */
|
||||
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
#include <unistd.h>
|
||||
#include <fcntl.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
#include <sys/ioctl.h>
|
||||
#include <linux/dvb/video.h>
|
||||
#include <linux/dvb/audio.h>
|
||||
#include <memory.h>
|
||||
#include <asm/types.h>
|
||||
#include <pthread.h>
|
||||
#include <errno.h>
|
||||
|
||||
#include "stm_ioctls.h"
|
||||
#include "common.h"
|
||||
#include "output.h"
|
||||
#include "debug.h"
|
||||
#include "misc.h"
|
||||
#include "pes.h"
|
||||
#include "writer.h"
|
||||
|
||||
/* ***************************** */
|
||||
/* Makros/Constants */
|
||||
/* ***************************** */
|
||||
|
||||
/* ***************************** */
|
||||
/* Types */
|
||||
/* ***************************** */
|
||||
|
||||
/* ***************************** */
|
||||
/* Variables */
|
||||
/* ***************************** */
|
||||
|
||||
/* ***************************** */
|
||||
/* Prototypes */
|
||||
/* ***************************** */
|
||||
|
||||
/* ***************************** */
|
||||
/* Functions */
|
||||
/* ***************************** */
|
||||
|
||||
int InsertVideoPrivateDataHeader(unsigned char *data, int payload_size)
|
||||
{
|
||||
BitPacker_t ld2 = {data, 0, 32};
|
||||
int i;
|
||||
|
||||
PutBits(&ld2, PES_PRIVATE_DATA_FLAG, 8);
|
||||
PutBits(&ld2, payload_size & 0xff, 8);
|
||||
PutBits(&ld2, (payload_size >> 8) & 0xff, 8);
|
||||
PutBits(&ld2, (payload_size >> 16) & 0xff, 8);
|
||||
|
||||
for (i = 4; i < (PES_PRIVATE_DATA_LENGTH + 1); i++)
|
||||
PutBits(&ld2, 0, 8);
|
||||
|
||||
FlushBits(&ld2);
|
||||
|
||||
return PES_PRIVATE_DATA_LENGTH + 1;
|
||||
|
||||
}
|
||||
|
||||
int InsertPesHeader(unsigned char *data, int size, unsigned char stream_id, unsigned long long int pts, int pic_start_code)
|
||||
{
|
||||
BitPacker_t ld2 = {data, 0, 32};
|
||||
|
||||
if (size > (MAX_PES_PACKET_SIZE - 13))
|
||||
{
|
||||
size = -1; // unbounded
|
||||
}
|
||||
|
||||
PutBits(&ld2, 0x0, 8);
|
||||
PutBits(&ld2, 0x0, 8);
|
||||
PutBits(&ld2, 0x1, 8); // Start Code
|
||||
PutBits(&ld2, stream_id, 8); // Stream_id = Audio Stream
|
||||
//4
|
||||
if (-1 == size)
|
||||
{
|
||||
PutBits(&ld2, 0x0, 16);
|
||||
}
|
||||
else
|
||||
{
|
||||
PutBits(&ld2, size + 3 + (pts != INVALID_PTS_VALUE ? 5 : 0) + (pic_start_code ? (5) : 0), 16); // PES_packet_length
|
||||
}
|
||||
//6 = 4+2
|
||||
PutBits(&ld2, 0x2, 2); // 10
|
||||
PutBits(&ld2, 0x0, 2); // PES_Scrambling_control
|
||||
PutBits(&ld2, 0x0, 1); // PES_Priority
|
||||
PutBits(&ld2, 0x0, 1); // data_alignment_indicator
|
||||
PutBits(&ld2, 0x0, 1); // Copyright
|
||||
PutBits(&ld2, 0x0, 1); // Original or Copy
|
||||
//7 = 6+1
|
||||
|
||||
if (pts != INVALID_PTS_VALUE)
|
||||
{
|
||||
PutBits(&ld2, 0x2, 2);
|
||||
}
|
||||
else
|
||||
{
|
||||
PutBits(&ld2, 0x0, 2); // PTS_DTS flag
|
||||
}
|
||||
|
||||
PutBits(&ld2, 0x0, 1); // ESCR_flag
|
||||
PutBits(&ld2, 0x0, 1); // ES_rate_flag
|
||||
PutBits(&ld2, 0x0, 1); // DSM_trick_mode_flag
|
||||
PutBits(&ld2, 0x0, 1); // additional_copy_ingo_flag
|
||||
PutBits(&ld2, 0x0, 1); // PES_CRC_flag
|
||||
PutBits(&ld2, 0x0, 1); // PES_extension_flag
|
||||
//8 = 7+1
|
||||
|
||||
if (pts != INVALID_PTS_VALUE)
|
||||
PutBits(&ld2, 0x5, 8);
|
||||
else
|
||||
PutBits(&ld2, 0x0, 8); // PES_header_data_length
|
||||
//9 = 8+1
|
||||
|
||||
if (pts != INVALID_PTS_VALUE)
|
||||
{
|
||||
PutBits(&ld2, 0x2, 4);
|
||||
PutBits(&ld2, (pts >> 30) & 0x7, 3);
|
||||
PutBits(&ld2, 0x1, 1);
|
||||
PutBits(&ld2, (pts >> 15) & 0x7fff, 15);
|
||||
PutBits(&ld2, 0x1, 1);
|
||||
PutBits(&ld2, pts & 0x7fff, 15);
|
||||
PutBits(&ld2, 0x1, 1);
|
||||
}
|
||||
//14 = 9+5
|
||||
|
||||
if (pic_start_code)
|
||||
{
|
||||
PutBits(&ld2, 0x0, 8);
|
||||
PutBits(&ld2, 0x0, 8);
|
||||
PutBits(&ld2, 0x1, 8); // Start Code
|
||||
PutBits(&ld2, pic_start_code & 0xff, 8); // 00, for picture start
|
||||
PutBits(&ld2, (pic_start_code >> 8) & 0xff, 8); // For any extra information (like in mpeg4p2, the pic_start_code)
|
||||
//14 + 4 = 18
|
||||
}
|
||||
|
||||
FlushBits(&ld2);
|
||||
|
||||
return (ld2.Ptr - data);
|
||||
}
|
268
libeplayer3/output/writer/sh4/vc1.c
Normal file
268
libeplayer3/output/writer/sh4/vc1.c
Normal file
@@ -0,0 +1,268 @@
|
||||
/*
|
||||
* linuxdvb output/writer handling.
|
||||
*
|
||||
* konfetti 2010 based on linuxdvb.c code from libeplayer2
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*
|
||||
*/
|
||||
|
||||
/* ***************************** */
|
||||
/* Includes */
|
||||
/* ***************************** */
|
||||
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
#include <unistd.h>
|
||||
#include <fcntl.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
#include <sys/ioctl.h>
|
||||
#include <sys/uio.h>
|
||||
#include <linux/dvb/video.h>
|
||||
#include <linux/dvb/audio.h>
|
||||
#include <memory.h>
|
||||
#include <asm/types.h>
|
||||
#include <pthread.h>
|
||||
#include <errno.h>
|
||||
|
||||
#include "stm_ioctls.h"
|
||||
#include "common.h"
|
||||
#include "output.h"
|
||||
#include "debug.h"
|
||||
#include "misc.h"
|
||||
#include "pes.h"
|
||||
#include "writer.h"
|
||||
|
||||
/* ***************************** */
|
||||
/* Makros/Constants */
|
||||
/* ***************************** */
|
||||
|
||||
#define WMV3_PRIVATE_DATA_LENGTH 4
|
||||
|
||||
#define METADATA_STRUCT_A_START 12
|
||||
#define METADATA_STRUCT_B_START 24
|
||||
#define METADATA_STRUCT_B_FRAMERATE_START 32
|
||||
#define METADATA_STRUCT_C_START 8
|
||||
|
||||
#define VC1_SEQUENCE_LAYER_METADATA_START_CODE 0x80
|
||||
#define VC1_FRAME_START_CODE 0x0d
|
||||
|
||||
/* ***************************** */
|
||||
/* 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
|
||||
};
|
||||
|
||||
/* ***************************** */
|
||||
/* Variables */
|
||||
/* ***************************** */
|
||||
|
||||
static int initialHeader = 1;
|
||||
static unsigned char FrameHeaderSeen = 0;
|
||||
|
||||
/* ***************************** */
|
||||
/* Prototypes */
|
||||
/* ***************************** */
|
||||
|
||||
/* ***************************** */
|
||||
/* MISC Functions */
|
||||
/* ***************************** */
|
||||
|
||||
static int reset()
|
||||
{
|
||||
initialHeader = 1;
|
||||
FrameHeaderSeen = 0;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int writeData(void *_call)
|
||||
{
|
||||
WriterAVCallData_t *call = (WriterAVCallData_t *) _call;
|
||||
|
||||
int len = 0;
|
||||
vc1_printf(10, "\n");
|
||||
|
||||
if (call == NULL)
|
||||
{
|
||||
vc1_err("call data is NULL...\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
if ((call->data == NULL) || (call->len <= 0))
|
||||
{
|
||||
vc1_err("parsing NULL Data. ignoring...\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (call->fd < 0)
|
||||
{
|
||||
vc1_err("file pointer < 0. ignoring ...\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
vc1_printf(10, "VideoPts %lld\n", call->Pts);
|
||||
vc1_printf(10, "Got Private Size %d\n", call->private_size);
|
||||
|
||||
if (initialHeader)
|
||||
{
|
||||
unsigned char PesHeader[PES_MAX_HEADER_SIZE];
|
||||
unsigned char PesPayload[128];
|
||||
unsigned char *PesPtr;
|
||||
unsigned int crazyFramerate = 0;
|
||||
struct iovec iov[2];
|
||||
|
||||
vc1_printf(10, "Framerate: %u\n", call->FrameRate);
|
||||
vc1_printf(10, "biWidth: %d\n", call->Width);
|
||||
vc1_printf(10, "biHeight: %d\n", call->Height);
|
||||
|
||||
crazyFramerate = ((10000000.0 / call->FrameRate) * 1000.0);
|
||||
vc1_printf(10, "crazyFramerate: %u\n", crazyFramerate);
|
||||
|
||||
memset(PesPayload, 0, sizeof(PesPayload));
|
||||
|
||||
PesPtr = PesPayload;
|
||||
|
||||
memcpy(PesPtr, SequenceLayerStartCode, sizeof(SequenceLayerStartCode));
|
||||
PesPtr += sizeof(SequenceLayerStartCode);
|
||||
|
||||
memcpy(PesPtr, Metadata, sizeof(Metadata));
|
||||
PesPtr += METADATA_STRUCT_C_START;
|
||||
PesPtr += WMV3_PRIVATE_DATA_LENGTH;
|
||||
|
||||
/* Metadata Header Struct A */
|
||||
*PesPtr++ = (call->Height >> 0) & 0xff;
|
||||
*PesPtr++ = (call->Height >> 8) & 0xff;
|
||||
*PesPtr++ = (call->Height >> 16) & 0xff;
|
||||
*PesPtr++ = call->Height >> 24;
|
||||
*PesPtr++ = (call->Width >> 0) & 0xff;
|
||||
*PesPtr++ = (call->Width >> 8) & 0xff;
|
||||
*PesPtr++ = (call->Width >> 16) & 0xff;
|
||||
*PesPtr++ = call->Width >> 24;
|
||||
|
||||
PesPtr += 12; /* Skip flag word and Struct B first 8 bytes */
|
||||
|
||||
*PesPtr++ = (crazyFramerate >> 0) & 0xff;
|
||||
*PesPtr++ = (crazyFramerate >> 8) & 0xff;
|
||||
*PesPtr++ = (crazyFramerate >> 16) & 0xff;
|
||||
*PesPtr++ = crazyFramerate >> 24;
|
||||
|
||||
iov[0].iov_base = PesHeader;
|
||||
iov[1].iov_base = PesPayload;
|
||||
iov[1].iov_len = PesPtr - PesPayload;
|
||||
iov[0].iov_len = InsertPesHeader(PesHeader, iov[1].iov_len, VC1_VIDEO_PES_START_CODE, INVALID_PTS_VALUE, 0);
|
||||
len = call->WriteV(call->fd, iov, 2);
|
||||
|
||||
/* For VC1 the codec private data is a standard vc1 sequence header so we just copy it to the output */
|
||||
iov[0].iov_base = PesHeader;
|
||||
iov[1].iov_base = call->private_data;
|
||||
iov[1].iov_len = call->private_size;
|
||||
iov[0].iov_len = InsertPesHeader(PesHeader, iov[1].iov_len, VC1_VIDEO_PES_START_CODE, INVALID_PTS_VALUE, 0);
|
||||
len = call->WriteV(call->fd, iov, 2);
|
||||
|
||||
initialHeader = 0;
|
||||
}
|
||||
|
||||
if (call->len > 0 && call->data)
|
||||
{
|
||||
uint32_t Position = 0;
|
||||
uint8_t insertSampleHeader = 1;
|
||||
|
||||
while (Position < call->len)
|
||||
{
|
||||
int32_t PacketLength = (call->len - Position) <= MAX_PES_PACKET_SIZE ?
|
||||
(call->len - Position) : MAX_PES_PACKET_SIZE;
|
||||
|
||||
int32_t Remaining = call->len - Position - PacketLength;
|
||||
|
||||
vc1_printf(20, "PacketLength=%d, Remaining=%d, Position=%d\n", PacketLength, Remaining, Position);
|
||||
|
||||
uint8_t PesHeader[PES_MAX_HEADER_SIZE];
|
||||
int32_t HeaderLength = InsertPesHeader(PesHeader, PacketLength, VC1_VIDEO_PES_START_CODE, call->Pts, 0);
|
||||
|
||||
if (insertSampleHeader)
|
||||
{
|
||||
const uint8_t Vc1FrameStartCode[] = {0, 0, 1, VC1_FRAME_START_CODE};
|
||||
|
||||
if (!FrameHeaderSeen && (call->len > 3) && (memcmp(call->data, Vc1FrameStartCode, 4) == 0))
|
||||
{
|
||||
FrameHeaderSeen = 1;
|
||||
}
|
||||
|
||||
if (!FrameHeaderSeen)
|
||||
{
|
||||
memcpy(&PesHeader[HeaderLength], Vc1FrameStartCode, sizeof(Vc1FrameStartCode));
|
||||
HeaderLength += sizeof(Vc1FrameStartCode);
|
||||
}
|
||||
insertSampleHeader = 0;
|
||||
}
|
||||
|
||||
struct iovec iov[2];
|
||||
iov[0].iov_base = PesHeader;
|
||||
iov[0].iov_len = HeaderLength;
|
||||
iov[1].iov_base = call->data + Position;
|
||||
iov[1].iov_len = PacketLength;
|
||||
|
||||
ssize_t l = call->WriteV(call->fd, iov, 2);
|
||||
if (l < 0)
|
||||
{
|
||||
len = l;
|
||||
break;
|
||||
}
|
||||
len += l;
|
||||
|
||||
Position += PacketLength;
|
||||
call->Pts = INVALID_PTS_VALUE;
|
||||
}
|
||||
}
|
||||
|
||||
vc1_printf(10, "< %d\n", len);
|
||||
return len;
|
||||
}
|
||||
|
||||
/* ***************************** */
|
||||
/* Writer Definition */
|
||||
/* ***************************** */
|
||||
|
||||
static WriterCaps_t caps =
|
||||
{
|
||||
"vc1",
|
||||
eVideo,
|
||||
"V_VC1",
|
||||
VIDEO_ENCODING_VC1,
|
||||
-1,
|
||||
-1
|
||||
};
|
||||
|
||||
struct Writer_s WriterVideoVC1 =
|
||||
{
|
||||
&reset,
|
||||
&writeData,
|
||||
&caps
|
||||
};
|
136
libeplayer3/output/writer/sh4/vorbis.c
Normal file
136
libeplayer3/output/writer/sh4/vorbis.c
Normal file
@@ -0,0 +1,136 @@
|
||||
/*
|
||||
* linuxdvb output/writer handling.
|
||||
*
|
||||
* konfetti 2010 based on linuxdvb.c code from libeplayer2
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*
|
||||
*/
|
||||
|
||||
/* ***************************** */
|
||||
/* Includes */
|
||||
/* ***************************** */
|
||||
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
#include <unistd.h>
|
||||
#include <fcntl.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
#include <sys/ioctl.h>
|
||||
#include <linux/dvb/video.h>
|
||||
#include <linux/dvb/audio.h>
|
||||
#include <memory.h>
|
||||
#include <asm/types.h>
|
||||
#include <pthread.h>
|
||||
#include <errno.h>
|
||||
|
||||
#include "stm_ioctls.h"
|
||||
#include "common.h"
|
||||
#include "output.h"
|
||||
#include "debug.h"
|
||||
#include "misc.h"
|
||||
#include "pes.h"
|
||||
#include "writer.h"
|
||||
|
||||
/* ***************************** */
|
||||
/* Makros/Constants */
|
||||
/* ***************************** */
|
||||
|
||||
/* ***************************** */
|
||||
/* Types */
|
||||
/* ***************************** */
|
||||
|
||||
/* ***************************** */
|
||||
/* Variables */
|
||||
/* ***************************** */
|
||||
|
||||
/* ***************************** */
|
||||
/* Prototypes */
|
||||
/* ***************************** */
|
||||
|
||||
/* ***************************** */
|
||||
/* MISC Functions */
|
||||
/* ***************************** */
|
||||
|
||||
static int reset()
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int writeData(void *_call)
|
||||
{
|
||||
WriterAVCallData_t *call = (WriterAVCallData_t *) _call;
|
||||
|
||||
unsigned char PesHeader[PES_MAX_HEADER_SIZE];
|
||||
|
||||
vorbis_printf(10, "\n");
|
||||
|
||||
if (call == NULL)
|
||||
{
|
||||
vorbis_err("call data is NULL...\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
vorbis_printf(10, "AudioPts %lld\n", call->Pts);
|
||||
|
||||
if ((call->data == NULL) || (call->len <= 0))
|
||||
{
|
||||
vorbis_err("parsing NULL Data. ignoring...\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (call->fd < 0)
|
||||
{
|
||||
vorbis_err("file pointer < 0. ignoring ...\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
int HeaderLength = InsertPesHeader(PesHeader, call->len, MPEG_AUDIO_PES_START_CODE, call->Pts, 0);
|
||||
|
||||
unsigned char *PacketStart = malloc(call->len + HeaderLength);
|
||||
|
||||
memcpy(PacketStart, PesHeader, HeaderLength);
|
||||
memcpy(PacketStart + HeaderLength, call->data, call->len);
|
||||
|
||||
int len = write(call->fd, PacketStart, call->len + HeaderLength);
|
||||
|
||||
free(PacketStart);
|
||||
|
||||
vorbis_printf(10, "vorbis_Write-< len=%d\n", len);
|
||||
return len;
|
||||
}
|
||||
|
||||
/* ***************************** */
|
||||
/* Writer Definition */
|
||||
/* ***************************** */
|
||||
|
||||
static WriterCaps_t caps_vorbis =
|
||||
{
|
||||
"vorbis",
|
||||
eAudio,
|
||||
"A_VORBIS",
|
||||
AUDIO_ENCODING_VORBIS,
|
||||
-1,
|
||||
-1
|
||||
};
|
||||
|
||||
struct Writer_s WriterAudioVORBIS =
|
||||
{
|
||||
&reset,
|
||||
&writeData,
|
||||
&caps_vorbis
|
||||
};
|
179
libeplayer3/output/writer/sh4/wma.c
Normal file
179
libeplayer3/output/writer/sh4/wma.c
Normal file
@@ -0,0 +1,179 @@
|
||||
/*
|
||||
* linuxdvb output/writer handling.
|
||||
*
|
||||
* konfetti 2010 based on linuxdvb.c code from libeplayer2
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*
|
||||
*/
|
||||
|
||||
/* ***************************** */
|
||||
/* Includes */
|
||||
/* ***************************** */
|
||||
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
#include <unistd.h>
|
||||
#include <fcntl.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
#include <sys/ioctl.h>
|
||||
#include <sys/uio.h>
|
||||
#include <linux/dvb/video.h>
|
||||
#include <linux/dvb/audio.h>
|
||||
#include <memory.h>
|
||||
#include <asm/types.h>
|
||||
#include <pthread.h>
|
||||
#include <errno.h>
|
||||
|
||||
#include "stm_ioctls.h"
|
||||
#include "common.h"
|
||||
#include "output.h"
|
||||
#include "debug.h"
|
||||
#include "misc.h"
|
||||
#include "pes.h"
|
||||
#include "writer.h"
|
||||
|
||||
/* ***************************** */
|
||||
/* Makros/Constants */
|
||||
/* ***************************** */
|
||||
|
||||
/* ***************************** */
|
||||
/* Types */
|
||||
/* ***************************** */
|
||||
|
||||
/* ***************************** */
|
||||
/* Variables */
|
||||
/* ***************************** */
|
||||
|
||||
static int initialHeader = 1;
|
||||
|
||||
/* ***************************** */
|
||||
/* Prototypes */
|
||||
/* ***************************** */
|
||||
|
||||
/* ***************************** */
|
||||
/* MISC Functions */
|
||||
/* ***************************** */
|
||||
|
||||
static int reset()
|
||||
{
|
||||
initialHeader = 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int writeData(void *_call)
|
||||
{
|
||||
WriterAVCallData_t *call = (WriterAVCallData_t *) _call;
|
||||
|
||||
int len = 0;
|
||||
|
||||
wma_printf(10, "\n");
|
||||
|
||||
if (call == NULL)
|
||||
{
|
||||
wma_err("call data is NULL...\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
wma_printf(10, "AudioPts %lld\n", call->Pts);
|
||||
|
||||
if ((call->data == NULL) || (call->len <= 0))
|
||||
{
|
||||
wma_err("parsing NULL Data. ignoring...\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (call->fd < 0)
|
||||
{
|
||||
wma_err("file pointer < 0. ignoring ...\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (initialHeader)
|
||||
{
|
||||
unsigned char PesHeader[PES_MAX_HEADER_SIZE];
|
||||
|
||||
if ((call->private_size <= 0) || (call->private_data == NULL))
|
||||
{
|
||||
wma_err("private NULL.\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
struct iovec iov[2];
|
||||
iov[0].iov_base = PesHeader;
|
||||
iov[0].iov_len = InsertPesHeader(PesHeader, call->private_size, MPEG_AUDIO_PES_START_CODE, 0, 0);
|
||||
iov[1].iov_base = call->private_data;
|
||||
iov[1].iov_len = call->private_size;
|
||||
len = call->WriteV(call->fd, iov, 2);
|
||||
initialHeader = 0;
|
||||
}
|
||||
|
||||
if (len > -1 && call->len > 0 && call->data)
|
||||
{
|
||||
unsigned char PesHeader[PES_MAX_HEADER_SIZE];
|
||||
struct iovec iov[2];
|
||||
iov[0].iov_base = PesHeader;
|
||||
iov[0].iov_len = InsertPesHeader(PesHeader, call->len, MPEG_AUDIO_PES_START_CODE, call->Pts, 0);
|
||||
iov[1].iov_base = call->data;
|
||||
iov[1].iov_len = call->len;
|
||||
|
||||
ssize_t l = call->WriteV(call->fd, iov, 2);
|
||||
len = (l > -1) ? len + l : l;
|
||||
}
|
||||
|
||||
wma_printf(10, "wma < %d\n", len);
|
||||
|
||||
return len;
|
||||
}
|
||||
|
||||
/* ***************************** */
|
||||
/* Writer Definition */
|
||||
/* ***************************** */
|
||||
|
||||
static WriterCaps_t capsWMAPRO =
|
||||
{
|
||||
"wma/pro",
|
||||
eAudio,
|
||||
"A_WMA/PRO",
|
||||
AUDIO_ENCODING_WMA,
|
||||
-1,
|
||||
-1
|
||||
};
|
||||
|
||||
struct Writer_s WriterAudioWMAPRO =
|
||||
{
|
||||
&reset,
|
||||
&writeData,
|
||||
&capsWMAPRO
|
||||
};
|
||||
|
||||
static WriterCaps_t capsWMA =
|
||||
{
|
||||
"wma",
|
||||
eAudio,
|
||||
"A_WMA",
|
||||
AUDIO_ENCODING_WMA,
|
||||
-1,
|
||||
-1
|
||||
};
|
||||
|
||||
struct Writer_s WriterAudioWMA =
|
||||
{
|
||||
&reset,
|
||||
&writeData,
|
||||
&capsWMA
|
||||
};
|
262
libeplayer3/output/writer/sh4/wmv.c
Normal file
262
libeplayer3/output/writer/sh4/wmv.c
Normal file
@@ -0,0 +1,262 @@
|
||||
/*
|
||||
* linuxdvb output/writer handling.
|
||||
*
|
||||
* konfetti 2010 based on linuxdvb.c code from libeplayer2
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*
|
||||
*/
|
||||
|
||||
/* ***************************** */
|
||||
/* Includes */
|
||||
/* ***************************** */
|
||||
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
#include <unistd.h>
|
||||
#include <fcntl.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
#include <sys/ioctl.h>
|
||||
#include <sys/uio.h>
|
||||
#include <linux/dvb/video.h>
|
||||
#include <linux/dvb/audio.h>
|
||||
#include <memory.h>
|
||||
#include <asm/types.h>
|
||||
#include <pthread.h>
|
||||
#include <errno.h>
|
||||
|
||||
#include "stm_ioctls.h"
|
||||
#include "common.h"
|
||||
#include "output.h"
|
||||
#include "debug.h"
|
||||
#include "misc.h"
|
||||
#include "pes.h"
|
||||
#include "writer.h"
|
||||
|
||||
/* ***************************** */
|
||||
/* Makros/Constants */
|
||||
/* ***************************** */
|
||||
|
||||
#define WMV3_PRIVATE_DATA_LENGTH 4
|
||||
|
||||
#define METADATA_STRUCT_A_START 12
|
||||
#define METADATA_STRUCT_B_START 24
|
||||
#define METADATA_STRUCT_B_FRAMERATE_START 32
|
||||
#define METADATA_STRUCT_C_START 8
|
||||
|
||||
/* ***************************** */
|
||||
/* 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
|
||||
};
|
||||
|
||||
/* ***************************** */
|
||||
/* Variables */
|
||||
/* ***************************** */
|
||||
|
||||
static int initialHeader = 1;
|
||||
|
||||
/* ***************************** */
|
||||
/* Prototypes */
|
||||
/* ***************************** */
|
||||
|
||||
/* ***************************** */
|
||||
/* MISC Functions */
|
||||
/* ***************************** */
|
||||
|
||||
static int reset()
|
||||
{
|
||||
initialHeader = 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int writeData(void *_call)
|
||||
{
|
||||
WriterAVCallData_t *call = (WriterAVCallData_t *) _call;
|
||||
|
||||
awmv_t private_data;
|
||||
int len = 0;
|
||||
|
||||
wmv_printf(10, "\n");
|
||||
|
||||
if (call == NULL)
|
||||
{
|
||||
wmv_err("call data is NULL...\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
if ((call->data == NULL) || (call->len <= 0))
|
||||
{
|
||||
wmv_err("parsing NULL Data. ignoring...\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (call->fd < 0)
|
||||
{
|
||||
wmv_err("file pointer < 0. ignoring ...\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
wmv_printf(10, "VideoPts %lld\n", call->Pts);
|
||||
wmv_printf(10, "Got Private Size %d\n", call->private_size);
|
||||
|
||||
memcpy(private_data.privateData, call->private_data,
|
||||
call->private_size > WMV3_PRIVATE_DATA_LENGTH ? WMV3_PRIVATE_DATA_LENGTH : call->private_size);
|
||||
|
||||
private_data.width = call->Width;
|
||||
private_data.height = call->Height;
|
||||
private_data.framerate = call->FrameRate;
|
||||
|
||||
#define PES_MIN_HEADER_SIZE 9
|
||||
if (initialHeader)
|
||||
{
|
||||
unsigned char PesPacket[PES_MIN_HEADER_SIZE + 128];
|
||||
unsigned char *PesPtr;
|
||||
unsigned int MetadataLength;
|
||||
unsigned int crazyFramerate = 0;
|
||||
|
||||
wmv_printf(10, "Framerate: %u\n", private_data.framerate);
|
||||
wmv_printf(10, "biWidth: %d\n", private_data.width);
|
||||
wmv_printf(10, "biHeight: %d\n", private_data.height);
|
||||
|
||||
crazyFramerate = ((10000000.0 / private_data.framerate) * 1000.0);
|
||||
wmv_printf(10, "crazyFramerate: %u\n", crazyFramerate);
|
||||
|
||||
PesPtr = &PesPacket[PES_MIN_HEADER_SIZE];
|
||||
|
||||
memcpy(PesPtr, Metadata, sizeof(Metadata));
|
||||
PesPtr += METADATA_STRUCT_C_START;
|
||||
|
||||
memcpy(PesPtr, private_data.privateData, WMV3_PRIVATE_DATA_LENGTH);
|
||||
PesPtr += WMV3_PRIVATE_DATA_LENGTH;
|
||||
|
||||
/* Metadata Header Struct A */
|
||||
*PesPtr++ = (private_data.height >> 0) & 0xff;
|
||||
*PesPtr++ = (private_data.height >> 8) & 0xff;
|
||||
*PesPtr++ = (private_data.height >> 16) & 0xff;
|
||||
*PesPtr++ = private_data.height >> 24;
|
||||
*PesPtr++ = (private_data.width >> 0) & 0xff;
|
||||
*PesPtr++ = (private_data.width >> 8) & 0xff;
|
||||
*PesPtr++ = (private_data.width >> 16) & 0xff;
|
||||
*PesPtr++ = private_data.width >> 24;
|
||||
|
||||
PesPtr += 12; /* Skip flag word and Struct B first 8 bytes */
|
||||
|
||||
*PesPtr++ = (crazyFramerate >> 0) & 0xff;
|
||||
*PesPtr++ = (crazyFramerate >> 8) & 0xff;
|
||||
*PesPtr++ = (crazyFramerate >> 16) & 0xff;
|
||||
*PesPtr++ = crazyFramerate >> 24;
|
||||
|
||||
MetadataLength = PesPtr - &PesPacket[PES_MIN_HEADER_SIZE];
|
||||
|
||||
int HeaderLength = InsertPesHeader(PesPacket, MetadataLength, VC1_VIDEO_PES_START_CODE, INVALID_PTS_VALUE, 0);
|
||||
|
||||
len = write(call->fd, PesPacket, HeaderLength + MetadataLength);
|
||||
|
||||
initialHeader = 0;
|
||||
}
|
||||
|
||||
if (call->len > 0 && call->data)
|
||||
{
|
||||
unsigned int Position = 0;
|
||||
unsigned char insertSampleHeader = 1;
|
||||
while (Position < call->len)
|
||||
{
|
||||
int PacketLength = (call->len - Position) <= MAX_PES_PACKET_SIZE ?
|
||||
(call->len - Position) : MAX_PES_PACKET_SIZE;
|
||||
|
||||
int Remaining = call->len - Position - PacketLength;
|
||||
|
||||
wmv_printf(20, "PacketLength=%d, Remaining=%d, Position=%d\n", PacketLength, Remaining, Position);
|
||||
|
||||
unsigned char PesHeader[PES_MAX_HEADER_SIZE];
|
||||
memset(PesHeader, '0', PES_MAX_HEADER_SIZE);
|
||||
int HeaderLength = InsertPesHeader(PesHeader, PacketLength, VC1_VIDEO_PES_START_CODE, call->Pts, 0);
|
||||
unsigned char *PacketStart;
|
||||
|
||||
if (insertSampleHeader)
|
||||
{
|
||||
unsigned int PesLength;
|
||||
unsigned int PrivateHeaderLength;
|
||||
PrivateHeaderLength = InsertVideoPrivateDataHeader(&PesHeader[HeaderLength], call->len);
|
||||
/* Update PesLength */
|
||||
PesLength = PesHeader[PES_LENGTH_BYTE_0] +
|
||||
(PesHeader[PES_LENGTH_BYTE_1] << 8) + PrivateHeaderLength;
|
||||
PesHeader[PES_LENGTH_BYTE_0] = PesLength & 0xff;
|
||||
PesHeader[PES_LENGTH_BYTE_1] = (PesLength >> 8) & 0xff;
|
||||
PesHeader[PES_HEADER_DATA_LENGTH_BYTE] += PrivateHeaderLength;
|
||||
PesHeader[PES_FLAGS_BYTE] |= PES_EXTENSION_DATA_PRESENT;
|
||||
|
||||
HeaderLength += PrivateHeaderLength;
|
||||
insertSampleHeader = 0;
|
||||
}
|
||||
|
||||
PacketStart = malloc(call->len + HeaderLength);
|
||||
memcpy(PacketStart, PesHeader, HeaderLength);
|
||||
memcpy(PacketStart + HeaderLength, call->data + Position, PacketLength);
|
||||
|
||||
len = write(call->fd, PacketStart, PacketLength + HeaderLength);
|
||||
free(PacketStart);
|
||||
|
||||
Position += PacketLength;
|
||||
call->Pts = INVALID_PTS_VALUE;
|
||||
}
|
||||
}
|
||||
|
||||
wmv_printf(10, "< %d\n", len);
|
||||
return len;
|
||||
}
|
||||
|
||||
/* ***************************** */
|
||||
/* Writer Definition */
|
||||
/* ***************************** */
|
||||
|
||||
static WriterCaps_t caps =
|
||||
{
|
||||
"wmv",
|
||||
eVideo,
|
||||
"V_WMV",
|
||||
VIDEO_ENCODING_WMV,
|
||||
-1,
|
||||
-1
|
||||
};
|
||||
|
||||
struct Writer_s WriterVideoWMV =
|
||||
{
|
||||
&reset,
|
||||
&writeData,
|
||||
&caps
|
||||
};
|
202
libeplayer3/output/writer/sh4/writer.c
Normal file
202
libeplayer3/output/writer/sh4/writer.c
Normal file
@@ -0,0 +1,202 @@
|
||||
/*
|
||||
* 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 "misc.h"
|
||||
#include "writer.h"
|
||||
|
||||
/* ***************************** */
|
||||
/* Makros/Constants */
|
||||
/* ***************************** */
|
||||
|
||||
#ifdef SAM_WITH_DEBUG
|
||||
#define WRITER_DEBUG
|
||||
#else
|
||||
#define WRITER_SILENT
|
||||
#endif
|
||||
|
||||
#ifdef WRITER_DEBUG
|
||||
|
||||
static short debug_level = 0;
|
||||
|
||||
#define writer_printf(level, x...) do { \
|
||||
if (debug_level >= level) printf(x); } while (0)
|
||||
#else
|
||||
#define writer_printf(level, x...)
|
||||
#endif
|
||||
|
||||
#ifndef WRITER_SILENT
|
||||
#define writer_err(x...) do { printf(x); } while (0)
|
||||
#else
|
||||
#define writer_err(x...)
|
||||
#endif
|
||||
|
||||
/* ***************************** */
|
||||
/* Types */
|
||||
/* ***************************** */
|
||||
|
||||
/* ***************************** */
|
||||
/* Variables */
|
||||
/* ***************************** */
|
||||
|
||||
static Writer_t *AvailableWriter[] =
|
||||
{
|
||||
&WriterAudioIPCM,
|
||||
&WriterAudioPCM,
|
||||
&WriterAudioMP3,
|
||||
&WriterAudioMPEGL3,
|
||||
&WriterAudioAC3,
|
||||
&WriterAudioAAC,
|
||||
&WriterAudioDTS,
|
||||
&WriterAudioWMA,
|
||||
&WriterAudioVORBIS,
|
||||
|
||||
&WriterVideoMPEG2,
|
||||
&WriterVideoMPEGH264,
|
||||
&WriterVideoH264,
|
||||
&WriterVideoDIVX,
|
||||
&WriterVideoFOURCC,
|
||||
&WriterVideoMSCOMP,
|
||||
&WriterVideoWMV,
|
||||
&WriterVideoH263,
|
||||
&WriterVideoFLV,
|
||||
&WriterVideoVC1,
|
||||
NULL
|
||||
};
|
||||
|
||||
// &WriterAudioFLAC,
|
||||
|
||||
/* ***************************** */
|
||||
/* Prototypes */
|
||||
/* ***************************** */
|
||||
|
||||
/* ***************************** */
|
||||
/* Functions */
|
||||
/* ***************************** */
|
||||
ssize_t WriteWithRetry(Context_t *context, int pipefd, int fd, void *pDVBMtx, const void *buf, int size)
|
||||
{
|
||||
fd_set rfds;
|
||||
|
||||
ssize_t ret;
|
||||
int retval = -1;
|
||||
struct timeval tv;
|
||||
|
||||
while (size > 0 && 0 == PlaybackDieNow(0) && !context->playback->isSeeking)
|
||||
{
|
||||
if (context->playback->isPaused)
|
||||
{
|
||||
FD_ZERO(&rfds);
|
||||
FD_SET(pipefd, &rfds);
|
||||
|
||||
tv.tv_sec = 0;
|
||||
tv.tv_usec = 500000; // 500ms
|
||||
|
||||
retval = select(pipefd + 1, &rfds, NULL, NULL, &tv);
|
||||
if (retval < 0)
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
if (retval == 0)
|
||||
{
|
||||
//printf("RETURN FROM SELECT DUE TO TIMEOUT TIMEOUT\n");
|
||||
continue;
|
||||
}
|
||||
|
||||
if (FD_ISSET(pipefd, &rfds))
|
||||
{
|
||||
FlushPipe(pipefd);
|
||||
//printf("RETURN FROM SELECT DUE TO pipefd SET\n");
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
//printf(">> Before Write fd [%d]\n", fd);
|
||||
ret = write(fd, buf, size);
|
||||
//printf(">> After Write ret[%d] size[%d]\n", (int)ret, size);
|
||||
if (ret == size)
|
||||
ret = 0; // no error
|
||||
|
||||
break;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
Reference in New Issue
Block a user