mirror of
https://github.com/tuxbox-fork-migrations/recycled-ni-libstb-hal.git
synced 2025-08-26 23:12:44 +02:00
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:
@@ -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 = ¤tAudioPts; //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)))
|
||||
|
@@ -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;
|
||||
|
@@ -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
|
||||
|
@@ -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;
|
||||
|
@@ -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);
|
||||
|
@@ -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
|
||||
|
@@ -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());
|
||||
|
@@ -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;
|
||||
|
||||
|
@@ -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());
|
||||
|
@@ -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());
|
||||
|
@@ -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());
|
||||
|
@@ -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;
|
||||
|
@@ -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)
|
||||
|
@@ -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)));
|
||||
|
@@ -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)));
|
||||
|
@@ -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)));
|
||||
|
@@ -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)));
|
||||
|
@@ -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)));
|
||||
|
@@ -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)));
|
||||
|
@@ -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)));
|
||||
|
@@ -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)));
|
||||
|
@@ -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)));
|
||||
|
@@ -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)));
|
||||
|
@@ -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)));
|
||||
|
@@ -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;
|
||||
}
|
||||
|
@@ -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 {
|
||||
|
@@ -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);
|
||||
}
|
||||
}
|
||||
|
Reference in New Issue
Block a user