libeplayer3: implement Writer class

This commit is contained in:
martii
2014-04-06 11:35:17 +02:00
parent 25948637ab
commit d97d2a84d8
26 changed files with 849 additions and 2357 deletions

View File

@@ -37,6 +37,10 @@
#include <pthread.h>
#include <errno.h>
#include <OpenThreads/ScopedLock>
#include <OpenThreads/Thread>
#include <OpenThreads/Condition>
#include "common.h"
#include "output.h"
#include "writer.h"
@@ -69,12 +73,26 @@ if (debug_level >= level) printf("[%s:%s] " fmt, __FILE__, __FUNCTION__, ## x );
#define cERR_LINUXDVB_NO_ERROR 0
#define cERR_LINUXDVB_ERROR -1
#define dioctl(fd,req,arg) ({ \
int _r = ioctl(fd,req,arg); \
if (_r) \
fprintf(stderr, "%s %d: ioctl '%s' failed: %d (%s)\n", __FILE__, __LINE__, #req, errno, strerror(errno)); \
_r; \
})
static const char VIDEODEV[] = "/dev/dvb/adapter0/video0";
static const char AUDIODEV[] = "/dev/dvb/adapter0/audio0";
static int videofd = -1;
static int audiofd = -1;
static Writer *videoWriter = NULL;
static Writer *audioWriter = NULL;
OpenThreads::Mutex audioMutex, videoMutex;
AVStream *audioStream = NULL;
AVStream *videoStream = NULL;
unsigned long long int sCURRENT_PTS = 0;
pthread_mutex_t LinuxDVBmutex;
@@ -119,7 +137,7 @@ int LinuxDvbOpen(Context_t * context __attribute__ ((unused)), char *type)
linuxdvb_printf(10, "v%d a%d\n", video, audio);
if (video && videofd < 0) {
if (videoStream && videofd < 0) {
videofd = open(VIDEODEV, O_RDWR);
if (videofd < 0) {
@@ -129,29 +147,10 @@ int LinuxDvbOpen(Context_t * context __attribute__ ((unused)), char *type)
return cERR_LINUXDVB_ERROR;
}
if (ioctl(videofd, VIDEO_CLEAR_BUFFER) == -1) {
linuxdvb_err("ioctl failed with errno %d\n", errno);
linuxdvb_err("VIDEO_CLEAR_BUFFER: %s\n", strerror(errno));
}
if (ioctl
(videofd, VIDEO_SELECT_SOURCE,
(void *) VIDEO_SOURCE_MEMORY) == -1) {
linuxdvb_err("ioctl failed with errno %d\n", errno);
linuxdvb_err("VIDEO_SELECT_SOURCE: %s\n", strerror(errno));
}
if (ioctl
(videofd, VIDEO_SET_STREAMTYPE,
(void *) STREAM_TYPE_PROGRAM) == -1) {
linuxdvb_err("ioctl failed with errno %d\n", errno);
linuxdvb_err("VIDEO_SET_STREAMTYPE: %s\n", strerror(errno));
}
if (ioctl(videofd, VIDEO_SET_SPEED, DVB_SPEED_NORMAL_PLAY) == -1) {
linuxdvb_err("ioctl failed with errno %d\n", errno);
linuxdvb_err("VIDEO_SET_SPEED: %s\n", strerror(errno));
}
dioctl(videofd, VIDEO_CLEAR_BUFFER, NULL);
dioctl(videofd, VIDEO_SELECT_SOURCE, (void *) VIDEO_SOURCE_MEMORY);
dioctl(videofd, VIDEO_SET_STREAMTYPE, (void *) STREAM_TYPE_PROGRAM);
dioctl(videofd, VIDEO_SET_SPEED, DVB_SPEED_NORMAL_PLAY);
}
if (audio && audiofd < 0) {
@@ -167,24 +166,9 @@ int LinuxDvbOpen(Context_t * context __attribute__ ((unused)), char *type)
return cERR_LINUXDVB_ERROR;
}
if (ioctl(audiofd, AUDIO_CLEAR_BUFFER) == -1) {
linuxdvb_err("ioctl failed with errno %d\n", errno);
linuxdvb_err("AUDIO_CLEAR_BUFFER: %s\n", strerror(errno));
}
if (ioctl
(audiofd, AUDIO_SELECT_SOURCE,
(void *) AUDIO_SOURCE_MEMORY) == -1) {
linuxdvb_err("ioctl failed with errno %d\n", errno);
linuxdvb_err("AUDIO_SELECT_SOURCE: %s\n", strerror(errno));
}
if (ioctl
(audiofd, AUDIO_SET_STREAMTYPE,
(void *) STREAM_TYPE_PROGRAM) == -1) {
linuxdvb_err("ioctl failed with errno %d\n", errno);
linuxdvb_err("AUDIO_SET_STREAMTYPE: %s\n", strerror(errno));
}
dioctl(audiofd, AUDIO_CLEAR_BUFFER, NULL);
dioctl(audiofd, AUDIO_SELECT_SOURCE, (void *) AUDIO_SOURCE_MEMORY);
dioctl(audiofd, AUDIO_SET_STREAMTYPE, (void *) STREAM_TYPE_PROGRAM);
}
return cERR_LINUXDVB_NO_ERROR;
@@ -221,90 +205,29 @@ int LinuxDvbClose(Context_t * context, char *type)
int LinuxDvbPlay(Context_t * context, char *type)
{
int ret = cERR_LINUXDVB_NO_ERROR;
Writer_t *writer;
unsigned char video = !strcmp("video", type);
unsigned char audio = !strcmp("audio", type);
linuxdvb_printf(10, "v%d a%d\n", video, audio);
if (video && videofd != -1) {
char *Encoding = NULL;
context->manager->video->Command(context, MANAGER_GETENCODING,
&Encoding);
AVStream *_videoStream = videoStream;
AVStream *_audioStream = audioStream;
if (_videoStream)
videoWriter = Writer::GetWriter(_videoStream->codec->codec_id, _videoStream->codec->codec_type);
if (_audioStream)
audioWriter = Writer::GetWriter(_audioStream->codec->codec_id, _audioStream->codec->codec_type);
linuxdvb_printf(10, "V %s\n", Encoding);
if (_videoStream && videofd > -1) {
writer = getWriter(Encoding);
if (writer == NULL) {
linuxdvb_err
("cannot found writer for encoding %s using default\n",
Encoding);
if (ioctl
(videofd, VIDEO_SET_ENCODING,
(void *) VIDEO_ENCODING_AUTO) == -1) {
linuxdvb_err("ioctl failed with errno %d\n", errno);
linuxdvb_err("VIDEO_SET_ENCODING: %s\n", strerror(errno));
ret = cERR_LINUXDVB_ERROR;
}
} else {
linuxdvb_printf(20, "found writer %s for encoding %s\n",
writer->caps->name, Encoding);
if (ioctl
(videofd, VIDEO_SET_ENCODING,
(void *) writer->caps->dvbEncoding) == -1) {
linuxdvb_err("ioctl failed with errno %d\n", errno);
linuxdvb_err("VIDEO_SET_ENCODING: %s\n", strerror(errno));
ret = cERR_LINUXDVB_ERROR;
}
}
if (ioctl(videofd, VIDEO_PLAY, NULL) == -1) {
linuxdvb_err("ioctl failed with errno %d\n", errno);
linuxdvb_err("VIDEO_PLAY: %s\n", strerror(errno));
if (dioctl(videofd, VIDEO_SET_ENCODING, videoWriter->GetVideoEncoding(_videoStream->codec->codec_id))
|| dioctl(videofd, VIDEO_PLAY, NULL))
ret = cERR_LINUXDVB_ERROR;
}
free(Encoding);
}
if (audio && audiofd != -1) {
char *Encoding = NULL;
context->manager->audio->Command(context, MANAGER_GETENCODING,
&Encoding);
linuxdvb_printf(20, "0 A %s\n", Encoding);
writer = getWriter(Encoding);
if (writer == NULL) {
linuxdvb_err
("cannot found writer for encoding %s using default\n",
Encoding);
if (ioctl
(audiofd, AUDIO_SET_ENCODING,
(void *) AUDIO_ENCODING_MP3) == -1) {
linuxdvb_err("ioctl failed with errno %d\n", errno);
linuxdvb_err("AUDIO_SET_ENCODING: %s\n", strerror(errno));
ret = cERR_LINUXDVB_ERROR;
}
} else {
linuxdvb_printf(20, "found writer %s for encoding %s\n",
writer->caps->name, Encoding);
if (ioctl
(audiofd, AUDIO_SET_ENCODING,
(void *) writer->caps->dvbEncoding) == -1) {
linuxdvb_err("ioctl failed with errno %d\n", errno);
linuxdvb_err("AUDIO_SET_ENCODING: %s\n", strerror(errno));
ret = -1;
}
}
if (ioctl(audiofd, AUDIO_PLAY, NULL) == -1) {
linuxdvb_err("ioctl failed with errno %d\n", errno);
linuxdvb_err("AUDIO_PLAY: %s\n", strerror(errno));
if (_audioStream && audiofd > -1) {
if (dioctl(audiofd, AUDIO_SET_ENCODING, audioWriter->GetAudioEncoding(_audioStream->codec->codec_id))
|| dioctl(audiofd, AUDIO_PLAY, NULL))
ret = cERR_LINUXDVB_ERROR;
}
free(Encoding);
}
return ret;
@@ -321,38 +244,22 @@ int LinuxDvbStop(Context_t * context __attribute__ ((unused)), char *type)
getLinuxDVBMutex(FILENAME, __FUNCTION__, __LINE__);
if (video && videofd != -1) {
if (ioctl(videofd, VIDEO_CLEAR_BUFFER) == -1) {
linuxdvb_err("ioctl failed with errno %d\n", errno);
linuxdvb_err("VIDEO_CLEAR_BUFFER: %s\n", strerror(errno));
}
dioctl(videofd, VIDEO_CLEAR_BUFFER, NULL);
/* set back to normal speed (end trickmodes) */
if (ioctl(videofd, VIDEO_SET_SPEED, DVB_SPEED_NORMAL_PLAY) == -1) {
linuxdvb_err("ioctl failed with errno %d\n", errno);
linuxdvb_err("VIDEO_SET_SPEED: %s\n", strerror(errno));
}
if (ioctl(videofd, VIDEO_STOP, NULL) == -1) {
linuxdvb_err("ioctl failed with errno %d\n", errno);
linuxdvb_err("VIDEO_STOP: %s\n", strerror(errno));
dioctl(videofd, VIDEO_SET_SPEED, DVB_SPEED_NORMAL_PLAY);
if (dioctl(videofd, VIDEO_STOP, NULL))
ret = cERR_LINUXDVB_ERROR;
}
}
if (audio && audiofd != -1) {
if (ioctl(audiofd, AUDIO_CLEAR_BUFFER) == -1) {
linuxdvb_err("ioctl failed with errno %d\n", errno);
linuxdvb_err("AUDIO_CLEAR_BUFFER: %s\n", strerror(errno));
}
dioctl(audiofd, AUDIO_CLEAR_BUFFER, NULL);
/* set back to normal speed (end trickmodes) */
if (ioctl(audiofd, AUDIO_SET_SPEED, DVB_SPEED_NORMAL_PLAY) == -1) {
linuxdvb_err("ioctl failed with errno %d\n", errno);
linuxdvb_err("AUDIO_SET_SPEED: %s\n", strerror(errno));
}
if (ioctl(audiofd, AUDIO_STOP, NULL) == -1) {
linuxdvb_err("ioctl failed with errno %d\n", errno);
linuxdvb_err("AUDIO_STOP: %s\n", strerror(errno));
dioctl(audiofd, AUDIO_SET_SPEED, DVB_SPEED_NORMAL_PLAY);
if (dioctl(audiofd, AUDIO_STOP, NULL))
ret = cERR_LINUXDVB_ERROR;
}
}
releaseLinuxDVBMutex(FILENAME, __FUNCTION__, __LINE__);
@@ -371,18 +278,12 @@ int LinuxDvbPause(Context_t * context __attribute__ ((unused)), char *type)
getLinuxDVBMutex(FILENAME, __FUNCTION__, __LINE__);
if (video && videofd != -1) {
if (ioctl(videofd, VIDEO_FREEZE, NULL) == -1) {
linuxdvb_err("ioctl failed with errno %d\n", errno);
linuxdvb_err("VIDEO_FREEZE: %s\n", strerror(errno));
if (dioctl(videofd, VIDEO_FREEZE, NULL))
ret = cERR_LINUXDVB_ERROR;
}
}
if (audio && audiofd != -1) {
if (ioctl(audiofd, AUDIO_PAUSE, NULL) == -1) {
linuxdvb_err("ioctl failed with errno %d\n", errno);
linuxdvb_err("AUDIO_PAUSE: %s\n", strerror(errno));
if (dioctl(audiofd, AUDIO_PAUSE, NULL))
ret = cERR_LINUXDVB_ERROR;
}
}
releaseLinuxDVBMutex(FILENAME, __FUNCTION__, __LINE__);
@@ -400,18 +301,12 @@ int LinuxDvbContinue(Context_t * context
linuxdvb_printf(10, "v%d a%d\n", video, audio);
if (video && videofd != -1) {
if (ioctl(videofd, VIDEO_CONTINUE, NULL) == -1) {
linuxdvb_err("ioctl failed with errno %d\n", errno);
linuxdvb_err("VIDEO_CONTINUE: %s\n", strerror(errno));
if (dioctl(videofd, VIDEO_CONTINUE, NULL))
ret = cERR_LINUXDVB_ERROR;
}
}
if (audio && audiofd != -1) {
if (ioctl(audiofd, AUDIO_CONTINUE, NULL) == -1) {
linuxdvb_err("ioctl failed with errno %d\n", errno);
linuxdvb_err("AUDIO_CONTINUE: %s\n", strerror(errno));
if (dioctl(audiofd, AUDIO_CONTINUE, NULL))
ret = cERR_LINUXDVB_ERROR;
}
}
linuxdvb_printf(10, "exiting\n");
@@ -428,10 +323,7 @@ int LinuxDvbReverseDiscontinuity(Context_t * context
linuxdvb_printf(50, "\n");
if (ioctl(videofd, VIDEO_DISCONTINUITY, (void *) dis_type) == -1) {
linuxdvb_err("ioctl failed with errno %d\n", errno);
linuxdvb_err("VIDEO_DISCONTINUITY: %s\n", strerror(errno));
}
dioctl(videofd, VIDEO_DISCONTINUITY, (void *) dis_type);
linuxdvb_printf(50, "exiting\n");
@@ -449,21 +341,13 @@ int LinuxDvbAudioMute(Context_t * context
if (*flag == '1') {
//AUDIO_SET_MUTE has no effect with new player
//if (ioctl(audiofd, AUDIO_SET_MUTE, 1) == -1)
if (ioctl(audiofd, AUDIO_STOP, NULL) == -1) {
linuxdvb_err("ioctl failed with errno %d\n", errno);
//linuxdvb_err("AUDIO_SET_MUTE: %s\n", strerror(errno));
linuxdvb_err("AUDIO_STOP: %s\n", strerror(errno));
if (dioctl(audiofd, AUDIO_STOP, NULL))
ret = cERR_LINUXDVB_ERROR;
}
} else {
//AUDIO_SET_MUTE has no effect with new player
//if (ioctl(audiofd, AUDIO_SET_MUTE, 0) == -1)
if (ioctl(audiofd, AUDIO_PLAY, NULL) == -1) {
linuxdvb_err("ioctl failed with errno %d\n", errno);
//linuxdvb_err("AUDIO_SET_MUTE: %s\n", strerror(errno));
linuxdvb_err("AUDIO_PLAY: %s\n", strerror(errno));
if (dioctl(audiofd, AUDIO_PLAY, NULL))
ret = cERR_LINUXDVB_ERROR;
}
}
}
@@ -483,19 +367,11 @@ int LinuxDvbFlush(Context_t * context __attribute__ ((unused)), char *type)
if ((video && videofd != -1) || (audio && audiofd != -1)) {
getLinuxDVBMutex(FILENAME, __FUNCTION__, __LINE__);
if (video && videofd != -1) {
if (ioctl(videofd, VIDEO_FLUSH, NULL) == -1) {
linuxdvb_err("ioctl failed with errno %d\n", errno);
linuxdvb_err("VIDEO_FLUSH: %s\n", strerror(errno));
}
}
if (video && videofd != -1)
dioctl(videofd, VIDEO_FLUSH, NULL);
if (audio && audiofd != -1) {
if (ioctl(audiofd, AUDIO_FLUSH, NULL) == -1) {
linuxdvb_err("ioctl failed with errno %d\n", errno);
linuxdvb_err("AUDIO_FLUSH: %s\n", strerror(errno));
}
}
if (audio && audiofd != -1)
dioctl(audiofd, AUDIO_FLUSH, NULL);
releaseLinuxDVBMutex(FILENAME, __FUNCTION__, __LINE__);
}
@@ -522,12 +398,8 @@ int LinuxDvbFastForward(Context_t * context, char *type)
/* konfetti comment: speed is a value given in skipped frames */
if (ioctl(videofd, VIDEO_FAST_FORWARD, context->playback->Speed) ==
-1) {
linuxdvb_err("ioctl failed with errno %d\n", errno);
linuxdvb_err("VIDEO_FAST_FORWARD: %s\n", strerror(errno));
if (dioctl(videofd, VIDEO_FAST_FORWARD, context->playback->Speed))
ret = cERR_LINUXDVB_ERROR;
}
releaseLinuxDVBMutex(FILENAME, __FUNCTION__, __LINE__);
}
@@ -538,12 +410,7 @@ int LinuxDvbFastForward(Context_t * context, char *type)
}
#else
static unsigned int SpeedList[] = {
1000, 1100, 1200, 1300, 1500,
2000, 3000, 4000, 5000, 8000,
12000, 16000,
125, 250, 500, 700, 800, 900
};
static unsigned int SpeedList[] = { 1000, 1100, 1200, 1300, 1500, 2000, 3000, 4000, 5000, 8000, 12000, 16000, 125, 250, 500, 700, 800, 900 };
int LinuxDvbFastForward(Context_t * context, char *type)
{
@@ -558,16 +425,12 @@ int LinuxDvbFastForward(Context_t * context, char *type)
getLinuxDVBMutex(FILENAME, __FUNCTION__, __LINE__);
speedIndex =
context->playback->Speed % (sizeof(SpeedList) / sizeof(int));
speedIndex = context->playback->Speed % (sizeof(SpeedList) / sizeof(int));
linuxdvb_printf(1, "speedIndex %d\n", speedIndex);
if (ioctl(videofd, VIDEO_SET_SPEED, SpeedList[speedIndex]) == -1) {
linuxdvb_err("ioctl failed with errno %d\n", errno);
linuxdvb_err("VIDEO_SET_SPEED: %s\n", strerror(errno));
if (dioctl(videofd, VIDEO_SET_SPEED, SpeedList[speedIndex]))
ret = cERR_LINUXDVB_ERROR;
}
releaseLinuxDVBMutex(FILENAME, __FUNCTION__, __LINE__);
}
@@ -581,9 +444,7 @@ int LinuxDvbFastForward(Context_t * context, char *type)
linuxdvb_printf(1, "speedIndex %d\n", speedIndex);
if (ioctl(audiofd, AUDIO_SET_SPEED, SpeedList[speedIndex]) == -1) {
linuxdvb_err("ioctl failed with errno %d\n", errno);
linuxdvb_err("AUDIO_SET_SPEED: %s\n", strerror(errno));
if (dioctl(audiofd, AUDIO_SET_SPEED, SpeedList[speedIndex])) {
ret = cERR_LINUXDVB_ERROR;
}
@@ -618,11 +479,7 @@ int LinuxDvbSlowMotion(Context_t * context, char *type)
getLinuxDVBMutex(FILENAME, __FUNCTION__, __LINE__);
if (video && videofd != -1) {
if (ioctl
(videofd, VIDEO_SLOWMOTION,
context->playback->SlowMotion) == -1) {
linuxdvb_err("ioctl failed with errno %d\n", errno);
linuxdvb_err("VIDEO_SLOWMOTION: %s\n", strerror(errno));
if (dioctl (videofd, VIDEO_SLOWMOTION, context->playback->SlowMotion)) {
ret = cERR_LINUXDVB_ERROR;
}
}
@@ -648,12 +505,8 @@ int LinuxDvbAVSync(Context_t * context, char *type
if (audiofd != -1) {
getLinuxDVBMutex(FILENAME, __FUNCTION__, __LINE__);
if (ioctl(audiofd, AUDIO_SET_AV_SYNC, context->playback->AVSync) ==
-1) {
linuxdvb_err("ioctl failed with errno %d\n", errno);
linuxdvb_err("AUDIO_SET_AV_SYNC: %s\n", strerror(errno));
if (dioctl(audiofd, AUDIO_SET_AV_SYNC, context->playback->AVSync))
ret = cERR_LINUXDVB_ERROR;
}
releaseLinuxDVBMutex(FILENAME, __FUNCTION__, __LINE__);
}
@@ -673,18 +526,12 @@ int LinuxDvbClear(Context_t * context __attribute__ ((unused)), char *type)
getLinuxDVBMutex(FILENAME, __FUNCTION__, __LINE__);
if (video && videofd != -1) {
if (ioctl(videofd, VIDEO_CLEAR_BUFFER) == -1) {
linuxdvb_err("ioctl failed with errno %d\n", errno);
linuxdvb_err("VIDEO_CLEAR_BUFFER: %s\n", strerror(errno));
if (dioctl(videofd, VIDEO_CLEAR_BUFFER, NULL))
ret = cERR_LINUXDVB_ERROR;
}
}
if (audio && audiofd != -1) {
if (ioctl(audiofd, AUDIO_CLEAR_BUFFER) == -1) {
linuxdvb_err("ioctl failed with errno %d\n", errno);
linuxdvb_err("AUDIO_CLEAR_BUFFER: %s\n", strerror(errno));
if (dioctl(audiofd, AUDIO_CLEAR_BUFFER, NULL))
ret = cERR_LINUXDVB_ERROR;
}
}
releaseLinuxDVBMutex(FILENAME, __FUNCTION__, __LINE__);
@@ -705,8 +552,8 @@ int LinuxDvbPts(Context_t * context
// pts is a non writting requests and can be done in parallel to other requests
//getLinuxDVBMutex(FILENAME, __FUNCTION__,__LINE__);
if ((videofd > -1 && !ioctl(videofd, VIDEO_GET_PTS, (void *) &sCURRENT_PTS))
|| (audiofd > -1 && !ioctl(audiofd, AUDIO_GET_PTS, (void *) &sCURRENT_PTS)))
if ((videofd > -1 && !dioctl(videofd, VIDEO_GET_PTS, (void *) &sCURRENT_PTS))
|| (audiofd > -1 && !dioctl(audiofd, AUDIO_GET_PTS, (void *) &sCURRENT_PTS)))
ret = cERR_LINUXDVB_NO_ERROR;
else
sCURRENT_PTS = 0;
@@ -730,16 +577,12 @@ int LinuxDvbGetFrameCount(Context_t * context
getLinuxDVBMutex(FILENAME, __FUNCTION__, __LINE__);
if (videofd != -1) {
if (ioctl(videofd, VIDEO_GET_PLAY_INFO, (void *) &playInfo) == -1) {
linuxdvb_err("ioctl failed with errno %d\n", errno);
linuxdvb_err("VIDEO_GET_PLAY_INFO: %s\n", strerror(errno));
if (dioctl(videofd, VIDEO_GET_PLAY_INFO, (void *) &playInfo)) {
ret = cERR_LINUXDVB_ERROR;
} else
linuxdvb_err("V: %llu\n", playInfo.frame_count);
} else if (audiofd != -1) {
if (ioctl(audiofd, AUDIO_GET_PLAY_INFO, (void *) &playInfo) == -1) {
linuxdvb_err("ioctl failed with errno %d\n", errno);
linuxdvb_err("AUDIO_GET_PLAY_INFO: %s\n", strerror(errno));
if (dioctl(audiofd, AUDIO_GET_PLAY_INFO, (void *) &playInfo)) {
ret = cERR_LINUXDVB_ERROR;
} else
linuxdvb_err("A: %llu\n", playInfo.frame_count);
@@ -755,281 +598,57 @@ int LinuxDvbGetFrameCount(Context_t * context
return ret;
}
int LinuxDvbSwitch(Context_t * context, char *type)
bool output_switch_audio(AVStream *stream)
{
unsigned char audio = !strcmp("audio", type);
unsigned char video = !strcmp("video", type);
Writer_t *writer;
linuxdvb_printf(10, "v%d a%d\n", video, audio);
if ((video && videofd != -1) || (audio && audiofd != -1)) {
getLinuxDVBMutex(FILENAME, __FUNCTION__, __LINE__);
if (audio && audiofd != -1) {
char *Encoding = NULL;
if (context && context->manager && context->manager->audio) {
context->manager->audio->Command(context,
MANAGER_GETENCODING,
&Encoding);
linuxdvb_printf(10, "A %s\n", Encoding);
writer = getWriter(Encoding);
if (ioctl(audiofd, AUDIO_STOP, NULL) == -1) {
linuxdvb_err("ioctl failed with errno %d\n", errno);
linuxdvb_err("AUDIO_STOP: %s\n", strerror(errno));
}
if (ioctl(audiofd, AUDIO_CLEAR_BUFFER) == -1) {
linuxdvb_err("ioctl failed with errno %d\n", errno);
linuxdvb_err("AUDIO_CLEAR_BUFFER: %s\n",
strerror(errno));
}
if (writer == NULL) {
linuxdvb_err
("cannot found writer for encoding %s using default\n",
Encoding);
if (ioctl
(audiofd, AUDIO_SET_ENCODING,
(void *) AUDIO_ENCODING_MP3) == -1) {
linuxdvb_err("ioctl failed with errno %d\n",
errno);
linuxdvb_err("AUDIO_SET_ENCODING: %s\n",
strerror(errno));
}
} else {
linuxdvb_printf(10,
"found writer %s for encoding %s\n",
writer->caps->name, Encoding);
if (ioctl
(audiofd, AUDIO_SET_ENCODING,
(void *) writer->caps->dvbEncoding) == -1) {
linuxdvb_err("ioctl failed with errno %d\n",
errno);
linuxdvb_err("AUDIO_SET_ENCODING: %s\n",
strerror(errno));
}
}
if (ioctl(audiofd, AUDIO_PLAY, NULL) == -1) {
linuxdvb_err("ioctl failed with errno %d\n", errno);
linuxdvb_err("AUDIO_PLAY: %s\n", strerror(errno));
}
free(Encoding);
} else
linuxdvb_printf(20, "no context for Audio\n");
}
if (video && videofd != -1) {
char *Encoding = NULL;
if (context && context->manager && context->manager->video) {
context->manager->video->Command(context,
MANAGER_GETENCODING,
&Encoding);
if (ioctl(videofd, VIDEO_STOP, NULL) == -1) {
linuxdvb_err("ioctl failed with errno %d\n", errno);
linuxdvb_err("VIDEO_STOP: %s\n", strerror(errno));
}
if (ioctl(videofd, VIDEO_CLEAR_BUFFER) == -1) {
linuxdvb_err("ioctl failed with errno %d\n", errno);
linuxdvb_err("VIDEO_CLEAR_BUFFER: %s\n",
strerror(errno));
}
linuxdvb_printf(10, "V %s\n", Encoding);
writer = getWriter(Encoding);
if (writer == NULL) {
linuxdvb_err
("cannot found writer for encoding %s using default\n",
Encoding);
if (ioctl
(videofd, VIDEO_SET_ENCODING,
(void *) VIDEO_ENCODING_AUTO) == -1) {
linuxdvb_err("ioctl failed with errno %d\n",
errno);
linuxdvb_err("VIDEO_SET_ENCODING: %s\n",
strerror(errno));
}
} else {
linuxdvb_printf(10,
"found writer %s for encoding %s\n",
writer->caps->name, Encoding);
if (ioctl
(videofd, VIDEO_SET_ENCODING,
(void *) writer->caps->dvbEncoding) == -1) {
linuxdvb_err("ioctl failed with errno %d\n",
errno);
linuxdvb_err("VIDEO_SET_ENCODING: %s\n",
strerror(errno));
}
}
if (ioctl(videofd, VIDEO_PLAY, NULL) == -1) {
/* konfetti: fixme: think on this, I think we should
* return an error here and stop the playback mode
*/
linuxdvb_err("ioctl failed with errno %d\n", errno);
linuxdvb_err("VIDEO_PLAY: %s\n", strerror(errno));
}
free(Encoding);
} else
linuxdvb_printf(20, "no context for Video\n");
}
releaseLinuxDVBMutex(FILENAME, __FUNCTION__, __LINE__);
}
linuxdvb_printf(10, "exiting\n");
return cERR_LINUXDVB_NO_ERROR;
if (audiofd < 0)
return false;
audioMutex.lock();
audioStream = stream;
audioWriter = Writer::GetWriter(stream->codec->codec_id, stream->codec->codec_type);
audio_encoding_t enc = Writer::GetAudioEncoding(stream->codec->codec_id);
dioctl(audiofd, AUDIO_STOP, NULL);
dioctl(audiofd, AUDIO_CLEAR_BUFFER, NULL);
dioctl (audiofd, AUDIO_SET_ENCODING, (void *) enc);
dioctl(audiofd, AUDIO_PLAY, NULL);
audioMutex.unlock();
return true;
}
static int Write(Context_t *context, AudioVideoOut_t *out)
bool output_switch_video(AVStream *stream)
{
int ret = cERR_LINUXDVB_NO_ERROR;
int res = 0;
unsigned char video = 0;
unsigned char audio = 0;
Writer_t *writer;
WriterAVCallData_t call;
call.stream = out->stream;
call.avfc = out->avfc;
if (videofd < 0)
return false;
videoMutex.lock();
videoStream = stream;
videoWriter = Writer::GetWriter(stream->codec->codec_id, stream->codec->codec_type);
video_encoding_t enc = Writer::GetVideoEncoding(stream->codec->codec_id);
dioctl(videofd, VIDEO_STOP, NULL);
dioctl(videofd, VIDEO_CLEAR_BUFFER, NULL);
dioctl(videofd, VIDEO_SET_ENCODING, (void *) enc);
dioctl(videofd, VIDEO_PLAY, NULL);
videoMutex.unlock();
return true;
}
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 Pts=%llu\n", out->packet->size, out->pts);
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();
static bool Write(AVFormatContext *avfc, AVStream *stream, AVPacket *packet, int64_t &Pts)
{
switch (stream->codec->codec_type) {
case AVMEDIA_TYPE_VIDEO:
return videoWriter->Write(videofd, avfc, stream, packet, Pts);
case AVMEDIA_TYPE_AUDIO:
return audioWriter->Write(audiofd, avfc, stream, packet, Pts);
default:
return false;
}
if (writer == NULL) {
linuxdvb_err("unknown video codec and no default writer %s\n",
Encoding);
ret = cERR_LINUXDVB_ERROR;
} else {
call.fd = videofd;
call.Pts = out->pts;
call.packet = out->packet;
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, "%s::%s Encoding = %s\n", FILENAME,
__FUNCTION__, 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.Pts = out->pts;
call.packet = out->packet;
call.restart_audio_resampling = out->restart_audio_resampling;
call.context = context;
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)
{
int ret = cERR_LINUXDVB_NO_ERROR;
Writer_t *writer;
char *Encoding = NULL;
context->manager->video->Command(context, MANAGER_GETENCODING,
&Encoding);
writer = getWriter(Encoding);
if (writer == NULL) {
linuxdvb_err("unknown video codec %s\n", Encoding);
ret = cERR_LINUXDVB_ERROR;
} else {
writer->reset();
}
free(Encoding);
context->manager->audio->Command(context, MANAGER_GETENCODING,
&Encoding);
writer = getWriter(Encoding);
if (writer == NULL) {
linuxdvb_err("unknown video codec %s\n", Encoding);
ret = cERR_LINUXDVB_ERROR;
} else {
writer->reset();
}
free(Encoding);
return ret;
if (videoWriter)
videoWriter->Init();
if (audioWriter)
audioWriter->Init();
return cERR_LINUXDVB_NO_ERROR;
}
static int Command(Context_t *context, OutputCmd_t command, const char *argument)
@@ -1099,10 +718,6 @@ static int Command(Context_t *context, OutputCmd_t command, const char *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;

View File

@@ -271,16 +271,6 @@ static int Command(Context_t *context, OutputCmd_t command, const char *argument
ret = cERR_OUTPUT_INTERNAL_ERROR;
break;
}
case OUTPUT_SWITCH:{
if (context && context->playback) {
if (context->playback->isAudio)
return context->output->audio->Command(context, OUTPUT_SWITCH, "audio");
if (context->playback->isVideo)
return context->output->video->Command(context, OUTPUT_SWITCH, "video");
} else
ret = cERR_OUTPUT_INTERNAL_ERROR;
break;
}
case OUTPUT_SLOWMOTION:{
if (context && context->playback) {
if (context->playback->isVideo)

View File

@@ -19,129 +19,44 @@
*
*/
/* ***************************** */
/* 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 <stdint.h>
#include <string.h>
#include <sys/uio.h>
#include <linux/dvb/video.h>
#include <linux/dvb/audio.h>
#include <linux/dvb/stm_ioctls.h>
#include <memory.h>
#include <asm/types.h>
#include <pthread.h>
#include <errno.h>
#include "common.h"
#include "output.h"
#include "debug.h"
#include "misc.h"
#include "pes.h"
#include "writer.h"
/* ***************************** */
/* Makros/Constants */
/* ***************************** */
#define AC3_HEADER_LENGTH 7
#define AC3_DEBUG
#ifdef AC3_DEBUG
static short debug_level = 0;
#define ac3_printf(level, fmt, x...) do { \
if (debug_level >= level) printf("[%s:%s] " fmt, __FILE__, __FUNCTION__, ## x); } while (0)
#else
#define ac3_printf(level, fmt, x...)
#endif
#ifndef AC3_SILENT
#define ac3_err(fmt, x...) do { printf("[%s:%s] " fmt, __FILE__, __FUNCTION__, ## x); } while (0)
#else
#define ac3_err(fmt, x...)
#endif
/* ***************************** */
/* Types */
/* ***************************** */
/* ***************************** */
/* Varaibles */
/* ***************************** */
/* ***************************** */
/* Prototypes */
/* ***************************** */
/* ***************************** */
/* MISC Functions */
/* ***************************** */
static int reset()
class WriterAC3 : public Writer
{
return 0;
public:
bool Write(int fd, AVFormatContext *avfc, AVStream *stream, AVPacket *packet, int64_t &pts);
WriterAC3();
};
bool WriterAC3::Write(int fd, AVFormatContext * /* avfc */, AVStream * /* stream */, AVPacket *packet, int64_t &pts)
{
if (fd < 0 || !packet)
return false;
unsigned char PesHeader[PES_MAX_HEADER_SIZE];
struct iovec iov[2];
iov[0].iov_base = PesHeader;
iov[0].iov_len = InsertPesHeader(PesHeader, packet->size, PRIVATE_STREAM_1_PES_START_CODE, pts, 0);
iov[1].iov_base = packet->data;
iov[1].iov_len = packet->size;
return writev(fd, iov, 2) > -1;
}
static int writeData(WriterAVCallData_t *call)
WriterAC3::WriterAC3()
{
ac3_printf(10, "\n");
unsigned char PesHeader[PES_MAX_HEADER_SIZE];
ac3_printf(10, "AudioPts %lld\n", call->Pts);
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->packet->size,
PRIVATE_STREAM_1_PES_START_CODE, call->Pts, 0);
iov[1].iov_base = call->packet->data;
iov[1].iov_len = call->packet->size;
return writev(call->fd, iov, 2);
Register(this, AV_CODEC_ID_AC3, AUDIO_ENCODING_AC3);
Register(this, AV_CODEC_ID_EAC3, AUDIO_ENCODING_AC3);
}
/* ***************************** */
/* Writer Definition */
/* ***************************** */
static WriterCaps_t caps_ac3 = {
"ac3",
eAudio,
"A_AC3",
AUDIO_ENCODING_AC3
};
struct Writer_s WriterAudioAC3 = {
&reset,
&writeData,
&caps_ac3
};
static WriterCaps_t caps_eac3 = {
"ac3",
eAudio,
"A_AC3",
AUDIO_ENCODING_AC3
};
struct Writer_s WriterAudioEAC3 = {
&reset,
&writeData,
&caps_eac3
};
static WriterAC3 writer_ac3 __attribute__ ((init_priority (300)));

View File

@@ -40,80 +40,39 @@
#include <pthread.h>
#include <errno.h>
#include "common.h"
#include "output.h"
#include "debug.h"
#include "misc.h"
#include "pes.h"
#include "writer.h"
/* ***************************** */
/* Makros/Constants */
/* ***************************** */
#define DIVX_DEBUG
#ifdef DIVX_DEBUG
static short debug_level = 0;
#define divx_printf(level, fmt, x...) do { \
if (debug_level >= level) printf("[%s:%s] " fmt, __FILE__, __FUNCTION__, ## x); } while (0)
#else
#define divx_printf(level, fmt, x...)
#endif
#ifndef DIVX_SILENT
#define divx_err(fmt, x...) do { printf("[%s:%s] " fmt, __FILE__, __FUNCTION__, ## x); } while (0)
#else
#define divx_err(fmt, x...)
#endif
/* ***************************** */
/* Types */
/* ***************************** */
/* ***************************** */
/* Varaibles */
/* ***************************** */
static int initialHeader = 1;
/* ***************************** */
/* Prototypes */
/* ***************************** */
/* ***************************** */
/* MISC Functions */
/* ***************************** */
static int reset()
class WriterDIVX : public Writer
{
initialHeader = 1;
return 0;
private:
bool initialHeader;
public:
bool Write(int fd, AVFormatContext *avfc, AVStream *stream, AVPacket *packet, int64_t &pts);
void Init();
WriterDIVX();
};
void WriterDIVX::Init()
{
initialHeader = true;
}
static int writeData(WriterAVCallData_t *call)
bool WriterDIVX::Write(int fd, AVFormatContext * /* avfc */, AVStream *stream, AVPacket *packet, int64_t &pts)
{
if (fd < 0 || !packet)
return false;
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 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->fd < 0) {
divx_err("file pointer < 0. ignoring ...\n");
return 0;
}
divx_printf(10, "AudioPts %lld\n", call->Pts);
usecPerFrame = 1000000 / av_q2d(call->stream->r_frame_rate);
divx_printf(10, "Microsecends per frame = %d\n", usecPerFrame);
usecPerFrame = 1000000 / av_q2d(stream->r_frame_rate);
memset(FakeHeaders, 0, sizeof(FakeHeaders));
@@ -136,67 +95,28 @@ static int writeData(WriterAVCallData_t *call)
struct iovec iov[4];
int ic = 0;
iov[ic].iov_base = PesHeader;
iov[ic++].iov_len =
InsertPesHeader(PesHeader, call->packet->size, MPEG_VIDEO_PES_START_CODE,
call->Pts, FakeStartCode);
iov[ic++].iov_len = InsertPesHeader(PesHeader, packet->size, MPEG_VIDEO_PES_START_CODE, pts, FakeStartCode);
iov[ic].iov_base = FakeHeaders;
iov[ic++].iov_len = FakeHeaderLength;
if (initialHeader) {
iov[ic].iov_base = call->stream->codec->extradata;
iov[ic++].iov_len = call->stream->codec->extradata_size;
iov[ic].iov_base = stream->codec->extradata;
iov[ic++].iov_len = stream->codec->extradata_size;
initialHeader = 0;
initialHeader = false;
}
iov[ic].iov_base = call->packet->data;
iov[ic++].iov_len = call->packet->size;
iov[ic].iov_base = packet->data;
iov[ic++].iov_len = packet->size;
int len = writev(call->fd, iov, ic);
divx_printf(10, "xvid_Write < len=%d\n", len);
return len;
return writev(fd, iov, ic) > -1;
}
/* ***************************** */
/* Writer Definition */
/* ***************************** */
WriterDIVX::WriterDIVX()
{
Register(this, AV_CODEC_ID_MPEG4, VIDEO_ENCODING_MPEG4P2);
Register(this, AV_CODEC_ID_MSMPEG4V1, VIDEO_ENCODING_MPEG4P2);
Register(this, AV_CODEC_ID_MSMPEG4V2, VIDEO_ENCODING_MPEG4P2);
Register(this, AV_CODEC_ID_MSMPEG4V3, VIDEO_ENCODING_MPEG4P2);
}
static WriterCaps_t mpeg4p2_caps = {
"mscomp",
eVideo,
"V_MSCOMP",
VIDEO_ENCODING_MPEG4P2
};
struct Writer_s WriterVideoMSCOMP = {
&reset,
&writeData,
&mpeg4p2_caps
};
static WriterCaps_t fourcc_caps = {
"fourcc",
eVideo,
"V_MS/VFW/FOURCC",
VIDEO_ENCODING_MPEG4P2
};
struct Writer_s WriterVideoFOURCC = {
&reset,
&writeData,
&fourcc_caps
};
static WriterCaps_t divx_caps = {
"divx",
eVideo,
"V_MKV/XVID",
VIDEO_ENCODING_MPEG4P2
};
struct Writer_s WriterVideoDIVX = {
&reset,
&writeData,
&divx_caps
};
static WriterDIVX writer_divx __attribute__ ((init_priority (300)));

View File

@@ -19,97 +19,41 @@
*
*/
/* ***************************** */
/* 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 <stdint.h>
#include <string.h>
#include <sys/uio.h>
#include <linux/dvb/video.h>
#include <linux/dvb/audio.h>
#include <linux/dvb/stm_ioctls.h>
#include <memory.h>
#include <asm/types.h>
#include <pthread.h>
#include <errno.h>
#include "common.h"
#include "output.h"
#include "debug.h"
#include "misc.h"
#include "pes.h"
#include "writer.h"
/* ***************************** */
/* Makros/Constants */
/* ***************************** */
#define PES_AUDIO_PRIVATE_HEADER_SIZE 16 // consider maximum private header size.
#define PES_AUDIO_HEADER_SIZE (32 + PES_AUDIO_PRIVATE_HEADER_SIZE)
#define PES_AUDIO_PACKET_SIZE 2028
#define SPDIF_AUDIO_PACKET_SIZE (1024 * sizeof(unsigned int) * 2) // stereo 32bit samples.
#define DTS_DEBUG
#ifdef DTS_DEBUG
static short debug_level = 0;
#define dts_printf(level, fmt, x...) do { \
if (debug_level >= level) printf("[%s:%s] " fmt, __FILE__, __FUNCTION__, ## x); } while (0)
#else
#define dts_printf(level, fmt, x...)
#endif
#ifndef DTS_SILENT
#define dts_err(fmt, x...) do { printf("[%s:%s] " fmt, __FILE__, __FUNCTION__, ## x); } while (0)
#else
#define dts_err(fmt, x...)
#endif
/* ***************************** */
/* Types */
/* ***************************** */
/* ***************************** */
/* Varaibles */
/* ***************************** */
/* ***************************** */
/* Prototypes */
/* ***************************** */
/* ***************************** */
/* MISC Functions */
/* ***************************** */
static int reset()
class WriterDTS : public Writer
{
return 0;
}
public:
bool Write(int fd, AVFormatContext *avfc, AVStream *stream, AVPacket *packet, int64_t &pts);
WriterDTS();
};
static int writeData(WriterAVCallData_t *call)
bool WriterDTS::Write(int fd, AVFormatContext * /* avfc */, AVStream * /* stream */, AVPacket *packet, int64_t &pts)
{
if (fd < 0 || !packet)
return false;
unsigned char PesHeader[PES_AUDIO_HEADER_SIZE];
dts_printf(10, "AudioPts %lld\n", call->Pts);
if (call->fd < 0) {
dts_err("file pointer < 0. ignoring ...\n");
return 0;
}
// #define DO_BYTESWAP
#ifdef DO_BYTESWAP
unsigned char *Data = (unsigned char *) malloc(call->packet->size);
memcpy(Data, call->packet->data, call->packet->size);
unsigned char Data[packet->size];
memcpy(Data, packet->data, packet->size);
/* 16-bit byte swap all data before injecting it */
for (i = 0; i < call->packet->size; i += 2) {
for (i = 0; i < packet->size; i += 2) {
unsigned char Tmp = Data[i];
Data[i] = Data[i + 1];
Data[i + 1] = Tmp;
@@ -119,41 +63,20 @@ static int writeData(WriterAVCallData_t *call)
struct iovec iov[2];
iov[0].iov_base = PesHeader;
iov[0].iov_len =
InsertPesHeader(PesHeader, call->packet->size,
MPEG_AUDIO_PES_START_CODE
/*PRIVATE_STREAM_1_PES_START_CODE */ , call->Pts,
0);
iov[0].iov_len = InsertPesHeader(PesHeader, packet->size, MPEG_AUDIO_PES_START_CODE /*PRIVATE_STREAM_1_PES_START_CODE */ , pts, 0);
#ifdef DO_BYTESPWAP
iov[1].iov_base = Data;
#else
iov[1].iov_base = call->packet->data;
iov[1].iov_base = packet->data;
#endif
iov[1].iov_len = call->packet->size;
iov[1].iov_len = packet->size;
int len = writev(call->fd, iov, 2);
#ifdef DO_BYTESWAP
free(Data);
#endif
dts_printf(10, "< len %d\n", len);
return len;
return writev(fd, iov, 2) > -1;
}
/* ***************************** */
/* Writer Definition */
/* ***************************** */
WriterDTS::WriterDTS()
{
Register(this, AV_CODEC_ID_DTS, AUDIO_ENCODING_DTS);
}
static WriterCaps_t caps = {
"dts",
eAudio,
"A_DTS",
AUDIO_ENCODING_DTS
};
struct Writer_s WriterAudioDTS = {
&reset,
&writeData,
&caps
};
static WriterDTS writer_dts __attribute__ ((init_priority (300)));

View File

@@ -19,117 +19,43 @@
*
*/
/* ***************************** */
/* 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 <stdint.h>
#include <string.h>
#include <sys/uio.h>
#include <linux/dvb/video.h>
#include <linux/dvb/audio.h>
#include <linux/dvb/stm_ioctls.h>
#include <memory.h>
#include <asm/types.h>
#include <pthread.h>
#include <errno.h>
#include "common.h"
#include "output.h"
#include "debug.h"
#include "misc.h"
#include "pes.h"
#include "misc.h"
#include "writer.h"
/* ***************************** */
/* Makros/Constants */
/* ***************************** */
#define FLAC_DEBUG
#ifdef FLAC_DEBUG
static short debug_level = 0;
#define flac_printf(level, fmt, x...) do { \
if (debug_level >= level) printf("[%s:%s] " fmt, __FILE__, __FUNCTION__, ## x); } while (0)
#else
#define flac_printf(level, fmt, x...)
#endif
#ifndef FLAC_SILENT
#define flac_err(fmt, x...) do { printf("[%s:%s] " fmt, __FILE__, __FUNCTION__, ## x); } while (0)
#else
#define flac_err(fmt, x...)
#endif
/* ***************************** */
/* Types */
/* ***************************** */
/* ***************************** */
/* Varaibles */
/* ***************************** */
/* ***************************** */
/* Prototypes */
/* ***************************** */
/* ***************************** */
/* MISC Functions */
/* ***************************** */
static int reset()
class WriterFLAC : public Writer
{
return 0;
}
public:
bool Write(int fd, AVFormatContext * /* avfc */, AVStream *stream, AVPacket *packet, int64_t &pts);
WriterFLAC();
};
static int writeData(WriterAVCallData_t *call)
bool WriterFLAC::Write(int fd, AVFormatContext * /* avfc */, AVStream * /* stream */, AVPacket *packet, int64_t &pts)
{
if (fd < 0 || !packet)
return -1;
unsigned char PesHeader[PES_MAX_HEADER_SIZE];
flac_printf(10, "AudioPts %lld\n", call->Pts);
if ((call->packet->data == NULL) || (call->packet->size <= 0)) {
flac_err("parsing NULL Data. ignoring...\n");
return 0;
}
if (call->fd < 0) {
flac_err("file pointer < 0. ignoring ...\n");
return 0;
}
struct iovec iov[2];
iov[0].iov_base = PesHeader;
iov[0].iov_len = InsertPesHeader(PesHeader, call->packet->size, MPEG_AUDIO_PES_START_CODE, call->Pts, 0);
iov[1].iov_base = call->packet->data;
iov[1].iov_len = call->packet->size;
iov[0].iov_len = InsertPesHeader(PesHeader, packet->size, MPEG_AUDIO_PES_START_CODE, pts, 0);
iov[1].iov_base = packet->data;
iov[1].iov_len = packet->size;
int len = writev(call->fd, iov, 2);
flac_printf(10, "flac_Write-< len=%d\n", len);
return len;
return writev(fd, iov, 2) > -1;
}
/* ***************************** */
/* Writer Definition */
/* ***************************** */
WriterFLAC::WriterFLAC()
{
Register(this, AV_CODEC_ID_FLAC, AUDIO_ENCODING_LPCM);
}
static WriterCaps_t caps_flac = {
"flac",
eAudio,
"A_FLAC",
AUDIO_ENCODING_LPCM //AUDIO_ENCODING_FLAC
};
struct Writer_s WriterAudioFLAC = {
&reset,
&writeData,
&caps_flac
};
static WriterFLAC writer_flac __attribute__ ((init_priority (300)));

View File

@@ -19,98 +19,33 @@
*
*/
/* ***************************** */
/* Includes */
/* ***************************** */
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <unistd.h>
#include <fcntl.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/ioctl.h>
#include <linux/dvb/video.h>
#include <linux/dvb/audio.h>
#include <linux/dvb/stm_ioctls.h>
#include <memory.h>
#include <asm/types.h>
#include <pthread.h>
#include <errno.h>
#include <sys/uio.h>
#include "common.h"
#include "output.h"
#include "debug.h"
#include "misc.h"
#include "pes.h"
#include "writer.h"
/* ***************************** */
/* Makros/Constants */
/* ***************************** */
#define H263_DEBUG
#ifdef H263_DEBUG
static short debug_level = 0;
static const char *FILENAME = "h263.c";
#define h263_printf(level, fmt, x...) do { \
if (debug_level >= level) printf("[%s:%s] " fmt, FILENAME, __FUNCTION__, ## x); } while (0)
#else
#define h263_printf(level, fmt, x...)
#endif
#ifndef H263_SILENT
#define h263_err(fmt, x...) do { printf("[%s:%s] " fmt, FILENAME, __FUNCTION__, ## x); } while (0)
#else
#define h263_err(fmt, x...)
#endif
/* ***************************** */
/* Types */
/* ***************************** */
/* ***************************** */
/* Varaibles */
/* ***************************** */
/* ***************************** */
/* Prototypes */
/* ***************************** */
/* ***************************** */
/* MISC Functions */
/* ***************************** */
static int reset()
class WriterH263 : public Writer
{
return 0;
}
public:
bool Write(int fd, AVFormatContext *avfc, AVStream *stream, AVPacket *packet, int64_t &pts);
WriterH263();
};
static int writeData(WriterAVCallData_t *call)
bool WriterH263::Write(int fd, AVFormatContext * /* avfc */, AVStream * /* stream */, AVPacket *packet, int64_t &pts)
{
if (fd < 0 || !packet)
return false;
unsigned char PesHeader[PES_MAX_HEADER_SIZE];
int len = 0;
h263_printf(10, "VideoPts %lld\n", call->Pts);
int HeaderLength = InsertPesHeader(PesHeader, packet->size, H263_VIDEO_PES_START_CODE, pts, 0);
if (call->fd < 0) {
h263_err("file pointer < 0. ignoring ...\n");
return 0;
}
int PrivateHeaderLength = InsertVideoPrivateDataHeader(&PesHeader[HeaderLength], packet->size);
int HeaderLength =
InsertPesHeader(PesHeader, call->packet->size, H263_VIDEO_PES_START_CODE,
call->Pts, 0);
int PrivateHeaderLength =
InsertVideoPrivateDataHeader(&PesHeader[HeaderLength], call->packet->size);
int PesLength =
PesHeader[PES_LENGTH_BYTE_0] +
(PesHeader[PES_LENGTH_BYTE_1] << 8) + PrivateHeaderLength;
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;
@@ -122,40 +57,17 @@ static int writeData(WriterAVCallData_t *call)
struct iovec iov[2];
iov[0].iov_base = PesHeader;
iov[0].iov_len = HeaderLength;
iov[1].iov_base = call->packet->data;
iov[1].iov_len = call->packet->size;
len = writev(call->fd, iov, 2);
h263_printf(10, "< len %d\n", len);
return len;
iov[1].iov_base = packet->data;
iov[1].iov_len = packet->size;
return writev(fd, iov, 2) > -1;
}
/* ***************************** */
/* Writer Definition */
/* ***************************** */
WriterH263::WriterH263()
{
Register(this, AV_CODEC_ID_H263, VIDEO_ENCODING_H263);
Register(this, AV_CODEC_ID_H263P, VIDEO_ENCODING_H263);
Register(this, AV_CODEC_ID_H263I, VIDEO_ENCODING_H263);
Register(this, AV_CODEC_ID_FLV1, VIDEO_ENCODING_FLV1);
}
static WriterCaps_t caps_h263 = {
"h263",
eVideo,
"V_H263",
VIDEO_ENCODING_H263
};
struct Writer_s WriterVideoH263 = {
&reset,
&writeData,
&caps_h263
};
static WriterCaps_t caps_flv = {
"FLV",
eVideo,
"V_FLV",
VIDEO_ENCODING_FLV1
};
struct Writer_s WriterVideoFLV = {
&reset,
&writeData,
&caps_flv
};
static WriterH263 writer_h263 __attribute__ ((init_priority (300)));

View File

@@ -19,62 +19,21 @@
*
*/
/* ***************************** */
/* 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 <stdint.h>
#include <string.h>
#include <sys/uio.h>
#include <linux/dvb/video.h>
#include <linux/dvb/audio.h>
#include <linux/dvb/stm_ioctls.h>
#include <memory.h>
#include <asm/types.h>
#include <pthread.h>
#include <errno.h>
#include <assert.h>
#include "common.h"
#include "output.h"
#include "debug.h"
#include "misc.h"
#include "pes.h"
#include "writer.h"
/* ***************************** */
/* Makros/Constants */
/* ***************************** */
#define H264_DEBUG
#ifdef H264_DEBUG
static short debug_level = 0;
#define h264_printf(level, fmt, x...) do { \
if (debug_level >= level) printf("[%s:%s] " fmt, __FILE__, __FUNCTION__, ## x); } while (0)
#else
#define h264_printf(level, fmt, x...)
#endif
#ifndef H264_SILENT
#define h264_err(fmt, x...) do { printf("[%s:%s] " fmt, __FILE__, __FUNCTION__, ## x); } while (0)
#else
#define h264_err(fmt, x...)
#endif
#define NALU_TYPE_PLAYER2_CONTAINER_PARAMETERS 24
#define CONTAINER_PARAMETERS_VERSION 0x00
/* ***************************** */
/* Types */
/* ***************************** */
typedef struct avcC_s {
unsigned char Version; /* configurationVersion */
unsigned char Profile; /* AVCProfileIndication */
@@ -85,31 +44,30 @@ typedef struct avcC_s {
unsigned char Params[1]; /* {length,params}{length,params}...sequence then picture */
} avcC_t;
/* ***************************** */
/* Varaibles */
/* ***************************** */
const unsigned char Head[] = { 0, 0, 0, 1 };
static int initialHeader = 1;
static unsigned int NalLengthBytes = 1;
/* ***************************** */
/* Prototypes */
/* ***************************** */
/* ***************************** */
/* MISC Functions */
/* ***************************** */
static int reset()
class WriterH264 : public Writer
{
initialHeader = 1;
return 0;
private:
bool initialHeader;
unsigned int NalLengthBytes;
public:
bool Write(int fd, AVFormatContext *avfc, AVStream *stream, AVPacket *packet, int64_t &pts);
void Init();
WriterH264();
};
void WriterH264::Init(void)
{
initialHeader = true;
initialHeader = 1;
NalLengthBytes = 1;
}
static int writeData(WriterAVCallData_t *call)
bool WriterH264::Write(int fd, AVFormatContext * /* avfc */, AVStream *stream, AVPacket *packet, int64_t &pts)
{
if (fd < 0 || !packet)
return false;
unsigned char PesHeader[PES_MAX_HEADER_SIZE];
unsigned long long int VideoPts;
unsigned int TimeDelta;
@@ -118,50 +76,37 @@ static int writeData(WriterAVCallData_t *call)
int ic = 0;
struct iovec iov[128];
TimeDelta = 1000.0 * av_q2d(call->stream->r_frame_rate); /* rational to double */
TimeDelta = 1000.0 * av_q2d(stream->r_frame_rate); /* rational to double */
TimeScale = (TimeDelta < 23970) ? 1001 : 1000; /* fixme: revise this */
VideoPts = pts;
VideoPts = call->Pts;
h264_printf(10, "VideoPts %lld - %d %d\n", call->Pts, TimeDelta, TimeScale);
if (call->fd < 0) {
h264_err("file pointer < 0. ignoring ...\n");
return 0;
}
if ((call->packet->size > 3)
&&
((call->packet->data[0] == 0x00 && call->packet->data[1] == 0x00
&& call->packet->data[2] == 0x00 && call->packet->data[3] == 0x01)
|| (call->packet->data[0] == 0xff && call->packet->data[1] == 0xff
&& call->packet->data[2] == 0xff && call->packet->data[3] == 0xff))) {
if ((packet->size > 3)
&& ((packet->data[0] == 0x00 && packet->data[1] == 0x00 && packet->data[2] == 0x00 && packet->data[3] == 0x01)
|| (packet->data[0] == 0xff && packet->data[1] == 0xff && packet->data[2] == 0xff && packet->data[3] == 0xff))) {
unsigned int PacketLength = 0;
unsigned int FakeStartCode = /* (call->Version << 8) | */ PES_VERSION_FAKE_START_CODE;
iov[ic++].iov_base = PesHeader;
if (initialHeader) {
initialHeader = 0;
iov[ic].iov_base = call->stream->codec->extradata;
iov[ic++].iov_len = call->stream->codec->extradata_size;
PacketLength += call->stream->codec->extradata_size;
initialHeader = false;
iov[ic].iov_base = stream->codec->extradata;
iov[ic++].iov_len = stream->codec->extradata_size;
PacketLength += stream->codec->extradata_size;
}
iov[ic].iov_base = call->packet->data;
iov[ic++].iov_len = call->packet->size;
PacketLength += call->packet->size;
iov[ic].iov_base = packet->data;
iov[ic++].iov_len = packet->size;
PacketLength += packet->size;
/*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 = (char *) "";
iov[ic].iov_base = (void *) "";
iov[ic++].iov_len = 1;
iov[0].iov_len =
InsertPesHeader(PesHeader, PacketLength,
MPEG_VIDEO_PES_START_CODE, call->Pts,
FakeStartCode);
return writev(call->fd, iov, ic);
InsertPesHeader(PesHeader, PacketLength, MPEG_VIDEO_PES_START_CODE, pts, FakeStartCode);
return writev(fd, iov, ic) > -1;
}
if (initialHeader) {
avcC_t *avcCHeader = (avcC_t *) call->stream->codec->extradata;
avcC_t *avcCHeader = (avcC_t *) stream->codec->extradata;
unsigned int i;
unsigned int ParamSets;
unsigned int ParamOffset;
@@ -169,13 +114,12 @@ static int writeData(WriterAVCallData_t *call)
unsigned int ParametersLength;
if (avcCHeader == NULL) {
h264_err("private_data NULL\n");
return -1;
fprintf(stderr, "stream->codec->extradata == NULL\n");
return false;
}
if (avcCHeader->Version != 1)
h264_err("Error unknown avcC version (%x). Expect problems.\n",
avcCHeader->Version);
fprintf(stderr, "Error unknown avcC version (%x). Expect problems.\n", avcCHeader->Version);
ParametersLength = 0;
@@ -211,33 +155,16 @@ static int writeData(WriterAVCallData_t *call)
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_len = InsertPesHeader(PesHeader, ParametersLength, MPEG_VIDEO_PES_START_CODE, INVALID_PTS_VALUE, 0);
iov[ic].iov_base = HeaderData;
iov[ic++].iov_len = ParametersLength;
len = writev(call->fd, iov, ic);
len = writev(fd, iov, ic);
if (len < 0)
return len;
return false;
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;
@@ -246,9 +173,6 @@ static int writeData(WriterAVCallData_t *call)
(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);
@@ -260,18 +184,12 @@ static int writeData(WriterAVCallData_t *call)
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);
@@ -281,19 +199,16 @@ static int writeData(WriterAVCallData_t *call)
ParamOffset += PsLength + 2;
}
iov[0].iov_len =
InsertPesHeader(PesHeader, InitialHeaderLength,
MPEG_VIDEO_PES_START_CODE, INVALID_PTS_VALUE,
0);
ssize_t l = writev(call->fd, iov, ic);
iov[0].iov_len = InsertPesHeader(PesHeader, InitialHeaderLength, MPEG_VIDEO_PES_START_CODE, INVALID_PTS_VALUE, 0);
ssize_t l = writev(fd, iov, ic);
if (l < 0)
return l;
return false;
len += l;
initialHeader = 0;
}
unsigned int SampleSize = call->packet->size;
unsigned int SampleSize = packet->size;
unsigned int NalStart = 0;
unsigned int VideoPosition = 0;
@@ -302,7 +217,7 @@ static int writeData(WriterAVCallData_t *call)
unsigned char NalData[4];
int NalPresent = 1;
memcpy(NalData, call->packet->data + VideoPosition, NalLengthBytes);
memcpy(NalData, packet->data + VideoPosition, NalLengthBytes);
VideoPosition += NalLengthBytes;
NalStart += NalLengthBytes;
switch (NalLengthBytes) {
@@ -313,25 +228,15 @@ static int writeData(WriterAVCallData_t *call)
NalLength = (NalData[0] << 8) | (NalData[1]);
break;
case 3:
NalLength =
(NalData[0] << 16) | (NalData[1] << 8) | (NalData[2]);
NalLength = (NalData[0] << 16) | (NalData[1] << 8) | (NalData[2]);
break;
default:
NalLength =
(NalData[0] << 24) | (NalData[1] << 16) | (NalData[2] << 8)
| (NalData[3]);
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);
fprintf(stderr, "nal length past end of buffer - size %u frame offset %u left %u\n", NalLength, NalStart, SampleSize - NalStart);
NalStart = SampleSize;
} else {
NalStart += NalLength;
@@ -344,46 +249,28 @@ static int writeData(WriterAVCallData_t *call)
iov[ic++].iov_len = sizeof(Head);
}
iov[ic].iov_base = call->packet->data + VideoPosition;
iov[ic].iov_base = packet->data + VideoPosition;
iov[ic++].iov_len = NalLength;
VideoPosition += NalLength;
h264_printf(20, " pts=%llu\n", VideoPts);
iov[0].iov_len =
InsertPesHeader(PesHeader, NalLength,
MPEG_VIDEO_PES_START_CODE, VideoPts, 0);
ssize_t l = writev(call->fd, iov, ic);
ssize_t l = writev(fd, iov, ic);
if (l < 0)
return l;
return false;
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;
return len > -1;
}
/* ***************************** */
/* Writer Definition */
/* ***************************** */
WriterH264::WriterH264()
{
Register(this, AV_CODEC_ID_H264, VIDEO_ENCODING_H264);
}
static WriterCaps_t caps = {
"h264",
eVideo,
"V_MPEG4/ISO/AVC",
VIDEO_ENCODING_H264
};
struct Writer_s WriterVideoH264 = {
&reset,
&writeData,
&caps
};
static WriterH264 writerh264 __attribute__ ((init_priority (300)));

View File

@@ -19,145 +19,45 @@
*
*/
/* ***************************** */
/* 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 <stdint.h>
#include <string.h>
#include <sys/uio.h>
#include <linux/dvb/video.h>
#include <linux/dvb/audio.h>
#include <linux/dvb/stm_ioctls.h>
#include <memory.h>
#include <asm/types.h>
#include <pthread.h>
#include <errno.h>
#include "common.h"
#include "output.h"
#include "debug.h"
#include "misc.h"
#include "pes.h"
#include "writer.h"
/* ***************************** */
/* Makros/Constants */
/* ***************************** */
#define MP3_DEBUG
#ifdef MP3_DEBUG
static short debug_level = 0;
#define mp3_printf(level, fmt, x...) do { \
if (debug_level >= level) printf("[%s:%s] " fmt, __FILE__, __FUNCTION__, ## x); } while (0)
#else
#define mp3_printf(level, fmt, x...)
#endif
#ifndef MP3_SILENT
#define mp3_err(fmt, x...) do { printf("[%s:%s] " fmt, __FILE__, __FUNCTION__, ## x); } while (0)
#else
#define mp3_err(fmt, x...)
#endif
/* ***************************** */
/* Types */
/* ***************************** */
/* ***************************** */
/* Varaibles */
/* ***************************** */
/* ***************************** */
/* Prototypes */
/* ***************************** */
/* ***************************** */
/* MISC Functions */
/* ***************************** */
static int reset()
class WriterMP3 : public Writer
{
return 0;
}
public:
bool Write(int fd, AVFormatContext *avfc, AVStream *stream, AVPacket *packet, int64_t &pts);
WriterMP3();
};
static int writeData(WriterAVCallData_t *call)
bool WriterMP3::Write(int fd, AVFormatContext * /* avfc */, AVStream * /* stream */, AVPacket *packet, int64_t &pts)
{
if (fd < 0 || !packet)
return false;
unsigned char PesHeader[PES_MAX_HEADER_SIZE];
mp3_printf(10, "AudioPts %lld\n", call->Pts);
if ((call->packet->data == NULL) || (call->packet->size <= 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->packet->size, MPEG_AUDIO_PES_START_CODE,
call->Pts, 0);
iov[1].iov_base = call->packet->data;
iov[1].iov_len = call->packet->size;
iov[0].iov_len = InsertPesHeader(PesHeader, packet->size, MPEG_AUDIO_PES_START_CODE, pts, 0);
iov[1].iov_base = packet->data;
iov[1].iov_len = packet->size;
int len = writev(call->fd, iov, 2);
mp3_printf(10, "mp3_Write-< len=%d\n", len);
return len;
return writev(fd, iov, 2) > -1;
}
/* ***************************** */
/* Writer Definition */
/* ***************************** */
WriterMP3::WriterMP3()
{
Register(this, AV_CODEC_ID_MP3, AUDIO_ENCODING_MP3);
Register(this, AV_CODEC_ID_MP2, AUDIO_ENCODING_MPEG2);
// Register(this, AV_CODEC_ID_VORBIS, AUDIO_ENCODING_VORBIS);
}
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
};
static WriterMP3 writer_mp3 __attribute__ ((init_priority (300)));

View File

@@ -19,146 +19,58 @@
*
*/
/* ***************************** */
/* 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 <stdint.h>
#include <string.h>
#include <sys/uio.h>
#include <linux/dvb/video.h>
#include <linux/dvb/audio.h>
#include <linux/dvb/stm_ioctls.h>
#include <memory.h>
#include <asm/types.h>
#include <pthread.h>
#include <errno.h>
#include "common.h"
#include "output.h"
#include <algorithm>
#include "debug.h"
#include "misc.h"
#include "pes.h"
#include "writer.h"
/* ***************************** */
/* Makros/Constants */
/* ***************************** */
#define MPEG2_DEBUG
#ifdef MPEG2_DEBUG
static short debug_level = 0;
#define mpeg2_printf(level, fmt, x...) do { \
if (debug_level >= level) printf("[%s:%s] " fmt, __FILE__, __FUNCTION__, ## x); } while (0)
#else
#define mpeg2_printf(level, fmt, x...)
#endif
#ifndef MPEG2_SILENT
#define mpeg2_err(fmt, x...) do { printf("[%s:%s] " fmt, __FILE__, __FUNCTION__, ## x); } while (0)
#else
#define mpeg2_err(fmt, x...)
#endif
/* ***************************** */
/* Types */
/* ***************************** */
/* ***************************** */
/* Varaibles */
/* ***************************** */
/* ***************************** */
/* Prototypes */
/* ***************************** */
/* ***************************** */
/* MISC Functions */
/* ***************************** */
static int reset()
class WriterMPEG2 : public Writer
{
return 0;
}
public:
bool Write(int fd, AVFormatContext *avfc, AVStream *stream, AVPacket *packet, int64_t &pts);
WriterMPEG2();
};
static int writeData(WriterAVCallData_t *call)
bool WriterMPEG2::Write(int fd, AVFormatContext * /* avfc */, AVStream * /* stream */, AVPacket *packet, int64_t &pts)
{
unsigned char PesHeader[PES_MAX_HEADER_SIZE];
int len = 0;
int Position = 0;
if (fd < 0 || !packet)
return false;
mpeg2_printf(10, "VideoPts %lld\n", call->Pts);
unsigned char PesHeader[PES_MAX_HEADER_SIZE];
if (call->fd < 0) {
mpeg2_err("file pointer < 0. ignoring ...\n");
return 0;
}
int64_t _pts = pts;
while (Position < call->packet->size) {
int PacketLength = (call->packet->size - Position) <= MAX_PES_PACKET_SIZE ?
(call->packet->size - Position) : MAX_PES_PACKET_SIZE;
for (int Position = 0; Position < packet->size; ) {
int PacketLength = std::min(packet->size - Position, MAX_PES_PACKET_SIZE);
struct iovec iov[2];
iov[0].iov_base = PesHeader;
iov[0].iov_len = InsertPesHeader(PesHeader, PacketLength, 0xe0, _pts, 0);
iov[1].iov_base = packet->data + Position;
iov[1].iov_len = PacketLength;
int Remaining = call->packet->size - 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->packet->data + Position;
iov[1].iov_len = PacketLength;
ssize_t l = writev(call->fd, iov, 2);
if (l < 0) {
len = l;
break;
ssize_t l = writev(fd, iov, 2);
if (l < 0) {
return false;
break;
}
Position += PacketLength;
_pts = INVALID_PTS_VALUE;
}
len += l;
Position += PacketLength;
call->Pts = INVALID_PTS_VALUE;
}
mpeg2_printf(10, "< len %d\n", len);
return len;
return true;
}
/* ***************************** */
/* Writer Definition */
/* ***************************** */
static WriterCaps_t caps = {
"mpeg2",
eVideo,
"V_MPEG2",
VIDEO_ENCODING_AUTO
};
WriterMPEG2::WriterMPEG2()
{
Register(this, AV_CODEC_ID_MPEG2TS, VIDEO_ENCODING_AUTO);
}
struct Writer_s WriterVideoMPEG2 = {
&reset,
&writeData,
&caps
};
static WriterCaps_t h264_caps = {
"mpges_h264",
eVideo,
"V_MPEG2/H264",
VIDEO_ENCODING_H264
};
struct Writer_s WriterVideoMPEGH264 = {
&reset,
&writeData,
&h264_caps
};
static WriterMPEG2 writer_mpeg2 __attribute__ ((init_priority (300)));

View File

@@ -19,107 +19,70 @@
*
*/
/* ***************************** */
/* 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 <stdint.h>
#include <string.h>
#include <sys/uio.h>
#include <linux/dvb/video.h>
#include <linux/dvb/audio.h>
#include <linux/dvb/stm_ioctls.h>
#include <memory.h>
#include <asm/types.h>
#include <pthread.h>
#include <errno.h>
#include "common.h"
#include "output.h"
#include "debug.h"
#include "misc.h"
#include "pes.h"
#include "writer.h"
/* ***************************** */
/* Makros/Constants */
/* ***************************** */
#define PCM_DEBUG
#ifdef PCM_DEBUG
static short debug_level = 0;
#define pcm_printf(level, fmt, x...) do { \
if (debug_level >= level) printf("[%s:%s] " fmt, __FILE__, __FUNCTION__, ## x); } while (0)
#else
#define pcm_printf(level, fmt, x...)
#endif
#ifndef PCM_SILENT
#define pcm_err(fmt, x...) do { printf("[%s:%s] " fmt, __FILE__, __FUNCTION__, ## x); } while (0)
#else
#define pcm_err(fmt, x...)
#endif
/* ***************************** */
/* Types */
/* ***************************** */
/* ***************************** */
/* Varaibles */
/* ***************************** */
static int initialHeader = 1;
static unsigned int SubFrameLen = 0;
static unsigned int SubFramesPerPES = 0;
extern "C" {
#include <libavutil/avutil.h>
#include <libavutil/time.h>
#include <libavformat/avformat.h>
#include <libswresample/swresample.h>
#include <libavutil/opt.h>
}
// reference: search for TypeLpcmDVDAudio in player/frame_parser/frame_parser_audio_lpcm.cpp
static const unsigned char clpcm_prv[14] = { 0xA0, //sub_stream_id
0, 0, //resvd and UPC_EAN_ISRC stuff, unused
0x0A, //private header length
0, 9, //first_access_unit_pointer
0x00, //emph,rsvd,stereo,downmix
0x0F, //quantisation word length 1,2
0x0F, //audio sampling freqency 1,2
0, //resvd, multi channel type
0, //bit shift on channel GR2, assignment
0x80, //dynamic range control
0, 0 //resvd for copyright management
static const unsigned char clpcm_prv[14] = {
0xA0, //sub_stream_id
0, 0, //resvd and UPC_EAN_ISRC stuff, unused
0x0A, //private header length
0, 9, //first_access_unit_pointer
0x00, //emph,rsvd,stereo,downmix
0x0F, //quantisation word length 1,2
0x0F, //audio sampling freqency 1,2
0, //resvd, multi channel type
0, //bit shift on channel GR2, assignment
0x80, //dynamic range control
0, 0 //resvd for copyright management
};
static unsigned char lpcm_prv[14];
static unsigned char breakBuffer[8192];
static unsigned int breakBufferFillSize = 0;
/* ***************************** */
/* Prototypes */
/* ***************************** */
/* ***************************** */
/* MISC Functions */
/* ***************************** */
static int uNoOfChannels;
static int uSampleRate;
static int uBitsPerSample;
static int prepareClipPlay()
class WriterPCM : public Writer
{
printf("rate: %d ch: %d bits: %d (%d bps)\n",
uSampleRate /*Format->dwSamplesPerSec */ ,
uNoOfChannels /*Format->wChannels */ ,
uBitsPerSample /*Format->wBitsPerSample */ ,
(uBitsPerSample /*Format->wBitsPerSample */ / 8)
);
private:
unsigned int SubFrameLen;
unsigned int SubFramesPerPES;
unsigned char lpcm_prv[14];
unsigned char breakBuffer[8192];
unsigned int breakBufferFillSize;
int uNoOfChannels;
int uSampleRate;
int uBitsPerSample;
SwrContext *swr;
AVFrame *decoded_frame;
int out_sample_rate;
int out_channels;
uint64_t out_channel_layout;
bool initialHeader;
bool restart_audio_resampling;
public:
bool Write(int fd, AVFormatContext *avfc, AVStream *stream, AVPacket *packet, int64_t &pts);
bool prepareClipPlay();
int writePCM(int fd, int64_t Pts, uint8_t *data, unsigned int size);
void Init();
WriterPCM();
};
bool WriterPCM::prepareClipPlay()
{
SubFrameLen = 0;
SubFramesPerPES = 0;
breakBufferFillSize = 0;
@@ -159,7 +122,7 @@ static int prepareClipPlay()
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.
// FIXME: PES header size was hardcoded to 18 in earlier code. Actual size returned by InsertPesHeader is 14.
SubFramesPerPES = ((2048 - 18) - sizeof(lpcm_prv)) / SubFrameLen;
SubFrameLen *= SubFramesPerPES;
@@ -173,26 +136,18 @@ static int prepareClipPlay()
break;
default:
printf("inappropriate bits per sample (%d) - must be 16 or 24\n", uBitsPerSample);
return 1;
return false;
}
return 0;
return true;
}
static int writePCM(int fd, int64_t Pts, uint8_t *data, unsigned int size)
int WriterPCM::writePCM(int fd, int64_t Pts, uint8_t *data, unsigned int size)
{
unsigned char PesHeader[PES_MAX_HEADER_SIZE];
pcm_printf(10, "AudioPts %lld\n", Pts);
if (fd < 0) {
pcm_err("file pointer < 0. ignoring ...\n");
return 0;
}
if (initialHeader) {
initialHeader = 0;
initialHeader = false;
prepareClipPlay();
}
@@ -268,36 +223,32 @@ static int writePCM(int fd, int64_t Pts, uint8_t *data, unsigned int size)
return size;
}
SwrContext *swr = NULL;
AVFrame *decoded_frame = NULL;
int out_sample_rate = 44100;
int out_channels = 2;
uint64_t out_channel_layout = AV_CH_LAYOUT_STEREO;
int restart_audio_resampling = 1;
static int reset()
void WriterPCM::Init()
{
initialHeader = 1;
restart_audio_resampling = 1;
return 0;
initialHeader = true;
restart_audio_resampling = true;
}
int64_t calcPts(AVFormatContext *, AVStream *, int64_t);
extern int64_t calcPts(AVFormatContext *, AVStream *, int64_t);
static int writeData(WriterAVCallData_t *call)
bool WriterPCM::Write(int fd, AVFormatContext *avfc, AVStream *stream, AVPacket *packet, int64_t &pts)
{
AVCodecContext *c = call->stream->codec;
AVPacket *packet = call->packet;
uint8_t *packet_data = packet->data;
if (fd < 0)
return false;
if (!packet) {
fprintf(stderr, "%s %s %d\n", __FILE__, __func__, __LINE__);
restart_audio_resampling = true;
return true;
}
AVCodecContext *c = stream->codec;
unsigned int packet_size = packet->size;
if (call->restart_audio_resampling)
restart_audio_resampling = 1;
if (restart_audio_resampling) {
restart_audio_resampling = 0;
initialHeader = 1;
fprintf(stderr, "%s %s %d\n", __FILE__, __func__, __LINE__);
restart_audio_resampling = false;
initialHeader = true;
if (swr) {
swr_free(&swr);
@@ -316,21 +267,20 @@ static int writeData(WriterAVCallData_t *call)
while (packet_size > 0) {
int got_frame = 0;
if (!decoded_frame) {
if (!(decoded_frame = av_frame_alloc())) {
if (decoded_frame)
av_frame_unref(decoded_frame);
else if (!(decoded_frame = av_frame_alloc())) {
fprintf(stderr, "out of memory\n");
exit(1);
}
} else
av_frame_unref(decoded_frame);
}
int len = avcodec_decode_audio4(c, decoded_frame, &got_frame, packet);
if (len < 0) {
restart_audio_resampling = 1;
fprintf(stderr, "%s %s %d\n", __FILE__, __func__, __LINE__);
restart_audio_resampling = true;
break;
}
packet_data += len;
packet_size -= len;
if (!got_frame)
@@ -387,38 +337,35 @@ static int writeData(WriterAVCallData_t *call)
// FIXME. PTS calculation is probably broken.
int64_t pts;
int64_t next_in_pts = av_rescale(av_frame_get_best_effort_timestamp(decoded_frame),
call->stream->time_base.num * (int64_t) out_sample_rate * c->sample_rate,
call->stream->time_base.den);
stream->time_base.num * (int64_t) out_sample_rate * c->sample_rate,
stream->time_base.den);
int64_t next_out_pts = av_rescale(swr_next_pts(swr, next_in_pts),
call->stream->time_base.den,
call->stream->time_base.num * (int64_t) out_sample_rate * c->sample_rate);
*(call->context->currentAudioPtsP) = pts = calcPts(call->avfc, call->stream, next_out_pts);
stream->time_base.den,
stream->time_base.num * (int64_t) out_sample_rate * c->sample_rate);
pts = calcPts(avfc, stream, next_out_pts);
out_samples = swr_convert(swr, &output, out_samples, (const uint8_t **) &decoded_frame->data[0], in_samples);
uSampleRate = out_sample_rate;
uNoOfChannels = av_get_channel_layout_nb_channels(out_channel_layout);
uBitsPerSample = 16;
writePCM(call->fd, pts, output, out_samples * sizeof(short) * out_channels);
writePCM(fd, pts, output, out_samples * sizeof(short) * out_channels);
av_freep(&output);
}
return packet->size;
return true;
}
/* ***************************** */
/* Writer Definition */
/* ***************************** */
WriterPCM::WriterPCM()
{
swr = NULL;
decoded_frame = NULL;
out_sample_rate = 44100;
out_channels = 2;
out_channel_layout = AV_CH_LAYOUT_STEREO;
restart_audio_resampling = true;
static WriterCaps_t caps_ipcm = {
"ipcm",
eAudio,
"A_IPCM",
AUDIO_ENCODING_LPCMA
};
Register(this, AV_CODEC_ID_PCM_S16LE/*FIXME*/, AUDIO_ENCODING_LPCMA);
}
struct Writer_s WriterAudioIPCM = {
&reset,
&writeData,
&caps_ipcm
};
static WriterPCM writer_pcm __attribute__ ((init_priority (300)));

View File

@@ -19,267 +19,169 @@
*
*/
/* ***************************** */
/* 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 <stdint.h>
#include <string.h>
#include <sys/uio.h>
#include <linux/dvb/video.h>
#include <linux/dvb/audio.h>
#include <linux/dvb/stm_ioctls.h>
#include <memory.h>
#include <asm/types.h>
#include <pthread.h>
#include <errno.h>
#include "common.h"
#include "output.h"
#include "debug.h"
#include <algorithm>
#include "misc.h"
#include "pes.h"
#include "writer.h"
/* ***************************** */
/* Makros/Constants */
/* ***************************** */
#define WMV3_PRIVATE_DATA_LENGTH 4
#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 METADATA_STRUCT_A_START 12
#define METADATA_STRUCT_B_START 24
#define METADATA_STRUCT_B_FRAMERATE_START 32
#define METADATA_STRUCT_C_START 8
#define VC1_SEQUENCE_LAYER_METADATA_START_CODE 0x80
#define VC1_FRAME_START_CODE 0x0d
#define VC1_SEQUENCE_LAYER_METADATA_START_CODE 0x80
#define VC1_FRAME_START_CODE 0x0d
#define VC1_DEBUG
#ifdef VC1_DEBUG
static short debug_level = 0;
#define vc1_printf(level, fmt, x...) do { \
if (debug_level >= level) printf("[%s:%s] " fmt, __FILE__, __FUNCTION__, ## x); } while (0)
#else
#define vc1_printf(level, fmt, x...)
#endif
#ifndef VC1_SILENT
#define vc1_err(fmt, x...) do { printf("[%s:%s] " fmt, __FILE__, __FUNCTION__, ## x); } while (0)
#else
#define vc1_err(fmt, x...)
#endif
/* ***************************** */
/* Types */
/* ***************************** */
static const unsigned char SequenceLayerStartCode[] =
{ 0x00, 0x00, 0x01, VC1_SEQUENCE_LAYER_METADATA_START_CODE };
static const unsigned char Metadata[] = {
0x00, 0x00, 0x00, 0xc5,
0x04, 0x00, 0x00, 0x00,
0xc0, 0x00, 0x00, 0x00, /* Struct C set for for advanced profile */
0x00, 0x00, 0x00, 0x00, /* Struct A */
0x00, 0x00, 0x00, 0x00,
0x0c, 0x00, 0x00, 0x00,
0x60, 0x00, 0x00, 0x00, /* Struct B */
0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00
class WriterVC1 : public Writer
{
private:
bool initialHeader;
unsigned char FrameHeaderSeen;
double frameRate;
public:
bool Write(int fd, AVFormatContext *avfc, AVStream *stream, AVPacket *packet, int64_t &pts);
void Init();
WriterVC1();
};
/* ***************************** */
/* Varaibles */
/* ***************************** */
static int initialHeader = 1;
static unsigned char FrameHeaderSeen = 0;
/* ***************************** */
/* Prototypes */
/* ***************************** */
/* ***************************** */
/* MISC Functions */
/* ***************************** */
static int reset()
void WriterVC1::Init()
{
initialHeader = 1;
FrameHeaderSeen = 0;
return 0;
initialHeader = true;
}
static int writeData(WriterAVCallData_t *call)
bool WriterVC1::Write(int fd, AVFormatContext *avfc, AVStream *stream, AVPacket *packet, int64_t &pts)
{
int len = 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->stream->codec->extradata_size);
if (fd < 0 || !packet)
return false;
if (initialHeader) {
initialHeader = false;
FrameHeaderSeen = false;
unsigned char PesHeader[PES_MAX_HEADER_SIZE];
unsigned char PesPayload[128];
unsigned char *PesPtr;
unsigned int crazyFramerate = 0;
struct iovec iov[2];
const unsigned char SequenceLayerStartCode[] =
{ 0x00, 0x00, 0x01, VC1_SEQUENCE_LAYER_METADATA_START_CODE };
vc1_printf(10, "Framerate: %f\n", 1000.0 * av_q2d(call->stream->r_frame_rate));
vc1_printf(10, "biWidth: %d\n", call->stream->codec->width);
vc1_printf(10, "biHeight: %d\n", call->stream->codec->height);
crazyFramerate = ((10000000.0 / av_q2d(call->stream->r_frame_rate)));
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
};
vc1_printf(10, "crazyFramerate: %u\n", crazyFramerate);
unsigned char PesHeader[PES_MAX_HEADER_SIZE];
unsigned char PesPayload[128];
unsigned char *PesPtr;
unsigned int usecPerFrame = ((10000000.0 / av_q2d(stream->r_frame_rate)));
struct iovec iov[2];
memset(PesPayload, 0, sizeof(PesPayload));
PesPtr = PesPayload;
memset(PesPayload, 0, sizeof(PesPayload));
memcpy(PesPtr, SequenceLayerStartCode,
sizeof(SequenceLayerStartCode));
PesPtr += sizeof(SequenceLayerStartCode);
PesPtr = PesPayload;
memcpy(PesPtr, Metadata, sizeof(Metadata));
PesPtr += METADATA_STRUCT_C_START;
PesPtr += WMV3_PRIVATE_DATA_LENGTH;
memcpy(PesPtr, SequenceLayerStartCode, sizeof(SequenceLayerStartCode));
PesPtr += sizeof(SequenceLayerStartCode);
/* Metadata Header Struct A */
*PesPtr++ = (call->stream->codec->height >> 0) & 0xff;
*PesPtr++ = (call->stream->codec->height >> 8) & 0xff;
*PesPtr++ = (call->stream->codec->height >> 16) & 0xff;
*PesPtr++ = call->stream->codec->height >> 24;
*PesPtr++ = (call->stream->codec->width >> 0) & 0xff;
*PesPtr++ = (call->stream->codec->width >> 8) & 0xff;
*PesPtr++ = (call->stream->codec->width >> 16) & 0xff;
*PesPtr++ = call->stream->codec->width >> 24;
memcpy(PesPtr, Metadata, sizeof(Metadata));
PesPtr += METADATA_STRUCT_C_START;
PesPtr += WMV3_PRIVATE_DATA_LENGTH;
PesPtr += 12; /* Skip flag word and Struct B first 8 bytes */
/* Metadata Header Struct A */
*PesPtr++ = (stream->codec->height >> 0) & 0xff;
*PesPtr++ = (stream->codec->height >> 8) & 0xff;
*PesPtr++ = (stream->codec->height >> 16) & 0xff;
*PesPtr++ = stream->codec->height >> 24;
*PesPtr++ = (stream->codec->width >> 0) & 0xff;
*PesPtr++ = (stream->codec->width >> 8) & 0xff;
*PesPtr++ = (stream->codec->width >> 16) & 0xff;
*PesPtr++ = stream->codec->width >> 24;
*PesPtr++ = (crazyFramerate >> 0) & 0xff;
*PesPtr++ = (crazyFramerate >> 8) & 0xff;
*PesPtr++ = (crazyFramerate >> 16) & 0xff;
*PesPtr++ = crazyFramerate >> 24;
PesPtr += 12; /* Skip flag word and Struct B first 8 bytes */
iov[0].iov_base = PesHeader;
iov[1].iov_base = PesPayload;
iov[1].iov_len = PesPtr - PesPayload;
iov[0].iov_len =
InsertPesHeader(PesHeader, iov[1].iov_len,
VC1_VIDEO_PES_START_CODE, INVALID_PTS_VALUE,
0);
len = writev(call->fd, iov, 2);
*PesPtr++ = (usecPerFrame >> 0) & 0xff;
*PesPtr++ = (usecPerFrame >> 8) & 0xff;
*PesPtr++ = (usecPerFrame >> 16) & 0xff;
*PesPtr++ = usecPerFrame >> 24;
/* 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->stream->codec->extradata;
iov[1].iov_len = call->stream->codec->extradata_size;
iov[0].iov_len =
InsertPesHeader(PesHeader, iov[1].iov_len,
VC1_VIDEO_PES_START_CODE, INVALID_PTS_VALUE,
0);
len = writev(call->fd, iov, 2);
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);
if (writev(fd, iov, 2) < 0)
return false;
initialHeader = 0;
}
/* 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 = stream->codec->extradata;
iov[1].iov_len = stream->codec->extradata_size;
iov[0].iov_len = InsertPesHeader(PesHeader, iov[1].iov_len, VC1_VIDEO_PES_START_CODE, INVALID_PTS_VALUE, 0);
if (writev(fd, iov, 2) < 0)
return false;
if (call->packet->size > 0 && call->packet->data) {
int Position = 0;
unsigned char insertSampleHeader = 1;
while (Position < call->packet->size) {
int PacketLength =
(call->packet->size - Position) <=
MAX_PES_PACKET_SIZE ? (call->packet->size -
Position) : MAX_PES_PACKET_SIZE;
int Remaining = call->packet->size - Position - PacketLength;
vc1_printf(20, "PacketLength=%d, Remaining=%d, Position=%d\n",
PacketLength, Remaining, Position);
unsigned char PesHeader[PES_MAX_HEADER_SIZE];
int HeaderLength =
InsertPesHeader(PesHeader, PacketLength,
VC1_VIDEO_PES_START_CODE, call->Pts, 0);
if (insertSampleHeader) {
const unsigned char Vc1FrameStartCode[] =
{ 0, 0, 1, VC1_FRAME_START_CODE };
/*
vc1_printf(10, "Data Start: {00 00 01 0d} - ");
int i;
for (i = 0; i < 4; i++) vc1_printf(10, "%02x ", call->packet->data[i]);
vc1_printf(10, "\n");
*/
if (!FrameHeaderSeen && (call->packet->size > 3)
&& (memcmp(call->packet->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->packet->data + Position;
iov[1].iov_len = PacketLength;
ssize_t l = writev(call->fd, iov, 2);
if (l < 0) {
len = l;
break;
}
len += l;
Position += PacketLength;
call->Pts = INVALID_PTS_VALUE;
initialHeader = false;
}
}
vc1_printf(10, "< %d\n", len);
return len;
int64_t _pts = pts;
if (packet->size > 0) {
int Position = 0;
unsigned char insertSampleHeader = 1;
while (Position < packet->size) {
int PacketLength = std::min(packet->size - Position, MAX_PES_PACKET_SIZE);
unsigned char PesHeader[PES_MAX_HEADER_SIZE];
int HeaderLength = InsertPesHeader(PesHeader, PacketLength, VC1_VIDEO_PES_START_CODE, _pts, 0);
if (insertSampleHeader) {
const unsigned char Vc1FrameStartCode[] = { 0, 0, 1, VC1_FRAME_START_CODE };
if (!FrameHeaderSeen && (packet->size > 3) && (memcmp(packet->data, Vc1FrameStartCode, 4) == 0))
FrameHeaderSeen = true;
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 = packet->data + Position;
iov[1].iov_len = PacketLength;
ssize_t l = writev(fd, iov, 2);
if (l < 0)
return false;
Position += PacketLength;
_pts = INVALID_PTS_VALUE;
}
}
return true;
}
/* ***************************** */
/* Writer Definition */
/* ***************************** */
WriterVC1::WriterVC1()
{
Register(this, AV_CODEC_ID_VC1, VIDEO_ENCODING_VC1);
}
static WriterCaps_t caps = {
"vc1",
eVideo,
"V_VC1",
VIDEO_ENCODING_VC1
};
struct Writer_s WriterVideoVC1 = {
&reset,
&writeData,
&caps
};
static WriterVC1 writer_vc1 __attribute__ ((init_priority (300)));

View File

@@ -19,241 +19,151 @@
*
*/
/* ***************************** */
/* Includes */
/* ***************************** */
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <stdint.h>
#include <string.h>
#include <unistd.h>
#include <fcntl.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/ioctl.h>
#include <sys/uio.h>
#include <linux/dvb/video.h>
#include <linux/dvb/audio.h>
#include <linux/dvb/stm_ioctls.h>
#include <memory.h>
#include <asm/types.h>
#include <pthread.h>
#include <errno.h>
#include "common.h"
#include "output.h"
#include "debug.h"
#include "misc.h"
#include "pes.h"
#include "writer.h"
/* ***************************** */
/* Makros/Constants */
/* ***************************** */
#include <algorithm>
#define WMV3_PRIVATE_DATA_LENGTH 4
#define METADATA_STRUCT_A_START 12
#define METADATA_STRUCT_B_START 24
#define METADATA_STRUCT_B_FRAMERATE_START 32
#define METADATA_STRUCT_C_START 8
#define WMV_DEBUG
#ifdef WMV_DEBUG
static short debug_level = 0;
#define wmv_printf(level, fmt, x...) do { \
if (debug_level >= level) printf("[%s:%s] " fmt, __FILE__, __FUNCTION__, ## x); } while (0)
#else
#define wmv_printf(level, fmt, x...)
#endif
#ifndef WMV_SILENT
#define wmv_err(fmt, x...) do { printf("[%s:%s] " fmt, __FILE__, __FUNCTION__, ## x); } while (0)
#else
#define wmv_err(fmt, x...)
#endif
/* ***************************** */
/* Types */
/* ***************************** */
typedef struct {
unsigned char privateData[WMV3_PRIVATE_DATA_LENGTH];
unsigned int width;
unsigned int height;
unsigned int framerate;
} awmv_t;
static const unsigned char Metadata[] = {
0x00, 0x00, 0x00, 0xc5,
0x04, 0x00, 0x00, 0x00,
#define METADATA_STRUCT_C_START 8
0xc0, 0x00, 0x00, 0x00, /* Struct C set for for advanced profile */
#define METADATA_STRUCT_A_START 12
0x00, 0x00, 0x00, 0x00, /* Struct A */
0x00, 0x00, 0x00, 0x00,
0x0c, 0x00, 0x00, 0x00,
#define METADATA_STRUCT_B_START 24
0x60, 0x00, 0x00, 0x00, /* Struct B */
0x00, 0x00, 0x00, 0x00,
#define METADATA_STRUCT_B_FRAMERATE_START 32
0x00, 0x00, 0x00, 0x00
};
/* ***************************** */
/* Varaibles */
/* ***************************** */
static int initialHeader = 1;
class WriterWMV : public Writer
{
private:
bool initialHeader;
public:
bool Write(int fd, AVFormatContext *avfc, AVStream *stream, AVPacket *packet, int64_t &pts);
void Init();
WriterWMV();
};
/* ***************************** */
/* Prototypes */
/* ***************************** */
/* ***************************** */
/* MISC Functions */
/* ***************************** */
static int reset()
void WriterWMV::Init()
{
initialHeader = 1;
return 0;
}
static int writeData(WriterAVCallData_t *call)
bool WriterWMV::Write(int fd, AVFormatContext * /* avfc */, AVStream *stream, AVPacket *packet, int64_t &pts)
{
awmv_t private_data;
int len = 0;
if (fd < 0 || !packet)
return false;
wmv_printf(10, "\n");
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->stream->codec->extradata_size);
memcpy(private_data.privateData, call->stream->codec->extradata, call->stream->codec->extradata_size > WMV3_PRIVATE_DATA_LENGTH ? WMV3_PRIVATE_DATA_LENGTH : call->stream->codec->extradata_size);
private_data.width = call->stream->codec->width;
private_data.height = call->stream->codec->height;
private_data.framerate = 1000.0 * av_q2d(call->stream->r_frame_rate); /* rational to double */
#define PES_MIN_HEADER_SIZE 9
if (initialHeader) {
#define PES_MIN_HEADER_SIZE 9
unsigned char PesPacket[PES_MIN_HEADER_SIZE + 128];
unsigned char *PesPtr;
unsigned int MetadataLength;
unsigned int crazyFramerate = 0;
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);
unsigned int usecPerFrame = ((10000000.0 / av_q2d(stream->r_frame_rate)));
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);
unsigned char privateData[WMV3_PRIVATE_DATA_LENGTH] = { 0 };
memcpy(privateData, stream->codec->extradata, stream->codec->extradata_size > WMV3_PRIVATE_DATA_LENGTH ? WMV3_PRIVATE_DATA_LENGTH : stream->codec->extradata_size);
memcpy(PesPtr, 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++ = (stream->codec->height >> 0) & 0xff;
*PesPtr++ = (stream->codec->height >> 8) & 0xff;
*PesPtr++ = (stream->codec->height >> 16) & 0xff;
*PesPtr++ = stream->codec->height >> 24;
*PesPtr++ = (stream->codec->width >> 0) & 0xff;
*PesPtr++ = (stream->codec->width >> 8) & 0xff;
*PesPtr++ = (stream->codec->width >> 16) & 0xff;
*PesPtr++ = stream->codec->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;
*PesPtr++ = (usecPerFrame >> 0) & 0xff;
*PesPtr++ = (usecPerFrame >> 8) & 0xff;
*PesPtr++ = (usecPerFrame >> 16) & 0xff;
*PesPtr++ = usecPerFrame >> 24;
MetadataLength = PesPtr - &PesPacket[PES_MIN_HEADER_SIZE];
int HeaderLength =
InsertPesHeader(PesPacket, MetadataLength,
VC1_VIDEO_PES_START_CODE, INVALID_PTS_VALUE,
0);
int HeaderLength = InsertPesHeader(PesPacket, MetadataLength, VC1_VIDEO_PES_START_CODE, INVALID_PTS_VALUE, 0);
len = write(call->fd, PesPacket, HeaderLength + MetadataLength);
if (write(fd, PesPacket, HeaderLength + MetadataLength) < 0)
return false;
initialHeader = 0;
initialHeader = false;
}
if (call->packet->size > 0 && call->packet->data) {
if (packet->size > 0 && packet->data) {
int Position = 0;
unsigned char insertSampleHeader = 1;
while (Position < call->packet->size) {
bool insertSampleHeader = true;
int PacketLength = (call->packet->size - Position) <= MAX_PES_PACKET_SIZE ? (call->packet->size - Position) : MAX_PES_PACKET_SIZE;
uint64_t _pts = pts;
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;
while (Position < packet->size) {
int PacketLength = std::min(packet->size - Position, MAX_PES_PACKET_SIZE);
unsigned char PesHeader[PES_MAX_HEADER_SIZE] = { 0 };
int HeaderLength = InsertPesHeader(PesHeader, PacketLength, VC1_VIDEO_PES_START_CODE, _pts, 0);
if (insertSampleHeader) {
unsigned int PesLength;
unsigned int PrivateHeaderLength;
PrivateHeaderLength = InsertVideoPrivateDataHeader(&PesHeader[HeaderLength], call->packet->size);
PrivateHeaderLength = InsertVideoPrivateDataHeader(&PesHeader[HeaderLength], packet->size);
/* Update PesLength */
PesLength = PesHeader[PES_LENGTH_BYTE_0] +
(PesHeader[PES_LENGTH_BYTE_1] << 8) +
PrivateHeaderLength;
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_HEADER_DATA_LENGTH_BYTE] += PrivateHeaderLength;
PesHeader[PES_FLAGS_BYTE] |= PES_EXTENSION_DATA_PRESENT;
HeaderLength += PrivateHeaderLength;
insertSampleHeader = 0;
insertSampleHeader = false;
}
PacketStart = (unsigned char *) malloc(call->packet->size + HeaderLength);
uint8_t PacketStart[packet->size + HeaderLength];
memcpy(PacketStart, PesHeader, HeaderLength);
memcpy(PacketStart + HeaderLength, call->packet->data + Position,
PacketLength);
len =
write(call->fd, PacketStart, PacketLength + HeaderLength);
free(PacketStart);
memcpy(PacketStart + HeaderLength, packet->data + Position, PacketLength);
if (write(fd, PacketStart, PacketLength + HeaderLength) < 0)
return false;
Position += PacketLength;
call->Pts = INVALID_PTS_VALUE;
_pts = INVALID_PTS_VALUE;
}
}
wmv_printf(10, "< %d\n", len);
return len;
return true;
}
/* ***************************** */
/* Writer Definition */
/* ***************************** */
WriterWMV::WriterWMV()
{
Register(this, AV_CODEC_ID_WMV1, VIDEO_ENCODING_WMV);
Register(this, AV_CODEC_ID_WMV2, VIDEO_ENCODING_WMV);
Register(this, AV_CODEC_ID_WMV3, VIDEO_ENCODING_WMV);
}
static WriterCaps_t caps = {
"wmv",
eVideo,
"V_WMV",
VIDEO_ENCODING_WMV
};
struct Writer_s WriterVideoWMV = {
&reset,
&writeData,
&caps
};
static WriterWMV writer_wmv __attribute__ ((init_priority (300)));

View File

@@ -19,128 +19,97 @@
*
*/
/* ***************************** */
/* Includes */
/* ***************************** */
#include <stdlib.h>
#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 <string>
#include <map>
#include "pes.h"
#include "writer.h"
/* ***************************** */
/* Makros/Constants */
/* ***************************** */
// This does suck ... the original idea was to just link the object files and let them register themselves.
// Alas, that didn't work as expected.
#define WRITER_DEBUG
#include "divx.cpp"
#include "h263.cpp"
#include "h264.cpp"
#include "mp3.cpp"
#include "vc1.cpp"
#include "wmv.cpp"
#include "ac3.cpp"
#include "dts.cpp"
#include "flac.cpp"
#include "mpeg2.cpp"
#include "pcm.cpp"
#ifdef WRITER_DEBUG
static std::map<enum AVCodecID,Writer *>writers __attribute__ ((init_priority (200)));
static std::map<enum AVCodecID,video_encoding_t>vencoding __attribute__ ((init_priority (200)));
static std::map<enum AVCodecID,audio_encoding_t>aencoding __attribute__ ((init_priority (200)));
static short debug_level = 0;
#define writer_printf(level, x...) do { \
if (debug_level >= level) printf(x); } while (0)
#else
#define writer_printf(level, x...)
#endif
#ifndef WRITER_SILENT
#define writer_err(x...) do { printf(x); } while (0)
#else
#define writer_err(x...)
#endif
/* ***************************** */
/* Types */
/* ***************************** */
/* ***************************** */
/* Varaibles */
/* ***************************** */
static Writer_t *AvailableWriter[] = {
&WriterAudioIPCM,
// &WriterAudioPCM,
&WriterAudioMP3,
&WriterAudioMPEGL3,
&WriterAudioAC3,
&WriterAudioEAC3,
// &WriterAudioAAC,
&WriterAudioDTS,
// &WriterAudioWMA,
&WriterAudioFLAC,
&WriterAudioVORBIS,
&WriterVideoMPEG2,
&WriterVideoMPEGH264,
&WriterVideoH264,
&WriterVideoDIVX,
&WriterVideoFOURCC,
&WriterVideoMSCOMP,
&WriterVideoWMV,
&WriterVideoH263,
&WriterVideoFLV,
&WriterVideoVC1,
NULL
};
/* ***************************** */
/* Prototypes */
/* ***************************** */
/* ***************************** */
/* Functions */
/* ***************************** */
Writer_t *getWriter(char *encoding)
void Writer::Register(Writer *w, enum AVCodecID id, video_encoding_t 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;
writers[id] = w;
vencoding[id] = encoding;
}
Writer_t *getDefaultVideoWriter()
void Writer::Register(Writer *w, enum AVCodecID id, audio_encoding_t encoding)
{
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;
writers[id] = w;
aencoding[id] = encoding;
}
Writer_t *getDefaultAudioWriter()
bool Writer::Write(int /* fd */, AVFormatContext * /* avfc */, AVStream * /*stream*/, AVPacket * /* packet */, int64_t & /* pts */)
{
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;
return false;
}
static Writer writer __attribute__ ((init_priority (300)));
Writer *Writer::GetWriter(enum AVCodecID id, enum AVMediaType codec_type)
{
fprintf(stderr, "%s %s %d\n", __FILE__,__func__,__LINE__);
std::map<enum AVCodecID,Writer*>::iterator it = writers.find(id);
if (it != writers.end())
return it->second;
fprintf(stderr, "%s %s %d: no writer found\n", __FILE__,__func__,__LINE__);
switch (codec_type) {
case AVMEDIA_TYPE_AUDIO:
if (id == AV_CODEC_ID_INJECTPCM) // should not happen
break;
fprintf(stderr, "%s %s %d: returning injectpcm\n", __FILE__,__func__,__LINE__);
return GetWriter(AV_CODEC_ID_INJECTPCM, codec_type);
case AVMEDIA_TYPE_VIDEO:
if (id == AV_CODEC_ID_MPEG2TS) // should not happen
break;
fprintf(stderr, "%s %s %d: returning mpeg2video\n", __FILE__,__func__,__LINE__);
return GetWriter(AV_CODEC_ID_MPEG2TS, codec_type);
default:
break;
}
fprintf(stderr, "%s %s %d: returning dummy writer\n", __FILE__,__func__,__LINE__);
return &writer;
}
video_encoding_t Writer::GetVideoEncoding(enum AVCodecID id)
{
std::map<enum AVCodecID,video_encoding_t>::iterator it = vencoding.find(id);
if (it != vencoding.end())
return it->second;
return VIDEO_ENCODING_AUTO;
}
audio_encoding_t Writer::GetAudioEncoding(enum AVCodecID id)
{
std::map<enum AVCodecID,audio_encoding_t>::iterator it = aencoding.find(id);
if (it != aencoding.end())
return it->second;
return AUDIO_ENCODING_LPCMA;
}