libeplayer3: implement Writer class

Origin commit data
------------------
Branch: master
Commit: 889d68740c
Author: martii <m4rtii@gmx.de>
Date: 2014-04-06 (Sun, 06 Apr 2014)


------------------
No further description and justification available within origin commit message!

------------------
This commit was generated by Migit
This commit is contained in:
martii
2014-04-06 11:35:17 +02:00
parent f9b3095ba6
commit e9b361f9f8
27 changed files with 850 additions and 2377 deletions

View File

@@ -39,6 +39,8 @@
#include <pthread.h>
#include <sys/prctl.h>
#include <linux/dvb/stm_ioctls.h>
#include "common.h"
#include "misc.h"
#include "debug.h"
@@ -103,72 +105,6 @@ static float seek_sec_abs = -1.0, seek_sec_rel = 0.0;
/* MISC Functions */
/* ***************************** */
static const char *Codec2Encoding(AVCodecContext * codec)
{
fprintf(stderr, "Codec ID: %ld (%.8lx)\n", (long) codec->codec_id, (long) codec->codec_id);
switch (codec->codec_id) {
case AV_CODEC_ID_MPEG1VIDEO:
case AV_CODEC_ID_MPEG2VIDEO:
return "V_MPEG1";
case AV_CODEC_ID_H263:
case AV_CODEC_ID_H263P:
case AV_CODEC_ID_H263I:
return "V_H263";
case AV_CODEC_ID_FLV1:
return "V_FLV";
case AV_CODEC_ID_VP5:
case AV_CODEC_ID_VP6:
case AV_CODEC_ID_VP6F:
return "V_VP6";
case AV_CODEC_ID_RV10:
case AV_CODEC_ID_RV20:
return "V_RMV";
case AV_CODEC_ID_MPEG4:
case AV_CODEC_ID_MSMPEG4V1:
case AV_CODEC_ID_MSMPEG4V2:
case AV_CODEC_ID_MSMPEG4V3:
return "V_MSCOMP";
case AV_CODEC_ID_WMV1:
case AV_CODEC_ID_WMV2:
case AV_CODEC_ID_WMV3:
return "V_WMV";
case AV_CODEC_ID_VC1:
return "V_VC1";
case AV_CODEC_ID_H264:
return "V_MPEG4/ISO/AVC";
case AV_CODEC_ID_AVS:
return "V_AVS";
case AV_CODEC_ID_MP2:
return "A_MPEG/L3";
case AV_CODEC_ID_MP3:
return "A_MP3";
case AV_CODEC_ID_AC3:
return "A_AC3";
case AV_CODEC_ID_EAC3:
return "A_EAC3";
case AV_CODEC_ID_DTS:
return "A_DTS";
/* subtitle */
case AV_CODEC_ID_SSA:
return "S_TEXT/ASS"; /* Hellmaster1024: seems to be ASS instead of SSA */
case AV_CODEC_ID_TEXT: /* Hellmaster1024: i dont have most of this, but lets hope it is normal text :-) */
case AV_CODEC_ID_DVD_SUBTITLE:
case AV_CODEC_ID_DVB_SUBTITLE:
case AV_CODEC_ID_XSUB:
case AV_CODEC_ID_MOV_TEXT:
case AV_CODEC_ID_HDMV_PGS_SUBTITLE:
case AV_CODEC_ID_DVB_TELETEXT:
case AV_CODEC_ID_SRT:
return "S_TEXT/SRT"; /* fixme */
default:
// Default to injected-pcm for unhandled audio types.
if (codec->codec_type == AVMEDIA_TYPE_AUDIO)
return "A_IPCM";
ffmpeg_err("Codec ID %ld (%.8lx) not found\n", (long) codec->codec_id, (long) codec->codec_id);
}
return NULL;
}
int64_t calcPts(AVFormatContext *avfc, AVStream * stream, int64_t pts)
{
if (!avfc || !stream) {
@@ -219,10 +155,9 @@ static void *FFMPEGThread(void *arg)
}
ffmpeg_printf(10, "Running!\n");
while (context && context->playback && context->playback->isPlaying && !context->playback->abortRequested) {
AudioVideoOut_t avOut;
avOut.restart_audio_resampling = 0;
bool restart_audio_resampling = false;
while (context && context->playback && context->playback->isPlaying && !context->playback->abortRequested) {
//IF MOVIE IS PAUSED, WAIT
if (context->playback->isPaused) {
@@ -291,7 +226,7 @@ static void *FFMPEGThread(void *arg)
if (res < 0 && context->playback->BackWard)
bofcount = 1;
seek_target = INT64_MIN;
avOut.restart_audio_resampling = 1;
restart_audio_resampling = true;
// flush streams
unsigned int i;
@@ -321,8 +256,6 @@ static void *FFMPEGThread(void *arg)
context->playback->readCount += packet.size;
avOut.packet = &packet;
int pid = avContext->streams[packet.stream_index]->id;
if (context->manager->video->Command(context, MANAGER_GET_TRACK, &videoTrack) < 0)
@@ -343,28 +276,16 @@ static void *FFMPEGThread(void *arg)
currentVideoPts = pts = calcPts(avContext, videoTrack->stream, packet.pts);
ffmpeg_printf(200, "VideoTrack index = %d %lld\n", pid, currentVideoPts);
avOut.pts = pts;
avOut.type = "video";
avOut.stream = videoTrack->stream;
avOut.avfc = avContext;
if (context->output->video->Write(context, &avOut) < 0) {
if (!context->output->video->Write(avContext, videoTrack->stream, &packet, currentVideoPts))
ffmpeg_err("writing data to video device failed\n");
}
} else if (audioTrack && (audioTrack->Id == pid)) {
context->currentAudioPtsP = &currentAudioPts; //FIXME, temporary workaround only
if (restart_audio_resampling) {
restart_audio_resampling = false;
context->output->audio->Write(avContext, audioTrack->stream, NULL, currentAudioPts);
}
if (!context->playback->BackWard) {
currentAudioPts = pts = calcPts(avContext, audioTrack->stream, packet.pts);
ffmpeg_printf(200, "AudioTrack index = %d\n", pid);
avOut.pts = pts;
avOut.type = "audio";
avOut.stream = audioTrack->stream;
avOut.avfc = avContext;
if (context->output->audio->Write(context, &avOut) < 0)
if (!context->output->audio->Write(avContext, audioTrack->stream, &packet, currentAudioPts))
ffmpeg_err("writing data to audio device failed\n");
}
} else if (subtitleTrack && (subtitleTrack->Id == pid)) {
@@ -492,7 +413,6 @@ static void container_ffmpeg_read_subtitle(Context_t * context, const char *file
track.Name = format;
track.is_static = 1;
track.Id = pid;
track.Encoding = strcmp(format, "srt") ? "S_TEXT/ASS" : "S_TEXT/SRT";
context->manager->subtitle->Command(context, MANAGER_ADD, &track);
}
@@ -505,6 +425,10 @@ static void container_ffmpeg_read_subtitles(Context_t * context, const char *fil
container_ffmpeg_read_subtitle(context, filename, "ssa", 0xFFFD);
}
// from output/linuxdvb.cpp ... FIXME!
extern AVStream *audioStream;
extern AVStream *videoStream;
int container_ffmpeg_init(Context_t * context, const char *filename)
{
int err;
@@ -582,13 +506,23 @@ int container_ffmpeg_init(Context_t * context, const char *filename)
terminating = 0;
int res = container_ffmpeg_update_tracks(context, filename);
audioStream = NULL;
videoStream = NULL;
unsigned int n, found_av = 0;
for (n = 0; n < avContext->nb_streams; n++) {
AVStream *stream = avContext->streams[n];
switch (stream->codec->codec_type) {
case AVMEDIA_TYPE_AUDIO:
case AVMEDIA_TYPE_VIDEO:
if (!audioStream)
audioStream = stream;
found_av = 1;
break;
case AVMEDIA_TYPE_VIDEO:
if (!videoStream)
videoStream = stream;
found_av = 1;
break;
default:
break;
}
@@ -645,11 +579,6 @@ int container_ffmpeg_update_tracks(Context_t * context, const char *filename)
Track_t track;
AVStream *stream = avContext->streams[n];
const char *encoding = Codec2Encoding(stream->codec);
if (encoding != NULL)
ffmpeg_printf(1, "%d. encoding = %s\n", n, encoding);
if (!stream->id)
stream->id = n + 1;
@@ -660,9 +589,7 @@ int container_ffmpeg_update_tracks(Context_t * context, const char *filename)
case AVMEDIA_TYPE_VIDEO:
ffmpeg_printf(10, "CODEC_TYPE_VIDEO %d\n", stream->codec->codec_type);
if (encoding != NULL) {
track.Name = "und";
track.Encoding = encoding;
track.avfc = avContext;
track.Id = stream->id;
@@ -679,14 +606,10 @@ int container_ffmpeg_update_tracks(Context_t * context, const char *filename)
ffmpeg_err("failed to add track %d\n", n);
}
} else {
ffmpeg_err("codec type video but codec unknown %d\n", stream->codec->codec_id);
}
break;
case AVMEDIA_TYPE_AUDIO:
ffmpeg_printf(10, "CODEC_TYPE_AUDIO %d\n", stream->codec->codec_type);
if (encoding != NULL) {
AVDictionaryEntry *lang;
lang = av_dict_get(stream->metadata, "language", NULL, 0);
@@ -695,7 +618,6 @@ int container_ffmpeg_update_tracks(Context_t * context, const char *filename)
ffmpeg_printf(10, "Language %s\n", track.Name.c_str());
track.Encoding = encoding;
track.Id = stream->id;
track.duration = (double) stream->duration * av_q2d(stream->time_base) * 1000.0;
@@ -706,6 +628,28 @@ int container_ffmpeg_update_tracks(Context_t * context, const char *filename)
track.duration = (double) stream->duration * av_q2d(stream->time_base) * 1000.0;
}
switch(stream->codec->codec_id) {
case AUDIO_ENCODING_MPEG2:
track.ac3flags = 9;
break;
case AV_CODEC_ID_MP3:
track.ac3flags = 4;
break;
case AV_CODEC_ID_AC3:
track.ac3flags = 1;
break;
case AV_CODEC_ID_EAC3:
track.ac3flags = 7;
break;
case AV_CODEC_ID_DTS:
track.ac3flags = 6;
break;
case AV_CODEC_ID_AAC:
track.ac3flags = 5;
break;
default:
track.ac3flags = 0;
}
if (context->manager->audio) {
if (context->manager->audio->Command(context, MANAGER_ADD, &track) < 0) {
/* konfetti: fixme: is this a reason to return with error? */
@@ -713,9 +657,6 @@ int container_ffmpeg_update_tracks(Context_t * context, const char *filename)
}
}
} else {
ffmpeg_err("codec type audio but codec unknown %d\n", stream->codec->codec_id);
}
break;
case AVMEDIA_TYPE_SUBTITLE:
{
@@ -729,7 +670,6 @@ int container_ffmpeg_update_tracks(Context_t * context, const char *filename)
ffmpeg_printf(10, "Language %s\n", track.Name.c_str());
track.Encoding = encoding;
track.Id = stream->id;
track.duration = (double) stream->duration * av_q2d(stream->time_base) * 1000.0;
@@ -908,11 +848,16 @@ static int container_ffmpeg_get_length(Context_t * context, double *length)
static int container_ffmpeg_switch_audio(Context_t * context, int *arg)
{
ffmpeg_printf(10, "track %d\n", *arg);
/* Hellmaster1024: nothing to do here! */
float sec = -5.0;
context->playback->Command(context, PLAYBACK_SEEK, (void *) &sec);
return cERR_CONTAINER_FFMPEG_NO_ERROR;
Track_t *audioTrack = NULL;
context->manager->audio->Command(context, MANAGER_GET_TRACK, &arg);
if (audioTrack) {
audioStream = audioTrack->stream;
ffmpeg_printf(10, "track %d\n", *arg);
/* Hellmaster1024: nothing to do here! */
float sec = -5.0;
context->playback->Command(context, PLAYBACK_SEEK, (void *) &sec);
}
return cERR_CONTAINER_FFMPEG_NO_ERROR;
}
static int container_ffmpeg_switch_subtitle(Context_t * context __attribute__ ((unused)), int *arg __attribute__ ((unused)))

View File

@@ -19,7 +19,6 @@ typedef enum {
MANAGER_GET,
MANAGER_GETNAME,
MANAGER_SET,
MANAGER_GETENCODING,
MANAGER_DEL,
MANAGER_GET_TRACK,
MANAGER_INIT_UPDATE
@@ -32,7 +31,6 @@ typedef enum {
typedef struct Track_s {
std::string Name;
const char *Encoding;
int Id;
/* new field for ffmpeg - add at the end so no problem
@@ -52,7 +50,10 @@ typedef struct Track_s {
int is_static;
long long int chapter_start;
long long int chapter_end;
Track_s() : Encoding(NULL), Id(0), language(NULL), duration(-1), avfc(NULL), stream(NULL), pending(0), is_static(0), chapter_start(0), chapter_end(0) {}
int ac3flags;
Track_s() : Id(-1), language(NULL), duration(-1), avfc(NULL), stream(NULL), pending(0), is_static(0), chapter_start(0), chapter_end(0), ac3flags(-1) {}
} Track_t;
struct Context_s;

View File

@@ -1,44 +1,18 @@
#ifndef misc_123
#define misc_123
#include <dirent.h>
/* some useful things needed by many files ... */
/* ***************************** */
/* Types */
/* ***************************** */
#define INVALID_PTS_VALUE 0x200000000ll
typedef struct BitPacker_s {
unsigned char *Ptr; /* write pointer */
unsigned int BitBuffer; /* bitreader shifter */
int Remaining; /* number of remaining in the shifter */
} BitPacker_t;
/* ***************************** */
/* Makros/Constants */
/* ***************************** */
#define INVALID_PTS_VALUE 0x200000000ull
/* ***************************** */
/* Prototypes */
/* ***************************** */
struct BitPacker_t
{
unsigned char *Ptr; /* write pointer */
unsigned int BitBuffer; /* bitreader shifter */
int Remaining; /* number of remaining in the shifter */
};
void PutBits(BitPacker_t * ld, unsigned int code, unsigned int length);
void FlushBits(BitPacker_t * ld);
/* ***************************** */
/* MISC Functions */
/* ***************************** */
static inline char *getExtension(char *name)
{
if (name) {
char *ext = strrchr(name, '.');
if (ext)
return ext + 1;
}
return NULL;
}
#endif

View File

@@ -28,7 +28,6 @@ typedef enum {
OUTPUT_AVSYNC,
OUTPUT_CLEAR,
OUTPUT_PTS,
OUTPUT_SWITCH,
OUTPUT_SLOWMOTION,
OUTPUT_AUDIOMUTE,
OUTPUT_REVERSE,
@@ -54,7 +53,7 @@ typedef struct Context_s Context_t;
typedef struct Output_s {
const char *Name;
int (*Command) (Context_t *, OutputCmd_t, const char *);
int (*Write) (Context_t *, AudioVideoOut_t *privateData);
bool (*Write) (AVFormatContext *avfc, AVStream *stream, AVPacket *packet, int64_t &Pts);
const char **Capabilities;
} Output_t;

View File

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

View File

@@ -3,6 +3,7 @@
#include <stdio.h>
#include <stdint.h>
#include <sys/types.h>
extern "C" {
#include <libavutil/avutil.h>
@@ -12,61 +13,23 @@ extern "C" {
#include <libavutil/opt.h>
}
typedef enum { eNone, eAudio, eVideo, eGfx } eWriterType_t;
#include <linux/dvb/stm_ioctls.h>
struct Context_s;
typedef struct Context_s Context_t;
#define AV_CODEC_ID_INJECTPCM AV_CODEC_ID_PCM_S16LE
typedef struct {
int fd;
int64_t Pts;
int restart_audio_resampling;
AVFormatContext *avfc;
AVStream *stream;
AVPacket *packet;
Context_t *context;
} WriterAVCallData_t;
class Writer
{
public:
static void Register(Writer *w, enum AVCodecID id, video_encoding_t encoding);
static void Register(Writer *w, enum AVCodecID id, audio_encoding_t encoding);
static video_encoding_t GetVideoEncoding(enum AVCodecID id);
static audio_encoding_t GetAudioEncoding(enum AVCodecID id);
static Writer *GetWriter(enum AVCodecID id, enum AVMediaType codec_type);
typedef struct WriterCaps_s {
const char *name;
eWriterType_t type;
const char *textEncoding;
/* fixme: revise if this is an enum! */
int dvbEncoding;
} WriterCaps_t;
typedef struct Writer_s {
int (*reset) ();
int (*writeData) (WriterAVCallData_t *);
WriterCaps_t *caps;
} Writer_t;
extern Writer_t WriterAudioIPCM;
extern Writer_t WriterAudioPCM;
extern Writer_t WriterAudioMP3;
extern Writer_t WriterAudioMPEGL3;
extern Writer_t WriterAudioAC3;
extern Writer_t WriterAudioEAC3;
//extern Writer_t WriterAudioAAC;
extern Writer_t WriterAudioDTS;
//extern Writer_t WriterAudioWMA;
extern Writer_t WriterAudioFLAC;
extern Writer_t WriterAudioVORBIS;
extern Writer_t WriterVideoMPEG2;
extern Writer_t WriterVideoMPEGH264;
extern Writer_t WriterVideoH264;
extern Writer_t WriterVideoWMV;
extern Writer_t WriterVideoDIVX;
extern Writer_t WriterVideoFOURCC;
extern Writer_t WriterVideoMSCOMP;
extern Writer_t WriterVideoH263;
extern Writer_t WriterVideoFLV;
extern Writer_t WriterVideoVC1;
Writer_t *getWriter(char *encoding);
Writer_t *getDefaultVideoWriter();
Writer_t *getDefaultAudioWriter();
virtual void Init(void) { }
virtual bool Write(int fd, AVFormatContext *avfc, AVStream *stream, AVPacket *packet, int64_t &pts);
Writer() { Init (); }
~Writer() {}
};
#endif

View File

@@ -97,7 +97,9 @@ static char **ManagerList(Context_t * context __attribute__ ((unused)))
char tmp[len];
snprintf(tmp, len, "%d %s\n", it->second.Id, it->second.Name.c_str());
tracklist[j] = strdup(tmp);
tracklist[j + 1] = strdup(it->second.Encoding);
snprintf(tmp, len, "%d\n", it->second.ac3flags);
tracklist[j + 1] = strdup(tmp);
j += 2;
}
tracklist[j] = NULL;
@@ -141,13 +143,6 @@ static int Command(Context_t *context, ManagerCmd_t command, void *argument)
*((Track_t **) argument) = NULL;
break;
}
case MANAGER_GETENCODING:{
if (CurrentPid > -1)
*((char **) argument) = strdup(Tracks[CurrentPid].Encoding);
else
*((char **) argument) = strdup("");
break;
}
case MANAGER_GETNAME:{
if (CurrentPid > -1)
*((char **) argument) = strdup(Tracks[CurrentPid].Name.c_str());

View File

@@ -92,7 +92,8 @@ static char **ManagerList(Context_t * context __attribute__ ((unused)))
char tmp[len];
snprintf(tmp, len, "%d %s\n", it->second.Id, it->second.Name.c_str());
tracklist[j] = strdup(tmp);
tracklist[j + 1] = strdup(it->second.Encoding);
tracklist[j + 1] = strdup("");
j += 2;
}
tracklist[j] = NULL;

View File

@@ -94,7 +94,8 @@ static char **ManagerList(Context_t * context __attribute__ ((unused)))
char tmp[len];
snprintf(tmp, len, "%d %s\n", it->second.Id, it->second.Name.c_str());
tracklist[j] = strdup(tmp);
tracklist[j + 1] = strdup(it->second.Encoding);
tracklist[j + 1] = strdup("");
j += 2;
}
tracklist[j] = NULL;
@@ -136,13 +137,6 @@ static int Command(Context_t *context, ManagerCmd_t command, void *argument)
*((Track_t **) argument) = NULL;
break;
}
case MANAGER_GETENCODING:{
if (CurrentPid > -1)
*((char **) argument) = strdup(Tracks[CurrentPid].Encoding);
else
*((char **) argument) = strdup("");
break;
}
case MANAGER_GETNAME:{
if (CurrentPid > -1)
*((char **) argument) = strdup(Tracks[CurrentPid].Name.c_str());

View File

@@ -94,7 +94,8 @@ static char **ManagerList(Context_t * context __attribute__ ((unused)))
char tmp[len];
snprintf(tmp, len, "%d %s\n", it->second.Id, it->second.Name.c_str());
tracklist[j] = strdup(tmp);
tracklist[j + 1] = strdup(it->second.Encoding);
tracklist[j + 1] = strdup("");
j += 2;
}
tracklist[j] = NULL;
@@ -137,13 +138,6 @@ static int Command(Context_t *context, ManagerCmd_t command, void *argument)
*((Track_t **) argument) = NULL;
break;
}
case MANAGER_GETENCODING:{
if (CurrentPid > -1)
*((char **) argument) = strdup(Tracks[CurrentPid].Encoding);
else
*((char **) argument) = strdup("");
break;
}
case MANAGER_GETNAME:{
if (CurrentPid > -1)
*((char **) argument) = strdup(Tracks[CurrentPid].Name.c_str());

View File

@@ -97,7 +97,8 @@ static char **ManagerList(Context_t * context __attribute__ ((unused)))
char tmp[len];
snprintf(tmp, len, "%d %s\n", it->second.Id, it->second.Name.c_str());
tracklist[j] = strdup(tmp);
tracklist[j + 1] = strdup(it->second.Encoding);
tracklist[j + 1] = strdup("");
j += 2;
}
tracklist[j] = NULL;
@@ -140,13 +141,6 @@ static int Command(Context_t *context, ManagerCmd_t command, void *argument)
*((Track_t **) argument) = NULL;
break;
}
case MANAGER_GETENCODING:{
if (CurrentPid > -1)
*((char **) argument) = strdup(Tracks[CurrentPid].Encoding);
else
*((char **) argument) = strdup("");
break;
}
case MANAGER_GETNAME:{
if (CurrentPid > -1)
*((char **) argument) = strdup(Tracks[CurrentPid].Name.c_str());

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

View File

@@ -627,24 +627,26 @@ static int PlaybackSwitchAudio(Context_t * context, int *track)
if (context->playback->isPlaying) {
if (context->manager && context->manager->audio) {
context->manager->audio->Command(context, MANAGER_GET,
&curtrackid);
context->manager->audio->Command(context, MANAGER_GET, &curtrackid);
context->manager->audio->Command(context, MANAGER_SET, track);
context->manager->audio->Command(context, MANAGER_GET,
&nextrackid);
context->manager->audio->Command(context, MANAGER_GET, &nextrackid);
}
if (nextrackid != curtrackid) {
//PlaybackPause(context);
if (context->output && context->output->audio)
context->output->audio->Command(context, OUTPUT_SWITCH, "audio");
if (context->container
&& context->container->selectedContainer)
if (context->container && context->container->selectedContainer)
context->container->selectedContainer->Command(context, CONTAINER_SWITCH_AUDIO, (const char *)&nextrackid);
//FIXME
Track_t *t=NULL;
context->manager->audio->Command(context, MANAGER_GET_TRACK, &t);
extern bool output_switch_audio(AVStream*);
if(t)
output_switch_audio(t->stream);
//FIXME
//PlaybackContinue(context);
}
} else {

View File

@@ -491,26 +491,7 @@ void cPlayback::FindAllPids(int *apids, unsigned int *ac3flags, unsigned int *nu
if (2 == sscanf(TrackList[i], "%d %s\n", &_pid, _lang)) {
apids[j]=_pid;
// atUnknown, atMPEG, atMP3, atAC3, atDTS, atAAC, atPCM, atOGG, atFLAC
if( !strncmp("A_MPEG/L3", TrackList[i+1], 9))
ac3flags[j] = 3;
if( !strncmp("A_MP3", TrackList[i+1], 5))
ac3flags[j] = 4;
else if(!strncmp("A_AC3", TrackList[i+1], 5))
ac3flags[j] = 1;
else if(!strncmp("A_EAC3", TrackList[i+1], 6))
ac3flags[j] = 7;
else if(!strncmp("A_DTS", TrackList[i+1], 5))
ac3flags[j] = 6;
else if(!strncmp("A_AAC", TrackList[i+1], 5))
ac3flags[j] = 5;
else if(!strncmp("A_PCM", TrackList[i+1], 5))
ac3flags[j] = 0; //todo
else if(!strncmp("A_VORBIS", TrackList[i+1], 8))
ac3flags[j] = 0; //todo
else if(!strncmp("A_FLAC", TrackList[i+1], 6))
ac3flags[j] = 0; //todo
else
ac3flags[j] = 0; //todo
ac3flags[j] = atoi(TrackList[i+1]);
language[j]=std::string(_lang);
}
}