mirror of
https://github.com/tuxbox-neutrino/libstb-hal.git
synced 2025-08-29 16:31:12 +02:00
- formatting code using astyle
Conflicts: libarmbox/dmx.cpp libgeneric-pc/video_lib.h libspark/dmx.cpp Signed-off-by: Thilo Graf <dbt@novatux.de>
This commit is contained in:
@@ -51,9 +51,9 @@ class Track;
|
||||
|
||||
class Input
|
||||
{
|
||||
friend class Player;
|
||||
friend class WriterPCM; // needs calcPts()
|
||||
friend int interrupt_cb(void *arg);
|
||||
friend class Player;
|
||||
friend class WriterPCM; // needs calcPts()
|
||||
friend int interrupt_cb(void *arg);
|
||||
|
||||
private:
|
||||
OpenThreads::Mutex mutex;
|
||||
@@ -75,7 +75,7 @@ class Input
|
||||
CodecList codecs[EPLAYER_MAX_CODECS];
|
||||
#endif
|
||||
uint64_t readCount;
|
||||
int64_t calcPts(AVStream * stream, int64_t pts);
|
||||
int64_t calcPts(AVStream *stream, int64_t pts);
|
||||
|
||||
public:
|
||||
Input();
|
||||
|
@@ -62,16 +62,16 @@ struct Program
|
||||
|
||||
class Manager
|
||||
{
|
||||
friend class Player;
|
||||
friend class Player;
|
||||
|
||||
private:
|
||||
Player *player;
|
||||
OpenThreads::Mutex mutex;
|
||||
std::map<int,Track*> videoTracks, audioTracks, subtitleTracks, teletextTracks;
|
||||
std::map<int,Program> Programs;
|
||||
void addTrack(std::map<int,Track*> &tracks, Track &track);
|
||||
Track *getTrack(std::map<int,Track*> &tracks, int pid);
|
||||
std::vector<Track> getTracks(std::map<int,Track*> &tracks);
|
||||
std::map<int, Track *> videoTracks, audioTracks, subtitleTracks, teletextTracks;
|
||||
std::map<int, Program> Programs;
|
||||
void addTrack(std::map<int, Track *> &tracks, Track &track);
|
||||
Track *getTrack(std::map<int, Track *> &tracks, int pid);
|
||||
std::vector<Track> getTracks(std::map<int, Track *> &tracks);
|
||||
public:
|
||||
void addVideoTrack(Track &track);
|
||||
void addAudioTrack(Track &track);
|
||||
|
@@ -5,16 +5,16 @@
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
#define INVALID_PTS_VALUE 0x200000000ll
|
||||
#define INVALID_PTS_VALUE 0x200000000ll
|
||||
|
||||
struct BitPacker_t
|
||||
{
|
||||
uint8_t *Ptr; /* write pointer */
|
||||
unsigned int BitBuffer; /* bitreader shifter */
|
||||
int Remaining; /* number of remaining in the shifter */
|
||||
uint8_t *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);
|
||||
void PutBits(BitPacker_t *ld, unsigned int code, unsigned int length);
|
||||
void FlushBits(BitPacker_t *ld);
|
||||
|
||||
#endif
|
||||
|
@@ -44,7 +44,7 @@ class Player;
|
||||
|
||||
class Output
|
||||
{
|
||||
friend class Player;
|
||||
friend class Player;
|
||||
|
||||
private:
|
||||
int videofd;
|
||||
|
@@ -3,30 +3,30 @@
|
||||
|
||||
#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 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 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 PCM_PES_START_CODE 0xbd
|
||||
#define PRIVATE_STREAM_1_PES_START_CODE 0xbd
|
||||
#define H263_VIDEO_PES_START_CODE 0xfe
|
||||
#define H264_VIDEO_PES_START_CODE 0xe2
|
||||
#define MPEG_VIDEO_PES_START_CODE 0xe0
|
||||
#define MPEG_AUDIO_PES_START_CODE 0xc0
|
||||
#define VC1_VIDEO_PES_START_CODE 0xfd
|
||||
#define AAC_AUDIO_PES_START_CODE 0xcf
|
||||
|
||||
int InsertPesHeader(uint8_t *data, int size, uint8_t stream_id, int64_t pts, int pic_start_code);
|
||||
int InsertVideoPrivateDataHeader(uint8_t *data, int payload_size);
|
||||
|
@@ -51,13 +51,14 @@ struct Chapter
|
||||
int64_t end;
|
||||
};
|
||||
|
||||
class Player {
|
||||
friend class Input;
|
||||
friend class Output;
|
||||
friend class Manager;
|
||||
friend class cPlayback;
|
||||
friend class WriterPCM;
|
||||
friend int interrupt_cb(void *arg);
|
||||
class Player
|
||||
{
|
||||
friend class Input;
|
||||
friend class Output;
|
||||
friend class Manager;
|
||||
friend class cPlayback;
|
||||
friend class WriterPCM;
|
||||
friend int interrupt_cb(void *arg);
|
||||
|
||||
private:
|
||||
Input input;
|
||||
@@ -81,10 +82,10 @@ class Player {
|
||||
uint64_t readCount;
|
||||
|
||||
std::string url;
|
||||
bool noprobe; /* hack: only minimal probing in av_find_stream_info */
|
||||
bool noprobe; /* hack: only minimal probing in av_find_stream_info */
|
||||
|
||||
void SetChapters(std::vector<Chapter> &Chapters);
|
||||
static void* playthread(void*);
|
||||
static void *playthread(void *);
|
||||
public:
|
||||
bool SwitchAudio(int pid);
|
||||
bool SwitchVideo(int pid);
|
||||
@@ -115,8 +116,14 @@ class Player {
|
||||
void RequestAbort();
|
||||
bool GetChapters(std::vector<int> &positions, std::vector<std::string> &titles);
|
||||
|
||||
AVFormatContext *GetAVFormatContext() { return input.GetAVFormatContext(); }
|
||||
void ReleaseAVFormatContext() { input.ReleaseAVFormatContext(); }
|
||||
AVFormatContext *GetAVFormatContext()
|
||||
{
|
||||
return input.GetAVFormatContext();
|
||||
}
|
||||
void ReleaseAVFormatContext()
|
||||
{
|
||||
input.ReleaseAVFormatContext();
|
||||
}
|
||||
|
||||
bool GetPrograms(std::vector<std::string> &keys, std::vector<std::string> &values);
|
||||
bool SelectProgram(int key);
|
||||
|
@@ -39,21 +39,21 @@ extern "C" {
|
||||
|
||||
/* wrapper */
|
||||
#if LIBAVFORMAT_VERSION_INT > AV_VERSION_INT(57,25,100)
|
||||
static AVCodecParameters __attribute__ ((unused)) *get_codecpar(AVStream *stream)
|
||||
static AVCodecParameters __attribute__((unused)) *get_codecpar(AVStream *stream)
|
||||
{
|
||||
return stream->codecpar;
|
||||
}
|
||||
#else
|
||||
static AVCodecContext __attribute__ ((unused)) *get_codecpar(AVStream *stream)
|
||||
static AVCodecContext __attribute__((unused)) *get_codecpar(AVStream *stream)
|
||||
{
|
||||
return stream->codec;
|
||||
}
|
||||
#endif
|
||||
|
||||
#if (LIBAVCODEC_VERSION_MAJOR > 55)
|
||||
#define av_free_packet av_packet_unref
|
||||
#define av_free_packet av_packet_unref
|
||||
#else
|
||||
#define av_packet_unref av_free_packet
|
||||
#define av_packet_unref av_free_packet
|
||||
#endif
|
||||
/* end wrapper */
|
||||
|
||||
@@ -71,7 +71,11 @@ class Writer
|
||||
static audio_encoding_t GetAudioEncoding(enum AVCodecID id);
|
||||
static Writer *GetWriter(enum AVCodecID id, enum AVMediaType codec_type, int track_type);
|
||||
|
||||
virtual void Init(int _fd, AVStream * /*stream*/, Player *_player ) { fd = _fd; player = _player; }
|
||||
virtual void Init(int _fd, AVStream * /*stream*/, Player *_player)
|
||||
{
|
||||
fd = _fd;
|
||||
player = _player;
|
||||
}
|
||||
virtual bool Write(AVPacket *packet, int64_t pts);
|
||||
};
|
||||
#endif
|
||||
|
@@ -34,14 +34,14 @@
|
||||
|
||||
static const char *FILENAME = "eplayer/input.cpp";
|
||||
|
||||
#define averror(_err,_fun) ({ \
|
||||
if (_err < 0) { \
|
||||
char _error[512]; \
|
||||
av_strerror(_err, _error, sizeof(_error)); \
|
||||
fprintf(stderr, "%s %d: %s: %d (%s)\n", FILENAME, __LINE__, #_fun, _err, _error); \
|
||||
} \
|
||||
_err; \
|
||||
})
|
||||
#define averror(_err,_fun) ({ \
|
||||
if (_err < 0) { \
|
||||
char _error[512]; \
|
||||
av_strerror(_err, _error, sizeof(_error)); \
|
||||
fprintf(stderr, "%s %d: %s: %d (%s)\n", FILENAME, __LINE__, #_fun, _err, _error); \
|
||||
} \
|
||||
_err; \
|
||||
})
|
||||
|
||||
Input::Input()
|
||||
{
|
||||
@@ -55,7 +55,7 @@ Input::Input()
|
||||
seek_avts_rel = 0;
|
||||
abortPlayback = false;
|
||||
#if LIBAVFORMAT_VERSION_INT > AV_VERSION_INT(57,25,100)
|
||||
for (int n = 0;n < EPLAYER_MAX_CODECS;n++)
|
||||
for (int n = 0; n < EPLAYER_MAX_CODECS; n++)
|
||||
codecs[n].codec = NULL;
|
||||
#endif
|
||||
}
|
||||
@@ -64,7 +64,7 @@ Input::~Input()
|
||||
{
|
||||
}
|
||||
|
||||
int64_t Input::calcPts(AVStream * stream, int64_t pts)
|
||||
int64_t Input::calcPts(AVStream *stream, int64_t pts)
|
||||
{
|
||||
if (pts == AV_NOPTS_VALUE)
|
||||
return INVALID_PTS_VALUE;
|
||||
@@ -89,17 +89,20 @@ extern void teletext_write(int pid, uint8_t *data, int size);
|
||||
static std::string lastlog_message;
|
||||
static unsigned int lastlog_repeats;
|
||||
|
||||
static void log_callback(void *ptr __attribute__ ((unused)), int lvl __attribute__ ((unused)), const char *format, va_list ap)
|
||||
static void log_callback(void *ptr __attribute__((unused)), int lvl __attribute__((unused)), const char *format, va_list ap)
|
||||
{
|
||||
char m[1024];
|
||||
if (sizeof(m) - 1 > (unsigned int) vsnprintf(m, sizeof(m), format, ap)) {
|
||||
if (lastlog_message.compare(m) || lastlog_repeats > 999) {
|
||||
if (sizeof(m) - 1 > (unsigned int) vsnprintf(m, sizeof(m), format, ap))
|
||||
{
|
||||
if (lastlog_message.compare(m) || lastlog_repeats > 999)
|
||||
{
|
||||
if (lastlog_repeats)
|
||||
fprintf(stderr, "last message repeated %u times\n", lastlog_repeats);
|
||||
lastlog_message = m;
|
||||
lastlog_repeats = 0;
|
||||
fprintf(stderr, "%s", m);
|
||||
} else
|
||||
}
|
||||
else
|
||||
lastlog_repeats++;
|
||||
}
|
||||
}
|
||||
@@ -115,21 +118,25 @@ static void logprintf(const char *format, ...)
|
||||
AVCodecContext *Input::GetCodecContext(unsigned int index)
|
||||
{
|
||||
#if LIBAVFORMAT_VERSION_INT > AV_VERSION_INT(57,25,100)
|
||||
if (codecs[index].codec) {
|
||||
if (codecs[index].codec)
|
||||
{
|
||||
return codecs[index].codec;
|
||||
}
|
||||
AVCodec *codec = avcodec_find_decoder(avfc->streams[index]->codecpar->codec_id);
|
||||
codecs[index].codec = avcodec_alloc_context3(codec);
|
||||
if (!codecs[index].codec) {
|
||||
if (!codecs[index].codec)
|
||||
{
|
||||
fprintf(stderr, "context3 alloc for stream %d failed\n", (int)index);
|
||||
return NULL;
|
||||
}
|
||||
if (avcodec_parameters_to_context(codecs[index].codec, avfc->streams[index]->codecpar) < 0) {
|
||||
if (avcodec_parameters_to_context(codecs[index].codec, avfc->streams[index]->codecpar) < 0)
|
||||
{
|
||||
fprintf(stderr, "copy parameters to codec context for stream %d failed\n", (int)index);
|
||||
avcodec_free_context(&codecs[index].codec);
|
||||
return NULL;
|
||||
}
|
||||
if (!codec) {
|
||||
if (!codec)
|
||||
{
|
||||
fprintf(stderr, "decoder for codec_id:(0x%X) stream:(%d) not found\n", avfc->streams[index]->codecpar->codec_id, (int)index);;
|
||||
return codecs[index].codec;
|
||||
}
|
||||
@@ -138,7 +145,8 @@ AVCodecContext *Input::GetCodecContext(unsigned int index)
|
||||
fprintf(stderr, "decoder for codec_id:(0x%X) stream:(%d) found\n", avfc->streams[index]->codecpar->codec_id, (int)index);;
|
||||
}
|
||||
int err = avcodec_open2(codecs[index].codec, codec, NULL);
|
||||
if (averror(err, avcodec_open2)) {
|
||||
if (averror(err, avcodec_open2))
|
||||
{
|
||||
fprintf(stderr, "open codec context for stream:(%d) failed}n", (int)index);
|
||||
avcodec_free_context(&codecs[index].codec);
|
||||
return NULL;
|
||||
@@ -161,10 +169,12 @@ bool Input::Play()
|
||||
// Oddly, this seems to be necessary for network streaming only ...
|
||||
bool audioSeen = !audioTrack || !player->isHttp;
|
||||
|
||||
while (player->isPlaying && !player->abortRequested) {
|
||||
while (player->isPlaying && !player->abortRequested)
|
||||
{
|
||||
|
||||
//IF MOVIE IS PAUSED, WAIT
|
||||
if (player->isPaused) {
|
||||
if (player->isPaused)
|
||||
{
|
||||
fprintf(stderr, "paused\n");
|
||||
usleep(100000);
|
||||
continue;
|
||||
@@ -173,44 +183,61 @@ bool Input::Play()
|
||||
int seek_target_flag = 0;
|
||||
int64_t seek_target = INT64_MIN; // in AV_TIME_BASE units
|
||||
|
||||
if (seek_avts_rel) {
|
||||
if (avfc->iformat->flags & AVFMT_TS_DISCONT) {
|
||||
if (avfc->bit_rate) {
|
||||
if (seek_avts_rel)
|
||||
{
|
||||
if (avfc->iformat->flags & AVFMT_TS_DISCONT)
|
||||
{
|
||||
if (avfc->bit_rate)
|
||||
{
|
||||
seek_target_flag = AVSEEK_FLAG_BYTE;
|
||||
seek_target = avio_tell(avfc->pb) + av_rescale(seek_avts_rel, avfc->bit_rate, 8 * AV_TIME_BASE);
|
||||
}
|
||||
} else {
|
||||
}
|
||||
else
|
||||
{
|
||||
int64_t pts;
|
||||
if(player->output.GetPts(pts))
|
||||
if (player->output.GetPts(pts))
|
||||
seek_target = av_rescale(pts, AV_TIME_BASE, 90000ll) + seek_avts_rel;
|
||||
}
|
||||
seek_avts_rel = 0;
|
||||
} else if (seek_avts_abs != INT64_MIN) {
|
||||
if (avfc->iformat->flags & AVFMT_TS_DISCONT) {
|
||||
if (avfc->bit_rate) {
|
||||
}
|
||||
else if (seek_avts_abs != INT64_MIN)
|
||||
{
|
||||
if (avfc->iformat->flags & AVFMT_TS_DISCONT)
|
||||
{
|
||||
if (avfc->bit_rate)
|
||||
{
|
||||
seek_target_flag = AVSEEK_FLAG_BYTE;
|
||||
seek_target = av_rescale(seek_avts_abs, avfc->bit_rate, 8 * AV_TIME_BASE);
|
||||
}
|
||||
} else {
|
||||
}
|
||||
else
|
||||
{
|
||||
seek_target = seek_avts_abs;
|
||||
}
|
||||
seek_avts_abs = INT64_MIN;
|
||||
} else if (player->isBackWard && av_gettime_relative() >= showtime) {
|
||||
}
|
||||
else if (player->isBackWard && av_gettime_relative() >= showtime)
|
||||
{
|
||||
player->output.ClearVideo();
|
||||
|
||||
if (bof) {
|
||||
if (bof)
|
||||
{
|
||||
showtime = av_gettime_relative();
|
||||
usleep(100000);
|
||||
continue;
|
||||
}
|
||||
seek_avts_rel = player->Speed * AV_TIME_BASE;
|
||||
showtime = av_gettime_relative() + 300000; //jump back every 300ms
|
||||
showtime = av_gettime_relative() + 300000; //jump back every 300ms
|
||||
continue;
|
||||
} else {
|
||||
}
|
||||
else
|
||||
{
|
||||
bof = false;
|
||||
}
|
||||
|
||||
if (seek_target > INT64_MIN) {
|
||||
if (seek_target > INT64_MIN)
|
||||
{
|
||||
int res;
|
||||
if (seek_target < 0)
|
||||
seek_target = 0;
|
||||
@@ -223,7 +250,8 @@ bool Input::Play()
|
||||
restart_audio_resampling = true;
|
||||
|
||||
// clear streams
|
||||
for (unsigned int i = 0; i < avfc->nb_streams; i++) {
|
||||
for (unsigned int i = 0; i < avfc->nb_streams; i++)
|
||||
{
|
||||
AVCodecContext *avcctx = GetCodecContext(i);
|
||||
if (avcctx && avcctx->codec)
|
||||
avcodec_flush_buffers(avcctx);
|
||||
@@ -236,13 +264,15 @@ bool Input::Play()
|
||||
av_init_packet(&packet);
|
||||
|
||||
int err = av_read_frame(avfc, &packet);
|
||||
if (err == AVERROR(EAGAIN)) {
|
||||
if (err == AVERROR(EAGAIN))
|
||||
{
|
||||
av_packet_unref(&packet);
|
||||
continue;
|
||||
}
|
||||
if (averror(err, av_read_frame)) { // EOF?
|
||||
if (averror(err, av_read_frame)) // EOF?
|
||||
{
|
||||
av_packet_unref(&packet);
|
||||
break; // while
|
||||
break; // while
|
||||
}
|
||||
|
||||
player->readCount += packet.size;
|
||||
@@ -254,24 +284,32 @@ bool Input::Play()
|
||||
Track *_subtitleTrack = subtitleTrack;
|
||||
Track *_teletextTrack = teletextTrack;
|
||||
|
||||
if (_videoTrack && (_videoTrack->stream == stream)) {
|
||||
if (_videoTrack && (_videoTrack->stream == stream))
|
||||
{
|
||||
int64_t pts = calcPts(stream, packet.pts);
|
||||
if (audioSeen && !player->output.Write(stream, &packet, pts))
|
||||
logprintf("writing data to video device failed\n");
|
||||
} else if (_audioTrack && (_audioTrack->stream == stream)) {
|
||||
if (restart_audio_resampling) {
|
||||
}
|
||||
else if (_audioTrack && (_audioTrack->stream == stream))
|
||||
{
|
||||
if (restart_audio_resampling)
|
||||
{
|
||||
restart_audio_resampling = false;
|
||||
player->output.Write(stream, NULL, 0);
|
||||
}
|
||||
if (!player->isBackWard) {
|
||||
if (!player->isBackWard)
|
||||
{
|
||||
int64_t pts = calcPts(stream, packet.pts);
|
||||
//if (!player->output.Write(stream, &packet, _videoTrack ? pts : 0)) // DBO: why pts only at video tracks ?
|
||||
//if (!player->output.Write(stream, &packet, _videoTrack ? pts : 0)) // DBO: why pts only at video tracks ?
|
||||
if (!player->output.Write(stream, &packet, pts))
|
||||
logprintf("writing data to audio device failed\n");
|
||||
}
|
||||
audioSeen = true;
|
||||
} else if (_subtitleTrack && (_subtitleTrack->stream == stream)) {
|
||||
if (avcctx->codec) {
|
||||
}
|
||||
else if (_subtitleTrack && (_subtitleTrack->stream == stream))
|
||||
{
|
||||
if (avcctx->codec)
|
||||
{
|
||||
AVSubtitle sub;
|
||||
memset(&sub, 0, sizeof(sub));
|
||||
int got_sub_ptr = 0;
|
||||
@@ -279,13 +317,16 @@ bool Input::Play()
|
||||
err = avcodec_decode_subtitle2(avcctx, &sub, &got_sub_ptr, &packet);
|
||||
averror(err, avcodec_decode_subtitle2);
|
||||
|
||||
if (got_sub_ptr && sub.num_rects > 0) {
|
||||
switch (sub.rects[0]->type) {
|
||||
if (got_sub_ptr && sub.num_rects > 0)
|
||||
{
|
||||
switch (sub.rects[0]->type)
|
||||
{
|
||||
case SUBTITLE_TEXT: // FIXME?
|
||||
case SUBTITLE_ASS:
|
||||
dvbsub_ass_write(avcctx, &sub, _subtitleTrack->pid);
|
||||
break;
|
||||
case SUBTITLE_BITMAP: {
|
||||
case SUBTITLE_BITMAP:
|
||||
{
|
||||
int64_t pts = calcPts(stream, packet.pts);
|
||||
dvbsub_write(&sub, pts);
|
||||
// avsubtitle_free() will be called by handler
|
||||
@@ -296,7 +337,9 @@ bool Input::Play()
|
||||
}
|
||||
}
|
||||
}
|
||||
} else if (_teletextTrack && (_teletextTrack->stream == stream)) {
|
||||
}
|
||||
else if (_teletextTrack && (_teletextTrack->stream == stream))
|
||||
{
|
||||
if (packet.data && packet.size > 1)
|
||||
teletext_write(_teletextTrack->pid, packet.data + 1, packet.size - 1);
|
||||
}
|
||||
@@ -329,7 +372,8 @@ bool Input::Play()
|
||||
#if LIBAVCODEC_VERSION_MAJOR < 58
|
||||
static int lock_callback(void **mutex, enum AVLockOp op)
|
||||
{
|
||||
switch (op) {
|
||||
switch (op)
|
||||
{
|
||||
case AV_LOCK_CREATE:
|
||||
*mutex = (void *) new OpenThreads::Mutex;
|
||||
return !*mutex;
|
||||
@@ -363,13 +407,15 @@ bool Input::ReadSubtitle(const char *filename, const char *format, int pid)
|
||||
|
||||
AVFormatContext *subavfc = avformat_alloc_context();
|
||||
int err = avformat_open_input(&subavfc, subfile, av_find_input_format(format), 0);
|
||||
if (averror(err, avformat_open_input)) {
|
||||
if (averror(err, avformat_open_input))
|
||||
{
|
||||
avformat_free_context(subavfc);
|
||||
return false;
|
||||
}
|
||||
|
||||
avformat_find_stream_info(subavfc, NULL);
|
||||
if (subavfc->nb_streams != 1) {
|
||||
if (subavfc->nb_streams != 1)
|
||||
{
|
||||
avformat_free_context(subavfc);
|
||||
return false;
|
||||
}
|
||||
@@ -380,7 +426,8 @@ bool Input::ReadSubtitle(const char *filename, const char *format, int pid)
|
||||
c = subavfc->streams[0]->codec;
|
||||
#else
|
||||
c = avcodec_alloc_context3(codec);
|
||||
if (avcodec_parameters_to_context(c, subavfc->streams[0]->codecpar) < 0) {
|
||||
if (avcodec_parameters_to_context(c, subavfc->streams[0]->codecpar) < 0)
|
||||
{
|
||||
avcodec_free_context(&c);
|
||||
avformat_close_input(&subavfc);
|
||||
avformat_free_context(subavfc);
|
||||
@@ -388,13 +435,15 @@ bool Input::ReadSubtitle(const char *filename, const char *format, int pid)
|
||||
}
|
||||
#endif
|
||||
codec = avcodec_find_decoder(c->codec_id);
|
||||
if (!codec) {
|
||||
if (!codec)
|
||||
{
|
||||
avformat_free_context(subavfc);
|
||||
return false;
|
||||
}
|
||||
|
||||
err = avcodec_open2(c, codec, NULL);
|
||||
if (averror(err, avcodec_open2)) {
|
||||
if (averror(err, avcodec_open2))
|
||||
{
|
||||
avformat_free_context(subavfc);
|
||||
return false;
|
||||
}
|
||||
@@ -402,7 +451,8 @@ bool Input::ReadSubtitle(const char *filename, const char *format, int pid)
|
||||
AVPacket packet;
|
||||
av_init_packet(&packet);
|
||||
|
||||
while (av_read_frame(subavfc, &packet) > -1) {
|
||||
while (av_read_frame(subavfc, &packet) > -1)
|
||||
{
|
||||
AVSubtitle sub;
|
||||
memset(&sub, 0, sizeof(sub));
|
||||
int got_sub = 0;
|
||||
@@ -426,7 +476,8 @@ bool Input::ReadSubtitle(const char *filename, const char *format, int pid)
|
||||
return true;
|
||||
}
|
||||
|
||||
bool Input::ReadSubtitles(const char *filename) {
|
||||
bool Input::ReadSubtitles(const char *filename)
|
||||
{
|
||||
if (strncmp(filename, "file://", 7))
|
||||
return false;
|
||||
filename += 7;
|
||||
@@ -454,7 +505,8 @@ bool Input::Init(const char *filename, std::string headers)
|
||||
av_log_set_level(AV_LOG_PANIC);
|
||||
#endif
|
||||
|
||||
if (!filename) {
|
||||
if (!filename)
|
||||
{
|
||||
fprintf(stderr, "filename NULL\n");
|
||||
return false;
|
||||
}
|
||||
@@ -501,14 +553,16 @@ again:
|
||||
av_log_set_level(AV_LOG_INFO);
|
||||
#endif
|
||||
av_dict_free(&options);
|
||||
if (averror(err, avformat_open_input)) {
|
||||
if (averror(err, avformat_open_input))
|
||||
{
|
||||
avformat_free_context(avfc);
|
||||
return false;
|
||||
}
|
||||
|
||||
avfc->iformat->flags |= AVFMT_SEEK_TO_PTS;
|
||||
avfc->flags = AVFMT_FLAG_GENPTS;
|
||||
if (player->noprobe) {
|
||||
if (player->noprobe)
|
||||
{
|
||||
#if LIBAVFORMAT_VERSION_INT < AV_VERSION_INT(55, 43, 100) || \
|
||||
LIBAVFORMAT_VERSION_INT > AV_VERSION_INT(57, 25, 0)
|
||||
avfc->max_analyze_duration = 1;
|
||||
@@ -520,7 +574,8 @@ again:
|
||||
#if 0
|
||||
if (!player->isHttp)
|
||||
{
|
||||
for (unsigned int i = 0; i < avfc->nb_streams; i++) {
|
||||
for (unsigned int i = 0; i < avfc->nb_streams; i++)
|
||||
{
|
||||
if (avfc->streams[i]->codec->codec_id == AV_CODEC_ID_AAC)
|
||||
find_info = false;
|
||||
}
|
||||
@@ -530,9 +585,11 @@ again:
|
||||
err = avformat_find_stream_info(avfc, NULL);
|
||||
|
||||
#if 0
|
||||
if (averror(err, avformat_find_stream_info)) {
|
||||
if (averror(err, avformat_find_stream_info))
|
||||
{
|
||||
avformat_close_input(&avfc);
|
||||
if (player->noprobe) {
|
||||
if (player->noprobe)
|
||||
{
|
||||
player->noprobe = false;
|
||||
goto again;
|
||||
}
|
||||
@@ -542,7 +599,8 @@ again:
|
||||
|
||||
bool res = UpdateTracks();
|
||||
|
||||
if (!videoTrack && !audioTrack) {
|
||||
if (!videoTrack && !audioTrack)
|
||||
{
|
||||
avformat_close_input(&avfc);
|
||||
return false;
|
||||
}
|
||||
@@ -563,9 +621,10 @@ bool Input::UpdateTracks()
|
||||
return true;
|
||||
|
||||
std::vector<Chapter> chapters;
|
||||
for (unsigned int i = 0; i < avfc->nb_chapters; i++) {
|
||||
for (unsigned int i = 0; i < avfc->nb_chapters; i++)
|
||||
{
|
||||
AVChapter *ch = avfc->chapters[i];
|
||||
AVDictionaryEntry* title = av_dict_get(ch->metadata, "title", NULL, 0);
|
||||
AVDictionaryEntry *title = av_dict_get(ch->metadata, "title", NULL, 0);
|
||||
Chapter chapter;
|
||||
chapter.title = title ? title->value : "";
|
||||
chapter.start = av_rescale(ch->time_base.num * AV_TIME_BASE, ch->start, ch->time_base.den);
|
||||
@@ -579,7 +638,8 @@ bool Input::UpdateTracks()
|
||||
av_dump_format(avfc, 0, player->url.c_str(), 0);
|
||||
|
||||
bool use_index_as_pid = false;
|
||||
for (unsigned int n = 0; n < avfc->nb_streams; n++) {
|
||||
for (unsigned int n = 0; n < avfc->nb_streams; n++)
|
||||
{
|
||||
AVStream *stream = avfc->streams[n];
|
||||
|
||||
AVCodecContext *avcctx = GetCodecContext(n);
|
||||
@@ -590,7 +650,8 @@ bool Input::UpdateTracks()
|
||||
track.title = lang ? lang->value : "";
|
||||
|
||||
if (!use_index_as_pid)
|
||||
switch (avcctx->codec_type) {
|
||||
switch (avcctx->codec_type)
|
||||
{
|
||||
case AVMEDIA_TYPE_VIDEO:
|
||||
case AVMEDIA_TYPE_AUDIO:
|
||||
case AVMEDIA_TYPE_SUBTITLE:
|
||||
@@ -600,17 +661,19 @@ bool Input::UpdateTracks()
|
||||
break;
|
||||
}
|
||||
|
||||
track.pid = use_index_as_pid ? n + 1: stream->id;
|
||||
track.pid = use_index_as_pid ? n + 1 : stream->id;
|
||||
track.ac3flags = 0;
|
||||
|
||||
switch (avcctx->codec_type) {
|
||||
switch (avcctx->codec_type)
|
||||
{
|
||||
case AVMEDIA_TYPE_VIDEO:
|
||||
player->manager.addVideoTrack(track);
|
||||
if (!videoTrack)
|
||||
videoTrack = player->manager.getVideoTrack(track.pid);
|
||||
break;
|
||||
case AVMEDIA_TYPE_AUDIO:
|
||||
switch(avcctx->codec_id) {
|
||||
switch (avcctx->codec_id)
|
||||
{
|
||||
case AV_CODEC_ID_MP2:
|
||||
track.ac3flags = 1;
|
||||
break;
|
||||
@@ -623,12 +686,14 @@ bool Input::UpdateTracks()
|
||||
case AV_CODEC_ID_DTS:
|
||||
track.ac3flags = 4;
|
||||
break;
|
||||
case AV_CODEC_ID_AAC: {
|
||||
case AV_CODEC_ID_AAC:
|
||||
{
|
||||
unsigned int extradata_size = avcctx->extradata_size;
|
||||
unsigned int object_type = 2;
|
||||
if(extradata_size >= 2)
|
||||
if (extradata_size >= 2)
|
||||
object_type = avcctx->extradata[0] >> 3;
|
||||
if (extradata_size <= 1 || object_type == 1 || object_type == 5) {
|
||||
if (extradata_size <= 1 || object_type == 1 || object_type == 5)
|
||||
{
|
||||
fprintf(stderr, "use resampling for AAC\n");
|
||||
track.ac3flags = 6;
|
||||
}
|
||||
@@ -654,24 +719,30 @@ bool Input::UpdateTracks()
|
||||
audioTrack = player->manager.getAudioTrack(track.pid);
|
||||
break;
|
||||
case AVMEDIA_TYPE_SUBTITLE:
|
||||
if (avcctx->codec_id == AV_CODEC_ID_DVB_TELETEXT) {
|
||||
if (avcctx->codec_id == AV_CODEC_ID_DVB_TELETEXT)
|
||||
{
|
||||
std::string l = lang ? lang->value : "";
|
||||
uint8_t *data = avcctx->extradata;
|
||||
int size = avcctx->extradata_size;
|
||||
if (size > 0 && 2 * size - 1 == (int) l.length())
|
||||
for (int i = 0; i < size; i += 2) {
|
||||
for (int i = 0; i < size; i += 2)
|
||||
{
|
||||
track.title = l.substr(i * 2, 3);
|
||||
track.type = data[i] >> 3;
|
||||
track.mag = data[i] & 7;
|
||||
track.page = data[i + 1];
|
||||
player->manager.addTeletextTrack(track);
|
||||
}
|
||||
} else {
|
||||
if (!avcctx->codec) {
|
||||
}
|
||||
else
|
||||
{
|
||||
if (!avcctx->codec)
|
||||
{
|
||||
avcctx->codec = avcodec_find_decoder(avcctx->codec_id);
|
||||
if (!avcctx->codec)
|
||||
fprintf(stderr, "avcodec_find_decoder failed for subtitle track %d\n", n);
|
||||
else {
|
||||
else
|
||||
{
|
||||
int err = avcodec_open2(avcctx, avcctx->codec, NULL);
|
||||
if (averror(err, avcodec_open2))
|
||||
avcctx->codec = NULL;
|
||||
@@ -687,9 +758,11 @@ bool Input::UpdateTracks()
|
||||
}
|
||||
}
|
||||
|
||||
for (unsigned int n = 0; n < avfc->nb_programs; n++) {
|
||||
for (unsigned int n = 0; n < avfc->nb_programs; n++)
|
||||
{
|
||||
AVProgram *p = avfc->programs[n];
|
||||
if (p->nb_stream_indexes) {
|
||||
if (p->nb_stream_indexes)
|
||||
{
|
||||
AVDictionaryEntry *name = av_dict_get(p->metadata, "name", NULL, 0);
|
||||
Program program;
|
||||
program.title = name ? name->value : "";
|
||||
@@ -712,9 +785,11 @@ bool Input::Stop()
|
||||
|
||||
av_log(NULL, AV_LOG_QUIET, "%s", "");
|
||||
|
||||
if (avfc) {
|
||||
if (avfc)
|
||||
{
|
||||
OpenThreads::ScopedLock<OpenThreads::Mutex> lock(mutex);
|
||||
for (unsigned int i = 0; i < avfc->nb_streams; i++) {
|
||||
for (unsigned int i = 0; i < avfc->nb_streams; i++)
|
||||
{
|
||||
#if LIBAVFORMAT_VERSION_INT > AV_VERSION_INT(57,25,100)
|
||||
if (codecs[i].codec)
|
||||
avcodec_free_context(&codecs[i].codec);
|
||||
@@ -756,7 +831,8 @@ bool Input::Seek(int64_t avts, bool absolute)
|
||||
|
||||
bool Input::GetDuration(int64_t &duration)
|
||||
{
|
||||
if (avfc) {
|
||||
if (avfc)
|
||||
{
|
||||
duration = avfc->duration;
|
||||
return true;
|
||||
}
|
||||
@@ -796,38 +872,45 @@ bool Input::GetMetadata(std::vector<std::string> &keys, std::vector<std::string>
|
||||
keys.clear();
|
||||
values.clear();
|
||||
|
||||
if (avfc) {
|
||||
if (avfc)
|
||||
{
|
||||
AVDictionaryEntry *tag = NULL;
|
||||
|
||||
if (avfc->metadata)
|
||||
while ((tag = av_dict_get(avfc->metadata, "", tag, AV_DICT_IGNORE_SUFFIX))) {
|
||||
while ((tag = av_dict_get(avfc->metadata, "", tag, AV_DICT_IGNORE_SUFFIX)))
|
||||
{
|
||||
keys.push_back(tag->key);
|
||||
values.push_back(tag->value);
|
||||
}
|
||||
|
||||
if (videoTrack)
|
||||
while ((tag = av_dict_get(videoTrack->stream->metadata, "", tag, AV_DICT_IGNORE_SUFFIX))) {
|
||||
while ((tag = av_dict_get(videoTrack->stream->metadata, "", tag, AV_DICT_IGNORE_SUFFIX)))
|
||||
{
|
||||
keys.push_back(tag->key);
|
||||
values.push_back(tag->value);
|
||||
}
|
||||
|
||||
if (audioTrack)
|
||||
while ((tag = av_dict_get(audioTrack->stream->metadata, "", tag, AV_DICT_IGNORE_SUFFIX))) {
|
||||
while ((tag = av_dict_get(audioTrack->stream->metadata, "", tag, AV_DICT_IGNORE_SUFFIX)))
|
||||
{
|
||||
keys.push_back(tag->key);
|
||||
values.push_back(tag->value);
|
||||
}
|
||||
|
||||
// find the first attached picture, if available
|
||||
for(unsigned int i = 0; i < avfc->nb_streams; i++) {
|
||||
if (avfc->streams[i]->disposition & AV_DISPOSITION_ATTACHED_PIC) {
|
||||
AVPacket *pkt = &avfc->streams[i]->attached_pic;
|
||||
FILE *cover_art = fopen("/tmp/.id3coverart", "wb");
|
||||
if (cover_art) {
|
||||
fwrite(pkt->data, pkt->size, 1, cover_art);
|
||||
fclose(cover_art);
|
||||
}
|
||||
av_packet_unref(pkt);
|
||||
break;
|
||||
for (unsigned int i = 0; i < avfc->nb_streams; i++)
|
||||
{
|
||||
if (avfc->streams[i]->disposition & AV_DISPOSITION_ATTACHED_PIC)
|
||||
{
|
||||
AVPacket *pkt = &avfc->streams[i]->attached_pic;
|
||||
FILE *cover_art = fopen("/tmp/.id3coverart", "wb");
|
||||
if (cover_art)
|
||||
{
|
||||
fwrite(pkt->data, pkt->size, 1, cover_art);
|
||||
fclose(cover_art);
|
||||
}
|
||||
av_packet_unref(pkt);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@@ -23,15 +23,17 @@
|
||||
#include "manager.h"
|
||||
#include "player.h"
|
||||
|
||||
void Manager::addTrack(std::map<int,Track*> &tracks, Track &track)
|
||||
void Manager::addTrack(std::map<int, Track *> &tracks, Track &track)
|
||||
{
|
||||
OpenThreads::ScopedLock<OpenThreads::Mutex> m_lock(mutex);
|
||||
std::map<int,Track*>::iterator it = tracks.find(track.pid);
|
||||
if (it == tracks.end()) {
|
||||
std::map<int, Track *>::iterator it = tracks.find(track.pid);
|
||||
if (it == tracks.end())
|
||||
{
|
||||
Track *t = new Track;
|
||||
*t = track;
|
||||
tracks[track.pid] = t;
|
||||
} else
|
||||
}
|
||||
else
|
||||
*it->second = track;
|
||||
}
|
||||
|
||||
@@ -55,12 +57,12 @@ void Manager::addTeletextTrack(Track &track)
|
||||
addTrack(teletextTracks, track);
|
||||
}
|
||||
|
||||
std::vector<Track> Manager::getTracks(std::map<int,Track*> &tracks)
|
||||
std::vector<Track> Manager::getTracks(std::map<int, Track *> &tracks)
|
||||
{
|
||||
player->input.UpdateTracks();
|
||||
std::vector<Track> res;
|
||||
OpenThreads::ScopedLock<OpenThreads::Mutex> m_lock(mutex);
|
||||
for(std::map<int,Track*>::iterator it = tracks.begin(); it != tracks.end(); ++it)
|
||||
for (std::map<int, Track *>::iterator it = tracks.begin(); it != tracks.end(); ++it)
|
||||
if (!it->second->inactive && !it->second->hidden)
|
||||
res.push_back(*it->second);
|
||||
return res;
|
||||
@@ -86,10 +88,10 @@ std::vector<Track> Manager::getTeletextTracks()
|
||||
return getTracks(teletextTracks);
|
||||
}
|
||||
|
||||
Track *Manager::getTrack(std::map<int,Track*> &tracks, int pid)
|
||||
Track *Manager::getTrack(std::map<int, Track *> &tracks, int pid)
|
||||
{
|
||||
OpenThreads::ScopedLock<OpenThreads::Mutex> m_lock(mutex);
|
||||
std::map<int,Track*>::iterator it = tracks.find(pid);
|
||||
std::map<int, Track *>::iterator it = tracks.find(pid);
|
||||
if (it != tracks.end() && !it->second->inactive)
|
||||
return it->second;
|
||||
return NULL;
|
||||
@@ -118,16 +120,16 @@ bool Manager::initTrackUpdate()
|
||||
{
|
||||
OpenThreads::ScopedLock<OpenThreads::Mutex> m_lock(mutex);
|
||||
|
||||
for (std::map<int,Track*>::iterator it = audioTracks.begin(); it != audioTracks.end(); ++it)
|
||||
for (std::map<int, Track *>::iterator it = audioTracks.begin(); it != audioTracks.end(); ++it)
|
||||
it->second->inactive = !it->second->is_static;
|
||||
|
||||
for (std::map<int, Track*>::iterator it = videoTracks.begin(); it != videoTracks.end(); ++it)
|
||||
for (std::map<int, Track *>::iterator it = videoTracks.begin(); it != videoTracks.end(); ++it)
|
||||
it->second->inactive = !it->second->is_static;
|
||||
|
||||
for (std::map<int,Track*>::iterator it = subtitleTracks.begin(); it != subtitleTracks.end(); ++it)
|
||||
for (std::map<int, Track *>::iterator it = subtitleTracks.begin(); it != subtitleTracks.end(); ++it)
|
||||
it->second->inactive = !it->second->is_static;
|
||||
|
||||
for (std::map<int,Track*>::iterator it = teletextTracks.begin(); it != teletextTracks.end(); ++it)
|
||||
for (std::map<int, Track *>::iterator it = teletextTracks.begin(); it != teletextTracks.end(); ++it)
|
||||
it->second->inactive = !it->second->is_static;
|
||||
|
||||
return true;
|
||||
@@ -142,7 +144,7 @@ std::vector<Program> Manager::getPrograms(void)
|
||||
{
|
||||
OpenThreads::ScopedLock<OpenThreads::Mutex> m_lock(mutex);
|
||||
std::vector<Program> res;
|
||||
for (std::map<int,Program>::iterator it = Programs.begin(); it != Programs.end(); ++it)
|
||||
for (std::map<int, Program>::iterator it = Programs.begin(); it != Programs.end(); ++it)
|
||||
res.push_back(it->second);
|
||||
return res;
|
||||
}
|
||||
@@ -150,81 +152,95 @@ std::vector<Program> Manager::getPrograms(void)
|
||||
bool Manager::selectProgram(const int id)
|
||||
{
|
||||
OpenThreads::ScopedLock<OpenThreads::Mutex> m_lock(mutex);
|
||||
std::map<int,Program>::iterator i = Programs.find(id);
|
||||
if (i != Programs.end()) {
|
||||
std::map<int, Program>::iterator i = Programs.find(id);
|
||||
if (i != Programs.end())
|
||||
{
|
||||
|
||||
// mark all tracks as hidden
|
||||
for (std::map<int,Track*>::iterator it = audioTracks.begin(); it != audioTracks.end(); ++it)
|
||||
for (std::map<int, Track *>::iterator it = audioTracks.begin(); it != audioTracks.end(); ++it)
|
||||
it->second->hidden = true;
|
||||
|
||||
for (std::map<int, Track*>::iterator it = videoTracks.begin(); it != videoTracks.end(); ++it)
|
||||
for (std::map<int, Track *>::iterator it = videoTracks.begin(); it != videoTracks.end(); ++it)
|
||||
it->second->hidden = true;
|
||||
|
||||
for (std::map<int,Track*>::iterator it = subtitleTracks.begin(); it != subtitleTracks.end(); ++it)
|
||||
for (std::map<int, Track *>::iterator it = subtitleTracks.begin(); it != subtitleTracks.end(); ++it)
|
||||
it->second->hidden = true;
|
||||
|
||||
for (std::map<int,Track*>::iterator it = teletextTracks.begin(); it != teletextTracks.end(); ++it)
|
||||
for (std::map<int, Track *>::iterator it = teletextTracks.begin(); it != teletextTracks.end(); ++it)
|
||||
it->second->hidden = true;
|
||||
|
||||
// unhide tracks that are part of the selected program
|
||||
for (unsigned int j = 0; j < i->second.streams.size(); j++) {
|
||||
for (unsigned int j = 0; j < i->second.streams.size(); j++)
|
||||
{
|
||||
AVStream *stream = i->second.streams[j];
|
||||
bool h = true;
|
||||
for (std::map<int,Track*>::iterator it = audioTracks.begin(); h && (it != audioTracks.end()); ++it)
|
||||
for (std::map<int, Track *>::iterator it = audioTracks.begin(); h && (it != audioTracks.end()); ++it)
|
||||
if (stream == it->second->stream)
|
||||
h = it->second->hidden = false;
|
||||
|
||||
if (!h)
|
||||
continue;
|
||||
|
||||
for (std::map<int, Track*>::iterator it = videoTracks.begin(); h && (it != videoTracks.end()); ++it)
|
||||
for (std::map<int, Track *>::iterator it = videoTracks.begin(); h && (it != videoTracks.end()); ++it)
|
||||
if (stream == it->second->stream)
|
||||
h = it->second->hidden = false;
|
||||
|
||||
if (!h)
|
||||
continue;
|
||||
|
||||
for (std::map<int,Track*>::iterator it = subtitleTracks.begin(); h && (it != subtitleTracks.end()); ++it)
|
||||
for (std::map<int, Track *>::iterator it = subtitleTracks.begin(); h && (it != subtitleTracks.end()); ++it)
|
||||
if (stream == it->second->stream)
|
||||
h = it->second->hidden = false;
|
||||
|
||||
if (!h)
|
||||
continue;
|
||||
|
||||
for (std::map<int,Track*>::iterator it = teletextTracks.begin(); h && (it != teletextTracks.end()); ++it)
|
||||
for (std::map<int, Track *>::iterator it = teletextTracks.begin(); h && (it != teletextTracks.end()); ++it)
|
||||
if (stream == it->second->stream)
|
||||
h = it->second->hidden = false;
|
||||
}
|
||||
|
||||
// tell ffmpeg what we're interested in
|
||||
for (std::map<int,Track*>::iterator it = audioTracks.begin(); it != audioTracks.end(); ++it)
|
||||
if (it->second->hidden || it->second->inactive) {
|
||||
for (std::map<int, Track *>::iterator it = audioTracks.begin(); it != audioTracks.end(); ++it)
|
||||
if (it->second->hidden || it->second->inactive)
|
||||
{
|
||||
it->second->stream->discard = AVDISCARD_ALL;
|
||||
} else {
|
||||
}
|
||||
else
|
||||
{
|
||||
it->second->stream->discard = AVDISCARD_NONE;
|
||||
player->input.SwitchAudio(it->second);
|
||||
}
|
||||
|
||||
for (std::map<int, Track*>::iterator it = videoTracks.begin(); it != videoTracks.end(); ++it)
|
||||
if (it->second->hidden || it->second->inactive) {
|
||||
for (std::map<int, Track *>::iterator it = videoTracks.begin(); it != videoTracks.end(); ++it)
|
||||
if (it->second->hidden || it->second->inactive)
|
||||
{
|
||||
it->second->stream->discard = AVDISCARD_ALL;
|
||||
} else {
|
||||
}
|
||||
else
|
||||
{
|
||||
it->second->stream->discard = AVDISCARD_NONE;
|
||||
player->input.SwitchVideo(it->second);
|
||||
}
|
||||
|
||||
for (std::map<int,Track*>::iterator it = subtitleTracks.begin(); it != subtitleTracks.end(); ++it)
|
||||
if (it->second->hidden || it->second->inactive) {
|
||||
for (std::map<int, Track *>::iterator it = subtitleTracks.begin(); it != subtitleTracks.end(); ++it)
|
||||
if (it->second->hidden || it->second->inactive)
|
||||
{
|
||||
it->second->stream->discard = AVDISCARD_ALL;
|
||||
} else {
|
||||
}
|
||||
else
|
||||
{
|
||||
it->second->stream->discard = AVDISCARD_NONE;
|
||||
player->input.SwitchSubtitle(it->second);
|
||||
}
|
||||
|
||||
for (std::map<int,Track*>::iterator it = teletextTracks.begin(); it != teletextTracks.end(); ++it)
|
||||
if (it->second->hidden || it->second->inactive) {
|
||||
for (std::map<int, Track *>::iterator it = teletextTracks.begin(); it != teletextTracks.end(); ++it)
|
||||
if (it->second->hidden || it->second->inactive)
|
||||
{
|
||||
it->second->stream->discard = AVDISCARD_ALL;
|
||||
} else {
|
||||
}
|
||||
else
|
||||
{
|
||||
it->second->stream->discard = AVDISCARD_NONE;
|
||||
player->input.SwitchTeletext(it->second);
|
||||
}
|
||||
@@ -238,19 +254,19 @@ void Manager::clearTracks()
|
||||
{
|
||||
OpenThreads::ScopedLock<OpenThreads::Mutex> m_lock(mutex);
|
||||
|
||||
for (std::map<int,Track*>::iterator it = audioTracks.begin(); it != audioTracks.end(); ++it)
|
||||
for (std::map<int, Track *>::iterator it = audioTracks.begin(); it != audioTracks.end(); ++it)
|
||||
delete it->second;
|
||||
audioTracks.clear();
|
||||
|
||||
for (std::map<int, Track*>::iterator it = videoTracks.begin(); it != videoTracks.end(); ++it)
|
||||
for (std::map<int, Track *>::iterator it = videoTracks.begin(); it != videoTracks.end(); ++it)
|
||||
delete it->second;
|
||||
videoTracks.clear();
|
||||
|
||||
for (std::map<int,Track*>::iterator it = subtitleTracks.begin(); it != subtitleTracks.end(); ++it)
|
||||
for (std::map<int, Track *>::iterator it = subtitleTracks.begin(); it != subtitleTracks.end(); ++it)
|
||||
delete it->second;
|
||||
subtitleTracks.clear();
|
||||
|
||||
for (std::map<int,Track*>::iterator it = teletextTracks.begin(); it != teletextTracks.end(); ++it)
|
||||
for (std::map<int, Track *>::iterator it = teletextTracks.begin(); it != teletextTracks.end(); ++it)
|
||||
delete it->second;
|
||||
teletextTracks.clear();
|
||||
|
||||
|
@@ -44,12 +44,12 @@
|
||||
|
||||
static const char *FILENAME = "eplayer/output.cpp";
|
||||
|
||||
#define dioctl(fd,req,arg) ({ \
|
||||
int _r = ioctl(fd,req,arg); \
|
||||
if (_r) \
|
||||
fprintf(stderr, "%s %d: ioctl '%s' failed: %d (%s)\n", FILENAME, __LINE__, #req, errno, strerror(errno)); \
|
||||
_r; \
|
||||
})
|
||||
#define dioctl(fd,req,arg) ({ \
|
||||
int _r = ioctl(fd,req,arg); \
|
||||
if (_r) \
|
||||
fprintf(stderr, "%s %d: ioctl '%s' failed: %d (%s)\n", FILENAME, __LINE__, #req, errno, strerror(errno)); \
|
||||
_r; \
|
||||
})
|
||||
|
||||
#define VIDEODEV "/dev/dvb/adapter0/video0"
|
||||
#define AUDIODEV "/dev/dvb/adapter0/audio0"
|
||||
@@ -70,7 +70,7 @@ bool Output::Open()
|
||||
{
|
||||
OpenThreads::ScopedLock<OpenThreads::Mutex> v_lock(videoMutex);
|
||||
OpenThreads::ScopedLock<OpenThreads::Mutex> a_lock(audioMutex);
|
||||
|
||||
|
||||
if (videofd < 0)
|
||||
videofd = open(VIDEODEV, O_RDWR);
|
||||
|
||||
@@ -85,7 +85,8 @@ bool Output::Open()
|
||||
if (audiofd < 0)
|
||||
audiofd = open(AUDIODEV, O_RDWR);
|
||||
|
||||
if (audiofd < 0) {
|
||||
if (audiofd < 0)
|
||||
{
|
||||
close(videofd);
|
||||
videofd = -1;
|
||||
return false;
|
||||
@@ -105,11 +106,13 @@ bool Output::Close()
|
||||
OpenThreads::ScopedLock<OpenThreads::Mutex> v_lock(videoMutex);
|
||||
OpenThreads::ScopedLock<OpenThreads::Mutex> a_lock(audioMutex);
|
||||
|
||||
if (videofd > -1) {
|
||||
if (videofd > -1)
|
||||
{
|
||||
close(videofd);
|
||||
videofd = -1;
|
||||
}
|
||||
if (audiofd > -1) {
|
||||
if (audiofd > -1)
|
||||
{
|
||||
close(audiofd);
|
||||
audiofd = -1;
|
||||
}
|
||||
@@ -127,22 +130,24 @@ bool Output::Play()
|
||||
OpenThreads::ScopedLock<OpenThreads::Mutex> v_lock(videoMutex);
|
||||
OpenThreads::ScopedLock<OpenThreads::Mutex> a_lock(audioMutex);
|
||||
|
||||
if (videoTrack && videoTrack->stream && videofd > -1 && get_codecpar(videoTrack->stream)) {
|
||||
if (videoTrack && videoTrack->stream && videofd > -1 && get_codecpar(videoTrack->stream))
|
||||
{
|
||||
videoWriter = Writer::GetWriter(get_codecpar(videoTrack->stream)->codec_id, get_codecpar(videoTrack->stream)->codec_type, videoTrack->ac3flags);
|
||||
videoWriter->Init(videofd, videoTrack->stream, player);
|
||||
if (dioctl(videofd, VIDEO_SET_ENCODING, videoWriter->GetVideoEncoding(get_codecpar(videoTrack->stream)->codec_id))
|
||||
|| dioctl(videofd, VIDEO_PLAY, NULL))
|
||||
|| dioctl(videofd, VIDEO_PLAY, NULL))
|
||||
ret = false;
|
||||
}
|
||||
|
||||
if (audioTrack && audioTrack->stream && audiofd > -1 && get_codecpar(audioTrack->stream)) {
|
||||
if (audioTrack && audioTrack->stream && audiofd > -1 && get_codecpar(audioTrack->stream))
|
||||
{
|
||||
audioWriter = Writer::GetWriter(get_codecpar(audioTrack->stream)->codec_id, get_codecpar(audioTrack->stream)->codec_type, audioTrack->ac3flags);
|
||||
audioWriter->Init(audiofd, audioTrack->stream, player);
|
||||
audio_encoding_t audioEncoding = AUDIO_ENCODING_LPCMA;
|
||||
if (audioTrack->ac3flags != 6)
|
||||
audioEncoding = audioWriter->GetAudioEncoding(get_codecpar(audioTrack->stream)->codec_id);
|
||||
if (dioctl(audiofd, AUDIO_SET_ENCODING, audioEncoding)
|
||||
|| dioctl(audiofd, AUDIO_PLAY, NULL))
|
||||
|| dioctl(audiofd, AUDIO_PLAY, NULL))
|
||||
ret = false;
|
||||
}
|
||||
return ret;
|
||||
@@ -155,7 +160,8 @@ bool Output::Stop()
|
||||
OpenThreads::ScopedLock<OpenThreads::Mutex> v_lock(videoMutex);
|
||||
OpenThreads::ScopedLock<OpenThreads::Mutex> a_lock(audioMutex);
|
||||
|
||||
if (videofd > -1) {
|
||||
if (videofd > -1)
|
||||
{
|
||||
ioctl(videofd, VIDEO_CLEAR_BUFFER, NULL);
|
||||
/* set back to normal speed (end trickmodes) */
|
||||
dioctl(videofd, VIDEO_SET_SPEED, DVB_SPEED_NORMAL_PLAY);
|
||||
@@ -163,7 +169,8 @@ bool Output::Stop()
|
||||
ret = false;
|
||||
}
|
||||
|
||||
if (audiofd > -1) {
|
||||
if (audiofd > -1)
|
||||
{
|
||||
ioctl(audiofd, AUDIO_CLEAR_BUFFER, NULL);
|
||||
/* set back to normal speed (end trickmodes) */
|
||||
dioctl(audiofd, AUDIO_SET_SPEED, DVB_SPEED_NORMAL_PLAY);
|
||||
@@ -181,12 +188,14 @@ bool Output::Pause()
|
||||
OpenThreads::ScopedLock<OpenThreads::Mutex> v_lock(videoMutex);
|
||||
OpenThreads::ScopedLock<OpenThreads::Mutex> a_lock(audioMutex);
|
||||
|
||||
if (videofd > -1) {
|
||||
if (videofd > -1)
|
||||
{
|
||||
if (dioctl(videofd, VIDEO_FREEZE, NULL))
|
||||
ret = false;
|
||||
}
|
||||
|
||||
if (audiofd > -1) {
|
||||
if (audiofd > -1)
|
||||
{
|
||||
if (dioctl(audiofd, AUDIO_PAUSE, NULL))
|
||||
ret = false;
|
||||
}
|
||||
@@ -228,7 +237,8 @@ bool Output::Flush()
|
||||
if (videofd > -1 && ioctl(videofd, VIDEO_FLUSH, NULL))
|
||||
ret = false;
|
||||
|
||||
if (audiofd > -1 && audioWriter) {
|
||||
if (audiofd > -1 && audioWriter)
|
||||
{
|
||||
// flush audio decoder
|
||||
AVPacket packet;
|
||||
packet.data = NULL;
|
||||
@@ -283,7 +293,7 @@ bool Output::GetPts(int64_t &pts)
|
||||
{
|
||||
pts = 0;
|
||||
return ((videofd > -1 && !ioctl(videofd, VIDEO_GET_PTS, (void *) &pts)) ||
|
||||
(audiofd > -1 && !ioctl(audiofd, AUDIO_GET_PTS, (void *) &pts)));
|
||||
(audiofd > -1 && !ioctl(audiofd, AUDIO_GET_PTS, (void *) &pts)));
|
||||
}
|
||||
|
||||
bool Output::GetFrameCount(int64_t &framecount)
|
||||
@@ -291,7 +301,8 @@ bool Output::GetFrameCount(int64_t &framecount)
|
||||
dvb_play_info_t playInfo;
|
||||
|
||||
if ((videofd > -1 && !dioctl(videofd, VIDEO_GET_PLAY_INFO, (void *) &playInfo)) ||
|
||||
(audiofd > -1 && !dioctl(audiofd, AUDIO_GET_PLAY_INFO, (void *) &playInfo))) {
|
||||
(audiofd > -1 && !dioctl(audiofd, AUDIO_GET_PLAY_INFO, (void *) &playInfo)))
|
||||
{
|
||||
framecount = playInfo.frame_count;
|
||||
return true;
|
||||
}
|
||||
@@ -303,20 +314,23 @@ bool Output::SwitchAudio(Track *track)
|
||||
OpenThreads::ScopedLock<OpenThreads::Mutex> a_lock(audioMutex);
|
||||
if (audioTrack && track->stream == audioTrack->stream)
|
||||
return true;
|
||||
if (audiofd > -1) {
|
||||
if (audiofd > -1)
|
||||
{
|
||||
dioctl(audiofd, AUDIO_STOP, NULL);
|
||||
ioctl(audiofd, AUDIO_CLEAR_BUFFER, NULL);
|
||||
}
|
||||
audioTrack = track;
|
||||
if (track->stream) {
|
||||
if (track->stream)
|
||||
{
|
||||
if (!get_codecpar(audioTrack->stream))
|
||||
return false;
|
||||
audioWriter = Writer::GetWriter(get_codecpar(audioTrack->stream)->codec_id, get_codecpar(audioTrack->stream)->codec_type, audioTrack->ac3flags);
|
||||
audioWriter->Init(audiofd, audioTrack->stream, player);
|
||||
if (audiofd > -1) {
|
||||
audioWriter = Writer::GetWriter(get_codecpar(audioTrack->stream)->codec_id, get_codecpar(audioTrack->stream)->codec_type, audioTrack->ac3flags);
|
||||
audioWriter->Init(audiofd, audioTrack->stream, player);
|
||||
if (audiofd > -1)
|
||||
{
|
||||
audio_encoding_t audioEncoding = AUDIO_ENCODING_LPCMA;
|
||||
if (audioTrack->ac3flags != 6)
|
||||
audioEncoding = Writer::GetAudioEncoding(get_codecpar(audioTrack->stream)->codec_id);
|
||||
if (audioTrack->ac3flags != 6)
|
||||
audioEncoding = Writer::GetAudioEncoding(get_codecpar(audioTrack->stream)->codec_id);
|
||||
dioctl(audiofd, AUDIO_SET_ENCODING, audioEncoding);
|
||||
dioctl(audiofd, AUDIO_PLAY, NULL);
|
||||
}
|
||||
@@ -329,17 +343,20 @@ bool Output::SwitchVideo(Track *track)
|
||||
OpenThreads::ScopedLock<OpenThreads::Mutex> v_lock(videoMutex);
|
||||
if (videoTrack && track->stream == videoTrack->stream)
|
||||
return true;
|
||||
if (videofd > -1) {
|
||||
if (videofd > -1)
|
||||
{
|
||||
dioctl(videofd, VIDEO_STOP, NULL);
|
||||
ioctl(videofd, VIDEO_CLEAR_BUFFER, NULL);
|
||||
}
|
||||
videoTrack = track;
|
||||
if (track->stream) {
|
||||
if (track->stream)
|
||||
{
|
||||
if (!get_codecpar(videoTrack->stream))
|
||||
return false;
|
||||
videoWriter = Writer::GetWriter(get_codecpar(videoTrack->stream)->codec_id, get_codecpar(videoTrack->stream)->codec_type, videoTrack->type);
|
||||
videoWriter->Init(videofd, videoTrack->stream, player);
|
||||
if (videofd > -1) {
|
||||
if (videofd > -1)
|
||||
{
|
||||
dioctl(videofd, VIDEO_SET_ENCODING, Writer::GetVideoEncoding(get_codecpar(videoTrack->stream)->codec_id));
|
||||
dioctl(videofd, VIDEO_PLAY, NULL);
|
||||
}
|
||||
@@ -349,12 +366,15 @@ bool Output::SwitchVideo(Track *track)
|
||||
|
||||
bool Output::Write(AVStream *stream, AVPacket *packet, int64_t pts)
|
||||
{
|
||||
switch (get_codecpar(stream)->codec_type) {
|
||||
case AVMEDIA_TYPE_VIDEO: {
|
||||
switch (get_codecpar(stream)->codec_type)
|
||||
{
|
||||
case AVMEDIA_TYPE_VIDEO:
|
||||
{
|
||||
OpenThreads::ScopedLock<OpenThreads::Mutex> v_lock(videoMutex);
|
||||
return videofd > -1 && videoWriter && videoWriter->Write(packet, pts);
|
||||
}
|
||||
case AVMEDIA_TYPE_AUDIO: {
|
||||
case AVMEDIA_TYPE_AUDIO:
|
||||
{
|
||||
OpenThreads::ScopedLock<OpenThreads::Mutex> a_lock(audioMutex);
|
||||
return audiofd > -1 && audioWriter && audioWriter->Write(packet, pts);
|
||||
}
|
||||
|
@@ -32,8 +32,8 @@
|
||||
|
||||
static const char *FILENAME = "eplayer/player.cpp";
|
||||
|
||||
#define cMaxSpeed_ff 128 /* fixme: revise */
|
||||
#define cMaxSpeed_fr -320 /* fixme: revise */
|
||||
#define cMaxSpeed_ff 128 /* fixme: revise */
|
||||
#define cMaxSpeed_fr -320 /* fixme: revise */
|
||||
|
||||
Player::Player()
|
||||
{
|
||||
@@ -75,16 +75,23 @@ bool Player::Open(const char *Url, bool _noprobe, std::string headers)
|
||||
|
||||
manager.clearTracks();
|
||||
|
||||
if (!strncmp("mms://", Url, 6)) {
|
||||
if (!strncmp("mms://", Url, 6))
|
||||
{
|
||||
url = "mmst";
|
||||
url += Url + 3;
|
||||
isHttp = true;
|
||||
} else if (strstr(Url, "://")) {
|
||||
}
|
||||
else if (strstr(Url, "://"))
|
||||
{
|
||||
url = Url;
|
||||
isHttp = strncmp("file://", Url, 7);
|
||||
} else if (!strncmp(Url, "bluray:/", 8)) {
|
||||
}
|
||||
else if (!strncmp(Url, "bluray:/", 8))
|
||||
{
|
||||
url = Url;
|
||||
} else {
|
||||
}
|
||||
else
|
||||
{
|
||||
fprintf(stderr, "%s %s %d: Unknown stream (%s)\n", FILENAME, __func__, __LINE__, Url);
|
||||
return false;
|
||||
}
|
||||
@@ -109,37 +116,46 @@ bool Player::Play()
|
||||
{
|
||||
bool ret = true;
|
||||
|
||||
if (!isPlaying) {
|
||||
if (!isPlaying)
|
||||
{
|
||||
output.AVSync(true);
|
||||
|
||||
ret = output.Play();
|
||||
|
||||
if (ret) {
|
||||
if (ret)
|
||||
{
|
||||
isPlaying = true;
|
||||
isPaused = false;
|
||||
isForwarding = false;
|
||||
if (isBackWard) {
|
||||
if (isBackWard)
|
||||
{
|
||||
isBackWard = false;
|
||||
output.Mute(false);
|
||||
}
|
||||
isSlowMotion = false;
|
||||
Speed = 1;
|
||||
|
||||
if (!hasThreadStarted) {
|
||||
if (!hasThreadStarted)
|
||||
{
|
||||
int err = pthread_create(&playThread, NULL, playthread, this);
|
||||
|
||||
if (err) {
|
||||
if (err)
|
||||
{
|
||||
fprintf(stderr, "%s %s %d: pthread_create: %d (%s)\n", FILENAME, __func__, __LINE__, err, strerror(err));
|
||||
ret = false;
|
||||
isPlaying = false;
|
||||
} else {
|
||||
}
|
||||
else
|
||||
{
|
||||
pthread_detach(playThread);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
} else {
|
||||
fprintf(stderr,"playback already running\n");
|
||||
}
|
||||
else
|
||||
{
|
||||
fprintf(stderr, "playback already running\n");
|
||||
ret = false;
|
||||
}
|
||||
return ret;
|
||||
@@ -149,7 +165,8 @@ bool Player::Pause()
|
||||
{
|
||||
bool ret = true;
|
||||
|
||||
if (isPlaying && !isPaused) {
|
||||
if (isPlaying && !isPaused)
|
||||
{
|
||||
|
||||
if (isSlowMotion)
|
||||
output.Clear();
|
||||
@@ -159,14 +176,17 @@ bool Player::Pause()
|
||||
isPaused = true;
|
||||
//isPlaying = 1;
|
||||
isForwarding = false;
|
||||
if (isBackWard) {
|
||||
if (isBackWard)
|
||||
{
|
||||
isBackWard = false;
|
||||
output.Mute(false);
|
||||
}
|
||||
isSlowMotion = false;
|
||||
Speed = 1;
|
||||
} else {
|
||||
fprintf(stderr,"playback not playing or already in pause mode\n");
|
||||
}
|
||||
else
|
||||
{
|
||||
fprintf(stderr, "playback not playing or already in pause mode\n");
|
||||
ret = false;
|
||||
}
|
||||
return ret;
|
||||
@@ -176,7 +196,8 @@ bool Player::Continue()
|
||||
{
|
||||
int ret = true;
|
||||
|
||||
if (isPlaying && (isPaused || isForwarding || isBackWard || isSlowMotion)) {
|
||||
if (isPlaying && (isPaused || isForwarding || isBackWard || isSlowMotion))
|
||||
{
|
||||
|
||||
if (isSlowMotion)
|
||||
output.Clear();
|
||||
@@ -186,14 +207,17 @@ bool Player::Continue()
|
||||
isPaused = false;
|
||||
//isPlaying = 1;
|
||||
isForwarding = false;
|
||||
if (isBackWard) {
|
||||
if (isBackWard)
|
||||
{
|
||||
isBackWard = false;
|
||||
output.Mute(false);
|
||||
}
|
||||
isSlowMotion = false;
|
||||
Speed = 1;
|
||||
} else {
|
||||
fprintf(stderr,"continue not possible\n");
|
||||
}
|
||||
else
|
||||
{
|
||||
fprintf(stderr, "continue not possible\n");
|
||||
ret = false;
|
||||
}
|
||||
|
||||
@@ -204,11 +228,13 @@ bool Player::Stop()
|
||||
{
|
||||
bool ret = true;
|
||||
|
||||
if (isPlaying) {
|
||||
if (isPlaying)
|
||||
{
|
||||
isPaused = false;
|
||||
isPlaying = false;
|
||||
isForwarding = false;
|
||||
if (isBackWard) {
|
||||
if (isBackWard)
|
||||
{
|
||||
isBackWard = false;
|
||||
output.Mute(false);
|
||||
}
|
||||
@@ -218,8 +244,10 @@ bool Player::Stop()
|
||||
output.Stop();
|
||||
input.Stop();
|
||||
|
||||
} else {
|
||||
fprintf(stderr,"stop not possible\n");
|
||||
}
|
||||
else
|
||||
{
|
||||
fprintf(stderr, "stop not possible\n");
|
||||
ret = false;
|
||||
}
|
||||
|
||||
@@ -234,9 +262,11 @@ bool Player::FastForward(int speed)
|
||||
int ret = true;
|
||||
|
||||
/* Audio only forwarding not supported */
|
||||
if (input.videoTrack && !isHttp && !isBackWard && (!isPaused || isPlaying)) {
|
||||
if (input.videoTrack && !isHttp && !isBackWard && (!isPaused || isPlaying))
|
||||
{
|
||||
|
||||
if ((speed <= 0) || (speed > cMaxSpeed_ff)) {
|
||||
if ((speed <= 0) || (speed > cMaxSpeed_ff))
|
||||
{
|
||||
fprintf(stderr, "speed %d out of range (1 - %d) \n", speed, cMaxSpeed_ff);
|
||||
return false;
|
||||
}
|
||||
@@ -244,8 +274,10 @@ bool Player::FastForward(int speed)
|
||||
isForwarding = 1;
|
||||
Speed = speed;
|
||||
output.FastForward(speed);
|
||||
} else {
|
||||
fprintf(stderr,"fast forward not possible\n");
|
||||
}
|
||||
else
|
||||
{
|
||||
fprintf(stderr, "fast forward not possible\n");
|
||||
ret = false;
|
||||
}
|
||||
|
||||
@@ -257,32 +289,40 @@ bool Player::FastBackward(int speed)
|
||||
bool ret = true;
|
||||
|
||||
/* Audio only reverse play not supported */
|
||||
if (input.videoTrack && !isForwarding && (!isPaused || isPlaying)) {
|
||||
if (input.videoTrack && !isForwarding && (!isPaused || isPlaying))
|
||||
{
|
||||
|
||||
if ((speed > 0) || (speed < cMaxSpeed_fr)) {
|
||||
if ((speed > 0) || (speed < cMaxSpeed_fr))
|
||||
{
|
||||
fprintf(stderr, "speed %d out of range (0 - %d) \n", speed, cMaxSpeed_fr);
|
||||
return false;
|
||||
}
|
||||
|
||||
if (speed == 0) {
|
||||
if (speed == 0)
|
||||
{
|
||||
isBackWard = false;
|
||||
Speed = 0; /* reverse end */
|
||||
} else {
|
||||
Speed = 0; /* reverse end */
|
||||
}
|
||||
else
|
||||
{
|
||||
Speed = speed;
|
||||
isBackWard = true;
|
||||
}
|
||||
|
||||
output.Clear();
|
||||
#if 0
|
||||
if (output->Command(player, OUTPUT_REVERSE, NULL) < 0) {
|
||||
fprintf(stderr,"OUTPUT_REVERSE failed\n");
|
||||
if (output->Command(player, OUTPUT_REVERSE, NULL) < 0)
|
||||
{
|
||||
fprintf(stderr, "OUTPUT_REVERSE failed\n");
|
||||
isBackWard = false;
|
||||
Speed = 1;
|
||||
ret = false;
|
||||
}
|
||||
#endif
|
||||
} else {
|
||||
fprintf(stderr,"fast backward not possible\n");
|
||||
}
|
||||
else
|
||||
{
|
||||
fprintf(stderr, "fast backward not possible\n");
|
||||
ret = false;
|
||||
}
|
||||
|
||||
@@ -294,11 +334,13 @@ bool Player::FastBackward(int speed)
|
||||
|
||||
bool Player::SlowMotion(int repeats)
|
||||
{
|
||||
if (input.videoTrack && !isHttp && isPlaying) {
|
||||
if (input.videoTrack && !isHttp && isPlaying)
|
||||
{
|
||||
if (isPaused)
|
||||
Continue();
|
||||
|
||||
switch (repeats) {
|
||||
switch (repeats)
|
||||
{
|
||||
case 2:
|
||||
case 4:
|
||||
case 8:
|
||||
@@ -318,7 +360,7 @@ bool Player::SlowMotion(int repeats)
|
||||
bool Player::Seek(int64_t pos, bool absolute)
|
||||
{
|
||||
if (GetVideoPid())
|
||||
/* Don't Clear if no video track */
|
||||
/* Don't Clear if no video track */
|
||||
output.Clear();
|
||||
return input.Seek(pos, absolute);
|
||||
}
|
||||
@@ -375,8 +417,9 @@ bool Player::GetChapters(std::vector<int> &positions, std::vector<std::string> &
|
||||
titles.clear();
|
||||
input.UpdateTracks();
|
||||
OpenThreads::ScopedLock<OpenThreads::Mutex> m_lock(chapterMutex);
|
||||
for (std::vector<Chapter>::iterator it = chapters.begin(); it != chapters.end(); ++it) {
|
||||
positions.push_back(it->start/1000);
|
||||
for (std::vector<Chapter>::iterator it = chapters.begin(); it != chapters.end(); ++it)
|
||||
{
|
||||
positions.push_back(it->start / 1000);
|
||||
titles.push_back(it->title);
|
||||
}
|
||||
return true;
|
||||
@@ -427,7 +470,8 @@ bool Player::GetPrograms(std::vector<std::string> &keys, std::vector<std::string
|
||||
if (p.empty())
|
||||
return false;
|
||||
|
||||
for (std::vector<Program>::iterator it = p.begin(); it != p.end(); ++it) {
|
||||
for (std::vector<Program>::iterator it = p.begin(); it != p.end(); ++it)
|
||||
{
|
||||
std::stringstream s;
|
||||
s << it->id;
|
||||
keys.push_back(s.str());
|
||||
|
@@ -41,7 +41,8 @@
|
||||
static inline void Hexdump(unsigned char *Data, int length)
|
||||
{
|
||||
int k;
|
||||
for (k = 0; k < length; k++) {
|
||||
for (k = 0; k < length; k++)
|
||||
{
|
||||
printf("%02x ", Data[k]);
|
||||
if (((k + 1) & 31) == 0)
|
||||
printf("\n");
|
||||
@@ -84,7 +85,7 @@ static inline int aac_get_sample_rate_index(uint32_t sample_rate)
|
||||
}
|
||||
|
||||
#if 0
|
||||
static unsigned char DefaultAACHeader[] = {0xff,0xf1,0x50,0x80,0x00,0x1f,0xfc};
|
||||
static unsigned char DefaultAACHeader[] = {0xff, 0xf1, 0x50, 0x80, 0x00, 0x1f, 0xfc};
|
||||
#endif
|
||||
|
||||
class WriterAAC : public Writer
|
||||
@@ -109,7 +110,7 @@ void WriterAAC::Init(int _fd, AVStream *_stream, Player *_player)
|
||||
printf("stream->codec->extradata_size %d\n", stream->codec->extradata_size);
|
||||
Hexdump(stream->codec->extradata, stream->codec->extradata_size);
|
||||
#endif
|
||||
unsigned int object_type = 2; // LC
|
||||
unsigned int object_type = 2; // LC
|
||||
unsigned int sample_index = aac_get_sample_rate_index(stream->codec->sample_rate);
|
||||
unsigned int chan_config = stream->codec->channels;
|
||||
if (stream->codec->extradata_size >= 2)
|
||||
@@ -123,7 +124,7 @@ void WriterAAC::Init(int _fd, AVStream *_stream, Player *_player)
|
||||
printf("aac sample_index %d\n", sample_index);
|
||||
printf("aac chan_config %d\n", chan_config);
|
||||
#endif
|
||||
object_type -= 1; // Cause of ADTS
|
||||
object_type -= 1; // Cause of ADTS
|
||||
aacbuflen = AAC_HEADER_LENGTH;
|
||||
aacbuf[0] = 0xFF;
|
||||
aacbuf[1] = 0xF1;
|
||||
@@ -147,7 +148,7 @@ bool WriterAAC::Write(AVPacket *packet, int64_t pts)
|
||||
uint8_t PesHeader[PES_MAX_HEADER_SIZE];
|
||||
uint8_t ExtraData[AAC_HEADER_LENGTH];
|
||||
|
||||
for (int pos = 0; pos < packet->size + AAC_HEADER_LENGTH; )
|
||||
for (int pos = 0; pos < packet->size + AAC_HEADER_LENGTH;)
|
||||
{
|
||||
int PacketLength = std::min(packet->size - pos + AAC_HEADER_LENGTH, MAX_PES_PACKET_SIZE);
|
||||
|
||||
@@ -182,4 +183,4 @@ WriterAAC::WriterAAC()
|
||||
Register(this, AV_CODEC_ID_AAC, AUDIO_ENCODING_AAC);
|
||||
}
|
||||
|
||||
static WriterAAC writer_aac __attribute__ ((init_priority (300)));
|
||||
static WriterAAC writer_aac __attribute__((init_priority(300)));
|
||||
|
@@ -46,7 +46,8 @@ bool WriterAC3::Write(AVPacket *packet, int64_t pts)
|
||||
|
||||
uint8_t PesHeader[PES_MAX_HEADER_SIZE];
|
||||
|
||||
for (int pos = 0; pos < packet->size; ) {
|
||||
for (int pos = 0; pos < packet->size;)
|
||||
{
|
||||
int PacketLength = std::min(packet->size - pos, MAX_PES_PACKET_SIZE);
|
||||
struct iovec iov[2];
|
||||
iov[0].iov_base = PesHeader;
|
||||
@@ -69,4 +70,4 @@ WriterAC3::WriterAC3()
|
||||
Register(this, AV_CODEC_ID_EAC3, AUDIO_ENCODING_AC3);
|
||||
}
|
||||
|
||||
static WriterAC3 writer_ac3 __attribute__ ((init_priority (300)));
|
||||
static WriterAC3 writer_ac3 __attribute__((init_priority(300)));
|
||||
|
@@ -58,7 +58,7 @@ bool WriterDIVX::Write(AVPacket *packet, int64_t pts)
|
||||
return false;
|
||||
|
||||
uint8_t PesHeader[PES_MAX_HEADER_SIZE];
|
||||
uint8_t FakeHeaders[64] = { 0 }; // 64bytes should be enough to make the fake headers
|
||||
uint8_t FakeHeaders[64] = { 0 }; // 64bytes should be enough to make the fake headers
|
||||
unsigned int FakeHeaderLength;
|
||||
uint8_t Version = 5;
|
||||
unsigned int FakeStartCode = (Version << 8) | PES_VERSION_FAKE_START_CODE;
|
||||
@@ -72,10 +72,10 @@ bool WriterDIVX::Write(AVPacket *packet, int64_t pts)
|
||||
PutBits(&ld, 0x0, 8);
|
||||
PutBits(&ld, 0x0, 8);
|
||||
*/
|
||||
PutBits(&ld, 0x1b0, 32); // startcode
|
||||
PutBits(&ld, 0, 8); // profile = reserved
|
||||
PutBits(&ld, 0x1b2, 32); // startcode (user data)
|
||||
PutBits(&ld, 0x53545443, 32); // STTC - an embedded ST timecode from an avi file
|
||||
PutBits(&ld, 0x1b0, 32); // startcode
|
||||
PutBits(&ld, 0, 8); // profile = reserved
|
||||
PutBits(&ld, 0x1b2, 32); // startcode (user data)
|
||||
PutBits(&ld, 0x53545443, 32); // STTC - an embedded ST timecode from an avi file
|
||||
PutBits(&ld, usecPerFrame, 32); // microseconds per frame
|
||||
FlushBits(&ld);
|
||||
|
||||
@@ -88,7 +88,8 @@ bool WriterDIVX::Write(AVPacket *packet, int64_t pts)
|
||||
iov[ic].iov_base = FakeHeaders;
|
||||
iov[ic++].iov_len = FakeHeaderLength;
|
||||
|
||||
if (initialHeader) {
|
||||
if (initialHeader)
|
||||
{
|
||||
iov[ic].iov_base = get_codecpar(stream)->extradata;
|
||||
iov[ic++].iov_len = get_codecpar(stream)->extradata_size;
|
||||
initialHeader = false;
|
||||
@@ -107,4 +108,4 @@ WriterDIVX::WriterDIVX()
|
||||
Register(this, AV_CODEC_ID_MSMPEG4V3, VIDEO_ENCODING_MPEG4P2);
|
||||
}
|
||||
|
||||
static WriterDIVX writer_divx __attribute__ ((init_priority (300)));
|
||||
static WriterDIVX writer_divx __attribute__((init_priority(300)));
|
||||
|
@@ -30,8 +30,8 @@
|
||||
#include "pes.h"
|
||||
#include "writer.h"
|
||||
|
||||
#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_PRIVATE_HEADER_SIZE 16 // consider maximum private header size.
|
||||
#define PES_AUDIO_HEADER_SIZE (32 + PES_AUDIO_PRIVATE_HEADER_SIZE)
|
||||
|
||||
class WriterDTS : public Writer
|
||||
{
|
||||
@@ -53,7 +53,8 @@ bool WriterDTS::Write(AVPacket *packet, int64_t pts)
|
||||
memcpy(Data, packet->data, packet->size);
|
||||
|
||||
/* 16-bit byte swap all data before injecting it */
|
||||
for (i = 0; i < packet->size; i += 2) {
|
||||
for (i = 0; i < packet->size; i += 2)
|
||||
{
|
||||
uint8_t Tmp = Data[i];
|
||||
Data[i] = Data[i + 1];
|
||||
Data[i + 1] = Tmp;
|
||||
@@ -63,7 +64,7 @@ bool WriterDTS::Write(AVPacket *packet, int64_t pts)
|
||||
struct iovec iov[2];
|
||||
|
||||
iov[0].iov_base = PesHeader;
|
||||
iov[0].iov_len = InsertPesHeader(PesHeader, packet->size, MPEG_AUDIO_PES_START_CODE /*PRIVATE_STREAM_1_PES_START_CODE */ , 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
|
||||
@@ -79,4 +80,4 @@ WriterDTS::WriterDTS()
|
||||
Register(this, AV_CODEC_ID_DTS, AUDIO_ENCODING_DTS);
|
||||
}
|
||||
|
||||
static WriterDTS writer_dts __attribute__ ((init_priority (300)));
|
||||
static WriterDTS writer_dts __attribute__((init_priority(300)));
|
||||
|
@@ -71,4 +71,4 @@ WriterH263::WriterH263()
|
||||
Register(this, AV_CODEC_ID_FLV1, VIDEO_ENCODING_FLV1);
|
||||
}
|
||||
|
||||
static WriterH263 writer_h263 __attribute__ ((init_priority (300)));
|
||||
static WriterH263 writer_h263 __attribute__((init_priority(300)));
|
||||
|
@@ -30,17 +30,18 @@
|
||||
#include "pes.h"
|
||||
#include "writer.h"
|
||||
|
||||
#define NALU_TYPE_PLAYER2_CONTAINER_PARAMETERS 24 // Reference: player/standards/h264.h
|
||||
#define CONTAINER_PARAMETERS_VERSION 0x00
|
||||
#define NALU_TYPE_PLAYER2_CONTAINER_PARAMETERS 24 // Reference: player/standards/h264.h
|
||||
#define CONTAINER_PARAMETERS_VERSION 0x00
|
||||
|
||||
typedef struct avcC_s {
|
||||
uint8_t Version; // configurationVersion
|
||||
uint8_t Profile; // AVCProfileIndication
|
||||
uint8_t Compatibility; // profile_compatibility
|
||||
uint8_t Level; // AVCLevelIndication
|
||||
uint8_t NalLengthMinusOne; // held in bottom two bits
|
||||
uint8_t NumParamSets; // held in bottom 5 bits
|
||||
uint8_t Params[1]; // {length,params}{length,params}...sequence then picture
|
||||
typedef struct avcC_s
|
||||
{
|
||||
uint8_t Version; // configurationVersion
|
||||
uint8_t Profile; // AVCProfileIndication
|
||||
uint8_t Compatibility; // profile_compatibility
|
||||
uint8_t Level; // AVCLevelIndication
|
||||
uint8_t NalLengthMinusOne; // held in bottom two bits
|
||||
uint8_t NumParamSets; // held in bottom 5 bits
|
||||
uint8_t Params[1]; // {length,params}{length,params}...sequence then picture
|
||||
} avcC_t;
|
||||
|
||||
class WriterH264 : public Writer
|
||||
@@ -74,14 +75,16 @@ bool WriterH264::Write(AVPacket *packet, int64_t pts)
|
||||
uint8_t *d = packet->data;
|
||||
|
||||
// byte-stream format
|
||||
if ((packet->size > 3) && ( (d[0] == 0x00 && d[1] == 0x00 && d[2] == 0x00 && d[3] == 0x01) // first NAL unit
|
||||
|| (d[0] == 0xff && d[1] == 0xff && d[2] == 0xff && d[3] == 0xff) // FIXME, needed???
|
||||
)) {
|
||||
if ((packet->size > 3) && ((d[0] == 0x00 && d[1] == 0x00 && d[2] == 0x00 && d[3] == 0x01) // first NAL unit
|
||||
|| (d[0] == 0xff && d[1] == 0xff && d[2] == 0xff && d[3] == 0xff) // FIXME, needed???
|
||||
))
|
||||
{
|
||||
unsigned int FakeStartCode = /* (call->Version << 8) | */ PES_VERSION_FAKE_START_CODE;
|
||||
int ic = 0;
|
||||
iov[ic++].iov_base = PesHeader;
|
||||
unsigned int len = 0;
|
||||
if (initialHeader) {
|
||||
if (initialHeader)
|
||||
{
|
||||
initialHeader = false;
|
||||
iov[ic].iov_base = get_codecpar(stream)->extradata;
|
||||
iov[ic++].iov_len = get_codecpar(stream)->extradata_size;
|
||||
@@ -103,10 +106,12 @@ bool WriterH264::Write(AVPacket *packet, int64_t pts)
|
||||
}
|
||||
|
||||
// convert NAL units without sync byte sequence to byte-stream format
|
||||
if (initialHeader) {
|
||||
if (initialHeader)
|
||||
{
|
||||
avcC_t *avcCHeader = (avcC_t *) get_codecpar(stream)->extradata;
|
||||
|
||||
if (!avcCHeader) {
|
||||
if (!avcCHeader)
|
||||
{
|
||||
fprintf(stderr, "stream->codec->extradata == NULL\n");
|
||||
return false;
|
||||
}
|
||||
@@ -122,35 +127,35 @@ bool WriterH264::Write(AVPacket *packet, int64_t pts)
|
||||
|
||||
uint8_t Header[20];
|
||||
unsigned int len = 0;
|
||||
Header[len++] = 0x00; // Start code, 00 00 00 01 for first NAL unit
|
||||
Header[len++] = 0x00; // Start code, 00 00 00 01 for first NAL unit
|
||||
Header[len++] = 0x00;
|
||||
Header[len++] = 0x00;
|
||||
Header[len++] = 0x01;
|
||||
Header[len++] = NALU_TYPE_PLAYER2_CONTAINER_PARAMETERS; // NAL unit header
|
||||
// Container message version - changes when/if we vary the format of the message
|
||||
Header[len++] = CONTAINER_PARAMETERS_VERSION;
|
||||
Header[len++] = 0xff; // marker bits
|
||||
Header[len++] = 0xff; // marker bits
|
||||
|
||||
#if 0
|
||||
#if 0
|
||||
if (FrameRate == 0xffffffff)
|
||||
FrameRate = (TimeScale > 1000) ? 1001 : 1;
|
||||
#endif
|
||||
#endif
|
||||
|
||||
Header[len++] = (TimeScale >> 24) & 0xff; // Output the timescale
|
||||
Header[len++] = (TimeScale >> 24) & 0xff; // Output the timescale
|
||||
Header[len++] = (TimeScale >> 16) & 0xff;
|
||||
Header[len++] = 0xff; // marker bits
|
||||
Header[len++] = 0xff; // marker bits
|
||||
Header[len++] = (TimeScale >> 8) & 0xff;
|
||||
Header[len++] = (TimeScale ) & 0xff;
|
||||
Header[len++] = 0xff; // marker bits
|
||||
Header[len++] = (TimeScale) & 0xff;
|
||||
Header[len++] = 0xff; // marker bits
|
||||
|
||||
Header[len++] = (FrameRate >> 24) & 0xff; // Output frame period (should be: time delta)
|
||||
Header[len++] = (FrameRate >> 24) & 0xff; // Output frame period (should be: time delta)
|
||||
Header[len++] = (FrameRate >> 16) & 0xff;
|
||||
Header[len++] = 0xff; // marker bits
|
||||
Header[len++] = 0xff; // marker bits
|
||||
Header[len++] = (FrameRate >> 8) & 0xff;
|
||||
Header[len++] = (FrameRate ) & 0xff;
|
||||
Header[len++] = 0xff; // marker bits
|
||||
Header[len++] = (FrameRate) & 0xff;
|
||||
Header[len++] = 0xff; // marker bits
|
||||
|
||||
Header[len++] = 0x80; // Rsbp trailing bits
|
||||
Header[len++] = 0x80; // Rsbp trailing bits
|
||||
|
||||
int ic = 0;
|
||||
iov[ic].iov_base = PesHeader;
|
||||
@@ -169,7 +174,8 @@ bool WriterH264::Write(AVPacket *packet, int64_t pts)
|
||||
|
||||
// sequence parameter set
|
||||
unsigned int ParamSets = avcCHeader->NumParamSets & 0x1f;
|
||||
for (unsigned int i = 0; i < ParamSets; i++) {
|
||||
for (unsigned int i = 0; i < ParamSets; i++)
|
||||
{
|
||||
unsigned int PsLength = (avcCHeader->Params[ParamOffset] << 8) | avcCHeader->Params[ParamOffset + 1];
|
||||
|
||||
iov[ic].iov_base = (uint8_t *) "\0\0\0\1";
|
||||
@@ -184,7 +190,8 @@ bool WriterH264::Write(AVPacket *packet, int64_t pts)
|
||||
// picture parameter set
|
||||
ParamSets = avcCHeader->Params[ParamOffset++];
|
||||
|
||||
for (unsigned int i = 0; i < ParamSets; i++) {
|
||||
for (unsigned int i = 0; i < ParamSets; i++)
|
||||
{
|
||||
unsigned int PsLength = (avcCHeader->Params[ParamOffset] << 8) | avcCHeader->Params[ParamOffset + 1];
|
||||
|
||||
iov[ic].iov_base = (uint8_t *) "\0\0\0\1";
|
||||
@@ -205,9 +212,11 @@ bool WriterH264::Write(AVPacket *packet, int64_t pts)
|
||||
}
|
||||
|
||||
uint8_t *de = d + packet->size;
|
||||
do {
|
||||
do
|
||||
{
|
||||
unsigned int len = 0;
|
||||
switch (NalLengthBytes) {
|
||||
switch (NalLengthBytes)
|
||||
{
|
||||
case 4:
|
||||
len = *d;
|
||||
d++;
|
||||
@@ -225,8 +234,9 @@ bool WriterH264::Write(AVPacket *packet, int64_t pts)
|
||||
d++;
|
||||
}
|
||||
|
||||
if (d + len > de) {
|
||||
fprintf(stderr, "NAL length past end of buffer - size %u frame offset %d left %d\n", len, (int) (d - packet->data), (int) (de - d));
|
||||
if (d + len > de)
|
||||
{
|
||||
fprintf(stderr, "NAL length past end of buffer - size %u frame offset %d left %d\n", len, (int)(d - packet->data), (int)(de - d));
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -245,7 +255,8 @@ bool WriterH264::Write(AVPacket *packet, int64_t pts)
|
||||
d += len;
|
||||
pts = INVALID_PTS_VALUE;
|
||||
|
||||
} while (d < de);
|
||||
}
|
||||
while (d < de);
|
||||
|
||||
return true;
|
||||
}
|
||||
@@ -255,4 +266,4 @@ WriterH264::WriterH264()
|
||||
Register(this, AV_CODEC_ID_H264, VIDEO_ENCODING_H264);
|
||||
}
|
||||
|
||||
static WriterH264 writerh264 __attribute__ ((init_priority (300)));
|
||||
static WriterH264 writerh264 __attribute__((init_priority(300)));
|
||||
|
@@ -28,7 +28,7 @@
|
||||
|
||||
#include "misc.h"
|
||||
|
||||
void PutBits(BitPacker_t * ld, unsigned int code, unsigned int length)
|
||||
void PutBits(BitPacker_t *ld, unsigned int code, unsigned int length)
|
||||
{
|
||||
unsigned int bit_buf;
|
||||
unsigned int bit_left;
|
||||
@@ -39,20 +39,23 @@ void PutBits(BitPacker_t * ld, unsigned int code, unsigned int length)
|
||||
#ifdef DEBUG_PUTBITS
|
||||
if (ld->debug)
|
||||
dprintf("code = %d, length = %d, bit_buf = 0x%x, bit_left = %d\n",
|
||||
code, length, bit_buf, bit_left);
|
||||
code, length, bit_buf, bit_left);
|
||||
#endif
|
||||
|
||||
if (length < bit_left) {
|
||||
if (length < bit_left)
|
||||
{
|
||||
/* fits into current buffer */
|
||||
bit_buf = (bit_buf << length) | code;
|
||||
bit_left -= length;
|
||||
} else {
|
||||
}
|
||||
else
|
||||
{
|
||||
/* doesn't fit */
|
||||
bit_buf <<= bit_left;
|
||||
bit_buf |= code >> (length - bit_left);
|
||||
ld->Ptr[0] = (uint8_t) (bit_buf >> 24);
|
||||
ld->Ptr[1] = (uint8_t) (bit_buf >> 16);
|
||||
ld->Ptr[2] = (uint8_t) (bit_buf >> 8);
|
||||
ld->Ptr[0] = (uint8_t)(bit_buf >> 24);
|
||||
ld->Ptr[1] = (uint8_t)(bit_buf >> 16);
|
||||
ld->Ptr[2] = (uint8_t)(bit_buf >> 8);
|
||||
ld->Ptr[3] = (uint8_t) bit_buf;
|
||||
ld->Ptr += 4;
|
||||
length -= bit_left;
|
||||
@@ -71,10 +74,11 @@ void PutBits(BitPacker_t * ld, unsigned int code, unsigned int length)
|
||||
ld->Remaining = bit_left;
|
||||
}
|
||||
|
||||
void FlushBits(BitPacker_t * ld)
|
||||
void FlushBits(BitPacker_t *ld)
|
||||
{
|
||||
ld->BitBuffer <<= ld->Remaining;
|
||||
while (ld->Remaining < 32) {
|
||||
while (ld->Remaining < 32)
|
||||
{
|
||||
#ifdef DEBUG_PUTBITS
|
||||
if (ld->debug)
|
||||
dprintf("flushing 0x%2.2x\n", ld->BitBuffer >> 24);
|
||||
|
@@ -46,7 +46,8 @@ bool WriterMP3::Write(AVPacket *packet, int64_t pts)
|
||||
|
||||
uint8_t PesHeader[PES_MAX_HEADER_SIZE];
|
||||
|
||||
for (int pos = 0; pos < packet->size; ) {
|
||||
for (int pos = 0; pos < packet->size;)
|
||||
{
|
||||
int PacketLength = std::min(packet->size - pos, MAX_PES_PACKET_SIZE);
|
||||
struct iovec iov[2];
|
||||
iov[0].iov_base = PesHeader;
|
||||
@@ -71,4 +72,4 @@ WriterMP3::WriterMP3()
|
||||
Register(this, AV_CODEC_ID_FLAC, AUDIO_ENCODING_LPCM);
|
||||
}
|
||||
|
||||
static WriterMP3 writer_mp3 __attribute__ ((init_priority (300)));
|
||||
static WriterMP3 writer_mp3 __attribute__((init_priority(300)));
|
||||
|
@@ -46,7 +46,8 @@ bool WriterMPEG2::Write(AVPacket *packet, int64_t pts)
|
||||
|
||||
uint8_t PesHeader[PES_MAX_HEADER_SIZE];
|
||||
|
||||
for (int pos = 0; pos < packet->size; ) {
|
||||
for (int pos = 0; pos < packet->size;)
|
||||
{
|
||||
int PacketLength = std::min(packet->size - pos, MAX_PES_PACKET_SIZE);
|
||||
struct iovec iov[2];
|
||||
iov[0].iov_base = PesHeader;
|
||||
@@ -68,4 +69,4 @@ WriterMPEG2::WriterMPEG2()
|
||||
Register(this, AV_CODEC_ID_MPEG2TS, VIDEO_ENCODING_AUTO);
|
||||
}
|
||||
|
||||
static WriterMPEG2 writer_mpeg2 __attribute__ ((init_priority (300)));
|
||||
static WriterMPEG2 writer_mpeg2 __attribute__((init_priority(300)));
|
||||
|
@@ -43,18 +43,19 @@ extern "C" {
|
||||
}
|
||||
|
||||
// reference: search for TypeLpcmDVDAudio in player/frame_parser/frame_parser_audio_lpcm.cpp
|
||||
static const uint8_t clpcm_prv[14] = {
|
||||
0xA0, //sub_stream_id
|
||||
0, 0, //resvd and UPC_EAN_ISRC stuff, unused
|
||||
0x0A, //private header length
|
||||
0, 9, //first_access_unit_pointer
|
||||
0x00, //emph,rsvd,stereo,downmix
|
||||
0x0F, //quantisation word length 1,2
|
||||
0x0F, //audio sampling freqency 1,2
|
||||
0, //resvd, multi channel type
|
||||
0, //bit shift on channel GR2, assignment
|
||||
0x80, //dynamic range control
|
||||
0, 0 //resvd for copyright management
|
||||
static const uint8_t clpcm_prv[14] =
|
||||
{
|
||||
0xA0, //sub_stream_id
|
||||
0, 0, //resvd and UPC_EAN_ISRC stuff, unused
|
||||
0x0A, //private header length
|
||||
0, 9, //first_access_unit_pointer
|
||||
0x00, //emph,rsvd,stereo,downmix
|
||||
0x0F, //quantisation word length 1,2
|
||||
0x0F, //audio sampling freqency 1,2
|
||||
0, //resvd, multi channel type
|
||||
0, //bit shift on channel GR2, assignment
|
||||
0x80, //dynamic range control
|
||||
0, 0 //resvd for copyright management
|
||||
};
|
||||
|
||||
class WriterPCM : public Writer
|
||||
@@ -98,7 +99,8 @@ bool WriterPCM::prepareClipPlay()
|
||||
memcpy(lpcm_prv, clpcm_prv, sizeof(lpcm_prv));
|
||||
|
||||
// figure out size of subframe and set up sample rate
|
||||
switch (uSampleRate) {
|
||||
switch (uSampleRate)
|
||||
{
|
||||
case 48000:
|
||||
SubFrameLen = 40;
|
||||
break;
|
||||
@@ -136,7 +138,8 @@ bool WriterPCM::prepareClipPlay()
|
||||
//set number of channels
|
||||
lpcm_prv[10] = uNoOfChannels - 1;
|
||||
|
||||
switch (uBitsPerSample) {
|
||||
switch (uBitsPerSample)
|
||||
{
|
||||
case 24:
|
||||
lpcm_prv[7] |= 0x20;
|
||||
case 16:
|
||||
@@ -154,7 +157,8 @@ bool WriterPCM::writePCM(int64_t Pts, uint8_t *data, unsigned int size)
|
||||
bool res = true;
|
||||
uint8_t PesHeader[PES_MAX_HEADER_SIZE];
|
||||
|
||||
if (initialHeader) {
|
||||
if (initialHeader)
|
||||
{
|
||||
initialHeader = false;
|
||||
prepareClipPlay();
|
||||
ioctl(fd, AUDIO_CLEAR_BUFFER, NULL);
|
||||
@@ -162,7 +166,8 @@ bool WriterPCM::writePCM(int64_t Pts, uint8_t *data, unsigned int size)
|
||||
|
||||
size += breakBufferFillSize;
|
||||
|
||||
while (size >= SubFrameLen) {
|
||||
while (size >= SubFrameLen)
|
||||
{
|
||||
if (breakBufferFillSize)
|
||||
memcpy(injectBuffer, breakBuffer, breakBufferFillSize);
|
||||
memcpy(injectBuffer + breakBufferFillSize, data, SubFrameLen - breakBufferFillSize);
|
||||
@@ -171,17 +176,22 @@ bool WriterPCM::writePCM(int64_t Pts, uint8_t *data, unsigned int size)
|
||||
breakBufferFillSize = 0;
|
||||
|
||||
//write the PCM data
|
||||
if (uBitsPerSample == 16) {
|
||||
for (unsigned int n = 0; n < SubFrameLen; n += 2) {
|
||||
if (uBitsPerSample == 16)
|
||||
{
|
||||
for (unsigned int n = 0; n < SubFrameLen; n += 2)
|
||||
{
|
||||
uint8_t tmp = injectBuffer[n];
|
||||
injectBuffer[n] = injectBuffer[n + 1];
|
||||
injectBuffer[n + 1] = tmp;
|
||||
}
|
||||
} else {
|
||||
}
|
||||
else
|
||||
{
|
||||
// 0 1 2 3 4 5 6 7 8 9 10 11
|
||||
// A1c A1b A1a B1c B1b B1a A2c A2b A2a B2c B2b B2a
|
||||
// to A1a A1b B1a B1b A2a A2b B2a B2b A1c B1c A2c B2c
|
||||
for (unsigned int n = 0; n < SubFrameLen; n += 12) {
|
||||
for (unsigned int n = 0; n < SubFrameLen; n += 12)
|
||||
{
|
||||
uint8_t t, *p = injectBuffer + n;
|
||||
t = p[0];
|
||||
p[0] = p[2];
|
||||
@@ -207,12 +217,14 @@ bool WriterPCM::writePCM(int64_t Pts, uint8_t *data, unsigned int size)
|
||||
iov[2].iov_len = SubFrameLen;
|
||||
iov[0].iov_len = InsertPesHeader(PesHeader, iov[1].iov_len + iov[2].iov_len, PCM_PES_START_CODE, Pts, 0);
|
||||
int len = writev(fd, iov, 3);
|
||||
if (len < 0) {
|
||||
if (len < 0)
|
||||
{
|
||||
res = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (size && res) {
|
||||
if (size && res)
|
||||
{
|
||||
breakBufferFillSize = size;
|
||||
memcpy(breakBuffer, data, size);
|
||||
}
|
||||
@@ -231,58 +243,67 @@ void WriterPCM::Init(int _fd, AVStream *_stream, Player *_player)
|
||||
|
||||
bool WriterPCM::Write(AVPacket *packet, int64_t pts)
|
||||
{
|
||||
if (!packet) {
|
||||
if (!packet)
|
||||
{
|
||||
restart_audio_resampling = true;
|
||||
return true;
|
||||
}
|
||||
|
||||
AVCodecContext *c = player->input.GetCodecContext((unsigned int)stream->index);
|
||||
|
||||
if (restart_audio_resampling) {
|
||||
if (restart_audio_resampling)
|
||||
{
|
||||
restart_audio_resampling = false;
|
||||
initialHeader = true;
|
||||
|
||||
if (swr) {
|
||||
if (swr)
|
||||
{
|
||||
swr_free(&swr);
|
||||
swr = NULL;
|
||||
}
|
||||
if (decoded_frame) {
|
||||
if (decoded_frame)
|
||||
{
|
||||
av_frame_free(&decoded_frame);
|
||||
decoded_frame = NULL;
|
||||
}
|
||||
|
||||
#if LIBAVFORMAT_VERSION_INT < AV_VERSION_INT(57,25,101)
|
||||
AVCodec *codec = avcodec_find_decoder(c->codec_id);
|
||||
if (!codec) {
|
||||
if (!codec)
|
||||
{
|
||||
fprintf(stderr, "%s %d: avcodec_find_decoder(%llx)\n", __func__, __LINE__, (unsigned long long) c->codec_id);
|
||||
return false;
|
||||
}
|
||||
avcodec_close(c);
|
||||
if (avcodec_open2(c, codec, NULL)) {
|
||||
if (avcodec_open2(c, codec, NULL))
|
||||
{
|
||||
fprintf(stderr, "%s %d: avcodec_open2 failed\n", __func__, __LINE__);
|
||||
return false;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
if (!swr) {
|
||||
if (!swr)
|
||||
{
|
||||
int in_rate = c->sample_rate;
|
||||
// rates in descending order
|
||||
int rates[] = {192000, 176400, 96000, 88200, 48000, 44100, 0};
|
||||
int i = 0;
|
||||
// find the next equal or smallest rate
|
||||
while (rates[i] && in_rate < rates[i])
|
||||
i++;
|
||||
i++;
|
||||
out_sample_rate = rates[i] ? rates[i] : 44100;
|
||||
out_channels = c->channels;
|
||||
if (c->channel_layout == 0) {
|
||||
if (c->channel_layout == 0)
|
||||
{
|
||||
// FIXME -- need to guess, looks pretty much like a bug in the FFMPEG WMA decoder
|
||||
c->channel_layout = AV_CH_LAYOUT_STEREO;
|
||||
}
|
||||
|
||||
out_channel_layout = c->channel_layout;
|
||||
// player2 won't play mono
|
||||
if (out_channel_layout == AV_CH_LAYOUT_MONO) {
|
||||
if (out_channel_layout == AV_CH_LAYOUT_MONO)
|
||||
{
|
||||
out_channel_layout = AV_CH_LAYOUT_STEREO;
|
||||
out_channels = 2;
|
||||
}
|
||||
@@ -292,7 +313,8 @@ bool WriterPCM::Write(AVPacket *packet, int64_t pts)
|
||||
uBitsPerSample = 16;
|
||||
|
||||
swr = swr_alloc();
|
||||
if (!swr) {
|
||||
if (!swr)
|
||||
{
|
||||
fprintf(stderr, "%s %d: swr_alloc failed\n", __func__, __LINE__);
|
||||
return false;
|
||||
}
|
||||
@@ -304,31 +326,37 @@ bool WriterPCM::Write(AVPacket *packet, int64_t pts)
|
||||
av_opt_set_sample_fmt(swr, "out_sample_fmt", AV_SAMPLE_FMT_S16, 0);
|
||||
|
||||
int e = swr_init(swr);
|
||||
if (e < 0) {
|
||||
if (e < 0)
|
||||
{
|
||||
fprintf(stderr, "swr_init: %d (icl=%d ocl=%d isr=%d osr=%d isf=%d osf=%d)\n",
|
||||
-e, (int) c->channel_layout,
|
||||
(int) out_channel_layout, c->sample_rate, out_sample_rate, c->sample_fmt, AV_SAMPLE_FMT_S16);
|
||||
-e, (int) c->channel_layout,
|
||||
(int) out_channel_layout, c->sample_rate, out_sample_rate, c->sample_fmt, AV_SAMPLE_FMT_S16);
|
||||
restart_audio_resampling = true;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
unsigned int packet_size = packet->size;
|
||||
while (packet_size > 0 || (!packet_size && !packet->data)) {
|
||||
while (packet_size > 0 || (!packet_size && !packet->data))
|
||||
{
|
||||
|
||||
if (!decoded_frame) {
|
||||
if (!(decoded_frame = av_frame_alloc())) {
|
||||
if (!decoded_frame)
|
||||
{
|
||||
if (!(decoded_frame = av_frame_alloc()))
|
||||
{
|
||||
fprintf(stderr, "out of memory\n");
|
||||
exit(1);
|
||||
}
|
||||
} else
|
||||
}
|
||||
else
|
||||
av_frame_unref(decoded_frame);
|
||||
|
||||
#if LIBAVCODEC_VERSION_INT < AV_VERSION_INT(57,37,100)
|
||||
int got_frame = 0;
|
||||
|
||||
int len = avcodec_decode_audio4(c, decoded_frame, &got_frame, packet);
|
||||
if (len < 0) {
|
||||
if (len < 0)
|
||||
{
|
||||
restart_audio_resampling = true;
|
||||
break;
|
||||
}
|
||||
@@ -336,35 +364,43 @@ bool WriterPCM::Write(AVPacket *packet, int64_t pts)
|
||||
if (packet->data)
|
||||
packet_size -= len;
|
||||
|
||||
if (!got_frame) {
|
||||
if (!got_frame)
|
||||
{
|
||||
if (!packet->data || !packet_size)
|
||||
break;
|
||||
continue;
|
||||
}
|
||||
#else
|
||||
int ret = avcodec_send_packet(c, packet);
|
||||
if (ret < 0) {
|
||||
if (ret != AVERROR(EAGAIN) && ret != AVERROR_EOF) {
|
||||
restart_audio_resampling = true;
|
||||
break;
|
||||
}
|
||||
int ret = avcodec_send_packet(c, packet);
|
||||
if (ret < 0)
|
||||
{
|
||||
if (ret != AVERROR(EAGAIN) && ret != AVERROR_EOF)
|
||||
{
|
||||
restart_audio_resampling = true;
|
||||
break;
|
||||
}
|
||||
if (ret >= 0) {
|
||||
packet_size = 0;
|
||||
}
|
||||
if (ret >= 0)
|
||||
{
|
||||
packet_size = 0;
|
||||
}
|
||||
ret = avcodec_receive_frame(c, decoded_frame);
|
||||
if (ret < 0)
|
||||
{
|
||||
if (ret == AVERROR_EOF)
|
||||
{
|
||||
restart_audio_resampling = true;
|
||||
break;
|
||||
}
|
||||
ret = avcodec_receive_frame(c, decoded_frame);
|
||||
if (ret < 0) {
|
||||
if (ret == AVERROR_EOF) {
|
||||
restart_audio_resampling = true;
|
||||
break;
|
||||
}
|
||||
if (ret != AVERROR(EAGAIN)) {
|
||||
break;
|
||||
}
|
||||
else {
|
||||
continue;
|
||||
}
|
||||
if (ret != AVERROR(EAGAIN))
|
||||
{
|
||||
break;
|
||||
}
|
||||
else
|
||||
{
|
||||
continue;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
#if (LIBAVUTIL_VERSION_MAJOR < 54)
|
||||
@@ -375,11 +411,13 @@ bool WriterPCM::Write(AVPacket *packet, int64_t pts)
|
||||
|
||||
int in_samples = decoded_frame->nb_samples;
|
||||
int out_samples = av_rescale_rnd(swr_get_delay(swr, c->sample_rate) + in_samples, out_sample_rate, c->sample_rate, AV_ROUND_UP);
|
||||
if (out_samples > out_samples_max) {
|
||||
if (out_samples > out_samples_max)
|
||||
{
|
||||
if (output)
|
||||
av_freep(&output);
|
||||
int e = av_samples_alloc(&output, NULL, out_channels, out_samples, AV_SAMPLE_FMT_S16, 1);
|
||||
if (e < 0) {
|
||||
if (e < 0)
|
||||
{
|
||||
fprintf(stderr, "av_samples_alloc: %d\n", -e);
|
||||
break;
|
||||
}
|
||||
@@ -388,7 +426,8 @@ bool WriterPCM::Write(AVPacket *packet, int64_t pts)
|
||||
|
||||
out_samples = swr_convert(swr, &output, out_samples, (const uint8_t **) &decoded_frame->data[0], in_samples);
|
||||
|
||||
if (!writePCM(pts, output, out_samples * sizeof(short) * out_channels)) {
|
||||
if (!writePCM(pts, output, out_samples * sizeof(short) * out_channels))
|
||||
{
|
||||
restart_audio_resampling = true;
|
||||
break;
|
||||
}
|
||||
@@ -409,4 +448,4 @@ WriterPCM::WriterPCM()
|
||||
Register(this, AV_CODEC_ID_INJECTPCM, AUDIO_ENCODING_LPCMA);
|
||||
}
|
||||
|
||||
static WriterPCM writer_pcm __attribute__ ((init_priority (300)));
|
||||
static WriterPCM writer_pcm __attribute__((init_priority(300)));
|
||||
|
@@ -53,44 +53,45 @@ int InsertPesHeader(uint8_t *data, int size, uint8_t stream_id, int64_t pts, int
|
||||
{
|
||||
BitPacker_t ld2 = { data, 0, 32 };
|
||||
|
||||
/* if (size > MAX_PES_PACKET_SIZE)
|
||||
size = 0; // unbounded */
|
||||
/* if (size > MAX_PES_PACKET_SIZE)
|
||||
size = 0; // unbounded */
|
||||
|
||||
PutBits(&ld2, 0x0, 8);
|
||||
PutBits(&ld2, 0x0, 8);
|
||||
PutBits(&ld2, 0x1, 8); // Start Code
|
||||
PutBits(&ld2, stream_id, 8); // Stream_id = Audio Stream
|
||||
PutBits(&ld2, 0x1, 8); // Start Code
|
||||
PutBits(&ld2, stream_id, 8); // Stream_id = Audio Stream
|
||||
//4
|
||||
PutBits(&ld2, size + 3 + (pts != INVALID_PTS_VALUE ? 5 : 0) + (pic_start_code ? (5) : 0), 16); // PES_packet_length
|
||||
PutBits(&ld2, size + 3 + (pts != INVALID_PTS_VALUE ? 5 : 0) + (pic_start_code ? (5) : 0), 16); // PES_packet_length
|
||||
//6 = 4+2
|
||||
PutBits(&ld2, 0x2, 2); // 10
|
||||
PutBits(&ld2, 0x0, 2); // PES_Scrambling_control
|
||||
PutBits(&ld2, 0x0, 1); // PES_Priority
|
||||
PutBits(&ld2, 0x0, 1); // data_alignment_indicator
|
||||
PutBits(&ld2, 0x0, 1); // Copyright
|
||||
PutBits(&ld2, 0x0, 1); // Original or Copy
|
||||
PutBits(&ld2, 0x2, 2); // 10
|
||||
PutBits(&ld2, 0x0, 2); // PES_Scrambling_control
|
||||
PutBits(&ld2, 0x0, 1); // PES_Priority
|
||||
PutBits(&ld2, 0x0, 1); // data_alignment_indicator
|
||||
PutBits(&ld2, 0x0, 1); // Copyright
|
||||
PutBits(&ld2, 0x0, 1); // Original or Copy
|
||||
//7 = 6+1
|
||||
|
||||
if (pts != INVALID_PTS_VALUE)
|
||||
PutBits(&ld2, 0x2, 2);
|
||||
else
|
||||
PutBits(&ld2, 0x0, 2); // PTS_DTS flag
|
||||
PutBits(&ld2, 0x0, 2); // PTS_DTS flag
|
||||
|
||||
PutBits(&ld2, 0x0, 1); // ESCR_flag
|
||||
PutBits(&ld2, 0x0, 1); // ES_rate_flag
|
||||
PutBits(&ld2, 0x0, 1); // DSM_trick_mode_flag
|
||||
PutBits(&ld2, 0x0, 1); // additional_copy_ingo_flag
|
||||
PutBits(&ld2, 0x0, 1); // PES_CRC_flag
|
||||
PutBits(&ld2, 0x0, 1); // PES_extension_flag
|
||||
PutBits(&ld2, 0x0, 1); // ESCR_flag
|
||||
PutBits(&ld2, 0x0, 1); // ES_rate_flag
|
||||
PutBits(&ld2, 0x0, 1); // DSM_trick_mode_flag
|
||||
PutBits(&ld2, 0x0, 1); // additional_copy_ingo_flag
|
||||
PutBits(&ld2, 0x0, 1); // PES_CRC_flag
|
||||
PutBits(&ld2, 0x0, 1); // PES_extension_flag
|
||||
//8 = 7+1
|
||||
|
||||
if (pts != INVALID_PTS_VALUE)
|
||||
PutBits(&ld2, 0x5, 8);
|
||||
else
|
||||
PutBits(&ld2, 0x0, 8); // PES_header_data_length
|
||||
PutBits(&ld2, 0x0, 8); // PES_header_data_length
|
||||
//9 = 8+1
|
||||
|
||||
if (pts != INVALID_PTS_VALUE) {
|
||||
if (pts != INVALID_PTS_VALUE)
|
||||
{
|
||||
PutBits(&ld2, 0x2, 4);
|
||||
PutBits(&ld2, (pts >> 30) & 0x7, 3);
|
||||
PutBits(&ld2, 0x1, 1);
|
||||
@@ -101,12 +102,13 @@ int InsertPesHeader(uint8_t *data, int size, uint8_t stream_id, int64_t pts, int
|
||||
}
|
||||
//14 = 9+5
|
||||
|
||||
if (pic_start_code) {
|
||||
if (pic_start_code)
|
||||
{
|
||||
PutBits(&ld2, 0x0, 8);
|
||||
PutBits(&ld2, 0x0, 8);
|
||||
PutBits(&ld2, 0x1, 8); // Start Code
|
||||
PutBits(&ld2, pic_start_code & 0xff, 8); // 00, for picture start
|
||||
PutBits(&ld2, (pic_start_code >> 8) & 0xff, 8); // For any extra information (like in mpeg4p2, the pic_start_code)
|
||||
PutBits(&ld2, 0x1, 8); // Start Code
|
||||
PutBits(&ld2, pic_start_code & 0xff, 8); // 00, for picture start
|
||||
PutBits(&ld2, (pic_start_code >> 8) & 0xff, 8); // For any extra information (like in mpeg4p2, the pic_start_code)
|
||||
//14 + 5 = 19
|
||||
}
|
||||
|
||||
|
@@ -32,16 +32,16 @@
|
||||
#include "pes.h"
|
||||
#include "writer.h"
|
||||
|
||||
#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
|
||||
|
||||
class WriterVC1 : public Writer
|
||||
{
|
||||
@@ -68,22 +68,24 @@ bool WriterVC1::Write(AVPacket *packet, int64_t pts)
|
||||
if (!packet || !packet->data)
|
||||
return false;
|
||||
|
||||
if (initialHeader) {
|
||||
if (initialHeader)
|
||||
{
|
||||
initialHeader = false;
|
||||
FrameHeaderSeen = false;
|
||||
|
||||
const uint8_t SequenceLayerStartCode[] =
|
||||
{ 0x00, 0x00, 0x01, VC1_SEQUENCE_LAYER_METADATA_START_CODE };
|
||||
{ 0x00, 0x00, 0x01, VC1_SEQUENCE_LAYER_METADATA_START_CODE };
|
||||
|
||||
|
||||
const uint8_t Metadata[] = {
|
||||
const uint8_t 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 */
|
||||
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 */
|
||||
0x60, 0x00, 0x00, 0x00, /* Struct B */
|
||||
0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00
|
||||
};
|
||||
@@ -116,7 +118,7 @@ bool WriterVC1::Write(AVPacket *packet, int64_t pts)
|
||||
*PesPtr++ = (get_codecpar(stream)->width >> 16) & 0xff;
|
||||
*PesPtr++ = get_codecpar(stream)->width >> 24;
|
||||
|
||||
PesPtr += 12; /* Skip flag word and Struct B first 8 bytes */
|
||||
PesPtr += 12; /* Skip flag word and Struct B first 8 bytes */
|
||||
|
||||
*PesPtr++ = (usecPerFrame >> 0) & 0xff;
|
||||
*PesPtr++ = (usecPerFrame >> 8) & 0xff;
|
||||
@@ -141,21 +143,25 @@ bool WriterVC1::Write(AVPacket *packet, int64_t pts)
|
||||
initialHeader = false;
|
||||
}
|
||||
|
||||
if (packet->size > 0) {
|
||||
if (packet->size > 0)
|
||||
{
|
||||
int Position = 0;
|
||||
bool insertSampleHeader = true;
|
||||
|
||||
while (Position < packet->size) {
|
||||
while (Position < packet->size)
|
||||
{
|
||||
int PacketLength = std::min(packet->size - Position, MAX_PES_PACKET_SIZE);
|
||||
uint8_t PesHeader[PES_MAX_HEADER_SIZE];
|
||||
int HeaderLength = InsertPesHeader(PesHeader, PacketLength, VC1_VIDEO_PES_START_CODE, pts, 0);
|
||||
|
||||
if (insertSampleHeader) {
|
||||
if (insertSampleHeader)
|
||||
{
|
||||
const uint8_t Vc1FrameStartCode[] = { 0, 0, 1, VC1_FRAME_START_CODE };
|
||||
|
||||
if (!FrameHeaderSeen && (packet->size > 3) && (memcmp(packet->data, Vc1FrameStartCode, 4) == 0))
|
||||
FrameHeaderSeen = true;
|
||||
if (!FrameHeaderSeen) {
|
||||
if (!FrameHeaderSeen)
|
||||
{
|
||||
memcpy(&PesHeader[HeaderLength], Vc1FrameStartCode, sizeof(Vc1FrameStartCode));
|
||||
HeaderLength += sizeof(Vc1FrameStartCode);
|
||||
}
|
||||
@@ -185,4 +191,4 @@ WriterVC1::WriterVC1()
|
||||
Register(this, AV_CODEC_ID_VC1, VIDEO_ENCODING_VC1);
|
||||
}
|
||||
|
||||
static WriterVC1 writer_vc1 __attribute__ ((init_priority (300)));
|
||||
static WriterVC1 writer_vc1 __attribute__((init_priority(300)));
|
||||
|
@@ -33,21 +33,22 @@
|
||||
|
||||
#include <algorithm>
|
||||
|
||||
#define WMV3_PRIVATE_DATA_LENGTH 4
|
||||
#define WMV3_PRIVATE_DATA_LENGTH 4
|
||||
|
||||
static const uint8_t Metadata[] = {
|
||||
static const uint8_t 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 */
|
||||
#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 */
|
||||
#define METADATA_STRUCT_B_START 24
|
||||
0x60, 0x00, 0x00, 0x00, /* Struct B */
|
||||
0x00, 0x00, 0x00, 0x00,
|
||||
#define METADATA_STRUCT_B_FRAMERATE_START 32
|
||||
#define METADATA_STRUCT_B_FRAMERATE_START 32
|
||||
0x00, 0x00, 0x00, 0x00
|
||||
};
|
||||
|
||||
@@ -75,7 +76,8 @@ bool WriterWMV::Write(AVPacket *packet, int64_t pts)
|
||||
if (!packet || !packet->data)
|
||||
return false;
|
||||
|
||||
if (initialHeader) {
|
||||
if (initialHeader)
|
||||
{
|
||||
#define PES_MIN_HEADER_SIZE 9
|
||||
uint8_t PesPacket[PES_MIN_HEADER_SIZE + 128];
|
||||
uint8_t *PesPtr;
|
||||
@@ -103,7 +105,7 @@ bool WriterWMV::Write(AVPacket *packet, int64_t pts)
|
||||
*PesPtr++ = (get_codecpar(stream)->width >> 16) & 0xff;
|
||||
*PesPtr++ = get_codecpar(stream)->width >> 24;
|
||||
|
||||
PesPtr += 12; /* Skip flag word and Struct B first 8 bytes */
|
||||
PesPtr += 12; /* Skip flag word and Struct B first 8 bytes */
|
||||
|
||||
*PesPtr++ = (usecPerFrame >> 0) & 0xff;
|
||||
*PesPtr++ = (usecPerFrame >> 8) & 0xff;
|
||||
@@ -120,18 +122,21 @@ bool WriterWMV::Write(AVPacket *packet, int64_t pts)
|
||||
initialHeader = false;
|
||||
}
|
||||
|
||||
if (packet->size > 0 && packet->data) {
|
||||
if (packet->size > 0 && packet->data)
|
||||
{
|
||||
int Position = 0;
|
||||
bool insertSampleHeader = true;
|
||||
|
||||
while (Position < packet->size) {
|
||||
while (Position < packet->size)
|
||||
{
|
||||
|
||||
int PacketLength = std::min(packet->size - Position, MAX_PES_PACKET_SIZE);
|
||||
|
||||
uint8_t PesHeader[PES_MAX_HEADER_SIZE] = { 0 };
|
||||
int HeaderLength = InsertPesHeader(PesHeader, PacketLength, VC1_VIDEO_PES_START_CODE, pts, 0);
|
||||
|
||||
if (insertSampleHeader) {
|
||||
if (insertSampleHeader)
|
||||
{
|
||||
unsigned int PesLength;
|
||||
unsigned int PrivateHeaderLength;
|
||||
|
||||
@@ -168,4 +173,4 @@ WriterWMV::WriterWMV()
|
||||
Register(this, AV_CODEC_ID_WMV3, VIDEO_ENCODING_WMV);
|
||||
}
|
||||
|
||||
static WriterWMV writer_wmv __attribute__ ((init_priority (300)));
|
||||
static WriterWMV writer_wmv __attribute__((init_priority(300)));
|
||||
|
@@ -43,9 +43,9 @@
|
||||
#include "wmv.cpp"
|
||||
//#include "aac.cpp"
|
||||
|
||||
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 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)));
|
||||
|
||||
void Writer::Register(Writer *w, enum AVCodecID id, video_encoding_t encoding)
|
||||
{
|
||||
@@ -64,17 +64,19 @@ bool Writer::Write(AVPacket * /* packet */, int64_t /* pts */)
|
||||
return false;
|
||||
}
|
||||
|
||||
static Writer writer __attribute__ ((init_priority (300)));
|
||||
static Writer writer __attribute__((init_priority(300)));
|
||||
|
||||
Writer *Writer::GetWriter(enum AVCodecID id, enum AVMediaType codec_type, int track_type)
|
||||
{
|
||||
fprintf(stderr, "GETWRITER %d %d %d", id, codec_type, track_type);
|
||||
if (track_type != 6) { // hack for ACC resampling
|
||||
std::map<enum AVCodecID,Writer*>::iterator it = writers.find(id);
|
||||
if (track_type != 6) // hack for ACC resampling
|
||||
{
|
||||
std::map<enum AVCodecID, Writer *>::iterator it = writers.find(id);
|
||||
if (it != writers.end())
|
||||
return it->second;
|
||||
}
|
||||
switch (codec_type) {
|
||||
switch (codec_type)
|
||||
{
|
||||
case AVMEDIA_TYPE_AUDIO:
|
||||
if (id == AV_CODEC_ID_INJECTPCM) // should not happen
|
||||
break;
|
||||
@@ -91,7 +93,7 @@ Writer *Writer::GetWriter(enum AVCodecID id, enum AVMediaType codec_type, int tr
|
||||
|
||||
video_encoding_t Writer::GetVideoEncoding(enum AVCodecID id)
|
||||
{
|
||||
std::map<enum AVCodecID,video_encoding_t>::iterator it = vencoding.find(id);
|
||||
std::map<enum AVCodecID, video_encoding_t>::iterator it = vencoding.find(id);
|
||||
if (it != vencoding.end())
|
||||
return it->second;
|
||||
return VIDEO_ENCODING_AUTO;
|
||||
@@ -99,7 +101,7 @@ video_encoding_t Writer::GetVideoEncoding(enum AVCodecID id)
|
||||
|
||||
audio_encoding_t Writer::GetAudioEncoding(enum AVCodecID id)
|
||||
{
|
||||
std::map<enum AVCodecID,audio_encoding_t>::iterator it = aencoding.find(id);
|
||||
std::map<enum AVCodecID, audio_encoding_t>::iterator it = aencoding.find(id);
|
||||
if (it != aencoding.end())
|
||||
return it->second;
|
||||
return AUDIO_ENCODING_LPCMA;
|
||||
|
Reference in New Issue
Block a user