libeplayer3: continue refresh

This commit is contained in:
martii
2014-04-08 20:02:07 +02:00
parent fcd1dc8399
commit cb3db6256c
25 changed files with 617 additions and 736 deletions

View File

@@ -1,9 +1,8 @@
noinst_LTLIBRARIES = libeplayer3.la
CXXFLAGS = -Wall
AM_CPPFLAGS = -I$(srcdir)/include
AM_CPPFLAGS += -Wall -D_LARGEFILE_SOURCE -D_FILE_OFFSET_BITS=64 -D_LARGEFILE64_SOURCE
AM_CPPFLAGS += -Wall #-fno-rtti
AM_CPPFLAGS += -D_LARGEFILE_SOURCE -D_FILE_OFFSET_BITS=64 -D_LARGEFILE64_SOURCE
AM_CPPFLAGS += -D__STDC_CONSTANT_MACROS -D__STDC_LIMIT_MACROS
AM_CPPFLAGS += -ggdb

View File

@@ -1,3 +1,9 @@
This is a revised libeplayer3 version for Neutrino, rewritten in C++, with
various code parts (e.g. subtitle processing, non-working decoders) removed.
--martii
The original libeplayer3 README follows:
/*
* SCOPE:
* -------

View File

@@ -1,3 +1,23 @@
/*
* input class
*
* Copyright (C) 2014 martii
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
#ifndef __INPUT_H__
#define __INPUT_H__
@@ -24,6 +44,7 @@ class Track;
class Input
{
friend class Player;
friend int interrupt_cb(void *arg);
private:
Track *videoTrack;
@@ -36,6 +57,7 @@ class Input
float seek_sec_rel;
bool isContainerRunning;
bool terminating;
bool abortPlayback;
Player *player;
AVFormatContext *avfc;

View File

@@ -1,3 +1,23 @@
/*
* manager class
*
* Copyright (C) 2014 martii
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
#ifndef __MANAGER_H__
#define __MANAGER_H__
@@ -24,21 +44,13 @@ struct Track
{
std::string Name;
int pid;
/* length of track */
int64_t duration;
/* context from ffmpeg */
AVFormatContext *avfc;
/* stream from ffmpeg */
AVStream *stream;
bool inactive;
bool is_static;
int ac3flags;
int type, mag, page; // for teletext
Track() : pid(-1), duration(-1), avfc(NULL), stream(NULL), inactive(0), is_static(0), ac3flags(0) {}
};
@@ -49,7 +61,10 @@ class Manager
private:
Player *player;
OpenThreads::Mutex mutex;
std::map<int,Track *> videoTracks, audioTracks, subtitleTracks, teletextTracks;
std::map<int,Track*> videoTracks, audioTracks, subtitleTracks, teletextTracks;
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);

View File

@@ -1,3 +1,23 @@
/*
* output class
*
* Copyright (C) 2014 martii
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
#ifndef __OUTPUT_H__
#define __OUTPUT_H__
@@ -54,7 +74,7 @@ class Output
bool GetFrameCount(int64_t &framecount);
bool SwitchAudio(AVStream *stream);
bool SwitchVideo(AVStream *stream);
bool Write(AVFormatContext *avfc, AVStream *stream, AVPacket *packet, int64_t &Pts);
bool Write(AVFormatContext *avfc, AVStream *stream, AVPacket *packet, int64_t Pts);
};
#endif

View File

@@ -28,7 +28,7 @@
#define VC1_VIDEO_PES_START_CODE 0xfd
#define AAC_AUDIO_PES_START_CODE 0xcf
int InsertPesHeader(uint8_t *data, int size, unsigned char stream_id, unsigned long long int pts, int pic_start_code);
int InsertPesHeader(uint8_t *data, int size, unsigned char stream_id, int64_t pts, int pic_start_code);
int InsertVideoPrivateDataHeader(uint8_t *data, int payload_size);
#endif

View File

@@ -1,3 +1,23 @@
/*
* player class
*
* Copyright (C) 2014 martii
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
#ifndef __PLAYER_H__
#define __PLAYER_H__
@@ -44,52 +64,50 @@ class Player {
Manager manager;
OpenThreads::Mutex chapterMutex;
std::vector<Chapter> chapters;
bool abortPlayback;
pthread_t supervisorThread;
bool abortRequested;
bool isHttp;
bool isPaused;
bool isCreationPhase;
bool isSlowMotion;
int Speed;
int AVSync;
bool hasThreadStarted;
bool isForwarding;
bool isBackWard;
bool isPlaying;
bool isVideo;
bool isAudio;
int Speed;
uint64_t readCount;
std::string url;
bool noprobe; /* hack: only minimal probing in av_find_stream_info */
int hasThreadStarted;
void SetChapters(std::vector<Chapter> &Chapters);
static void* SupervisorThread(void*);
public:
bool isForwarding;
bool isBackWard;
bool isPlaying;
uint64_t readCount;
bool SwitchAudio(int pid);
bool SwitchVideo(int pid);
bool SwitchTeletext(int pid);
bool SwitchSubtitle(int pid);
bool GetPts(int64_t &pts);
bool GetFrameCount(int64_t &framecount);
bool GetDuration(double &duration);
bool GetMetadata(std::vector<std::string> &keys, std::vector<std::string> &values);
bool SlowMotion(int repeats);
bool FastBackward(int speed);
bool FastForward(int speed);
bool Open(const char *Url);
bool Open(const char *Url, bool noprobe = false);
bool Close();
bool Play();
bool Pause();
bool Continue();
bool Stop();
bool Seek(float pos, bool absolute);
bool Terminate();
void RequestAbort();
bool GetChapters(std::vector<int> &positions, std::vector<std::string> &titles);
void SetChapters(std::vector<Chapter> &Chapters);
Player();
Player();
};
#endif

View File

@@ -1,3 +1,23 @@
/*
* writer class headers
*
* Copyright (C) 2014 martii
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
#ifndef __WRITER_H__
#define __WRITER_H__
@@ -27,7 +47,7 @@ class Writer
static Writer *GetWriter(enum AVCodecID id, enum AVMediaType codec_type);
virtual void Init(void) { }
virtual bool Write(int fd, AVFormatContext *avfc, AVStream *stream, AVPacket *packet, int64_t &pts);
virtual bool Write(int fd, AVFormatContext *avfc, AVStream *stream, AVPacket *packet, int64_t pts);
Writer() { Init (); }
~Writer() {}

View File

@@ -1,12 +1,14 @@
/*
* Container handling for all stream's handled by ffmpeg
* konfetti 2010; based on code from crow
* input class
*
* based on libeplayer3 container_ffmpeg.c, konfetti 2010; based on code from crow
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
* Copyright (C) 2014 martii
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
@@ -15,31 +17,28 @@
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
#include <sys/ioctl.h>
#include <fcntl.h>
#include <unistd.h>
#include <memory.h>
#include <string.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <errno.h>
#include <sys/poll.h>
#include <pthread.h>
#include <sys/prctl.h>
#include <linux/dvb/stm_ioctls.h>
#include "player.h"
#include "misc.h"
#define averror(_err,_fun) ({ \
if (_err < 0) { \
char _error[512]; \
av_strerror(_err, _error, sizeof(_error)); \
fprintf(stderr, "%s %d: %s: %d (%s)\n", __FILE__, __LINE__, #_fun, _err, _error); \
} \
_err; \
})
Input::Input()
{
videoTrack = NULL;
@@ -48,7 +47,6 @@ Input::Input()
teletextTrack = NULL;
hasPlayThreadStarted = 0;
isContainerRunning = 0;
seek_sec_abs = -1.0;
seek_sec_rel = 0.0;
terminating = false;
@@ -67,14 +65,14 @@ int64_t calcPts(AVFormatContext *avfc, AVStream * stream, int64_t pts)
}
if (pts == AV_NOPTS_VALUE)
pts = INVALID_PTS_VALUE;
else if (avfc->start_time == AV_NOPTS_VALUE)
pts = 90000.0 * (double) pts * av_q2d(stream->time_base);
else
pts = 90000.0 * (double) pts * av_q2d(stream->time_base) - 90000.0 * avfc->start_time / AV_TIME_BASE;
return INVALID_PTS_VALUE;
if (pts & 0x8000000000000000ull)
pts = INVALID_PTS_VALUE;
pts = 90000.0 * (double) pts * av_q2d(stream->time_base);
if (avfc->start_time != AV_NOPTS_VALUE)
pts -= 90000.0 * avfc->start_time / AV_TIME_BASE;
if (pts & 0x8000000000000000ll)
return INVALID_PTS_VALUE;
return pts;
}
@@ -88,23 +86,11 @@ extern "C" void teletext_write(int pid, uint8_t *data, int size);
bool Input::Play()
{
char threadname[17];
strncpy(threadname, __func__, sizeof(threadname));
threadname[16] = 0;
prctl(PR_SET_NAME, (unsigned long) &threadname);
hasPlayThreadStarted = 1;
int64_t currentVideoPts = 0, currentAudioPts = 0, showtime = 0, bofcount = 0;
int64_t showtime = 0, bofcount = 0;
bool restart_audio_resampling = false;
while (player->isCreationPhase) {
fprintf(stderr, "Thread waiting for end of init phase...\n");
usleep(1000);
}
fprintf(stderr, "Running!\n");
while (player->isPlaying && !player->abortRequested) {
//IF MOVIE IS PAUSED, WAIT
@@ -123,7 +109,9 @@ bool Input::Play()
seek_target_flag = AVSEEK_FLAG_BYTE;
seek_target = avio_tell(avfc->pb) + seek_sec_rel * br;
} else {
seek_target = ((((currentVideoPts > 0) ? currentVideoPts : currentAudioPts) / 90000.0) + seek_sec_rel) * AV_TIME_BASE;
int64_t pts;
if(player->output.GetPts(pts))
seek_target = (pts * AV_TIME_BASE)/ 90000.0 + seek_sec_rel * AV_TIME_BASE;
}
seek_sec_rel = 0.0;
} else if (seek_sec_abs >= 0.0) {
@@ -147,17 +135,15 @@ bool Input::Play()
if (avfc->iformat->flags & AVFMT_TS_DISCONT) {
off_t pos = avio_tell(avfc->pb);
if (pos > 0) {
float br;
if (avfc->bit_rate)
br = avfc->bit_rate / 8.0;
else
br = 180000.0;
seek_target = pos + player->Speed * 8 * br;
seek_target_flag = AVSEEK_FLAG_BYTE;
}
if (pos > 0) {
float br = avfc->bit_rate ? avfc->bit_rate / 8.0 : 180000.0;
seek_target_flag = AVSEEK_FLAG_BYTE;
seek_target = pos + player->Speed * 8 * br;
}
} else {
seek_target = ((((currentVideoPts > 0) ? currentVideoPts : currentAudioPts) / 90000.0) + player->Speed * 8) * AV_TIME_BASE;;
int64_t pts;
if(player->output.GetPts(pts))
seek_target = (pts * AV_TIME_BASE)/ 90000.0 + seek_sec_rel * AV_TIME_BASE;
}
showtime = av_gettime() + 300000; //jump back every 300ms
} else {
@@ -185,76 +171,63 @@ bool Input::Play()
AVPacket packet;
av_init_packet(&packet);
int av_res = av_read_frame(avfc, &packet);
if (av_res == AVERROR(EAGAIN)) {
int err = av_read_frame(avfc, &packet);
if (err == AVERROR(EAGAIN)) {
av_free_packet(&packet);
continue;
}
if (av_res) { // av_read_frame failed
fprintf(stderr, "no data ->end of file reached ?\n");
av_free_packet(&packet);
if (averror(err, av_read_frame)) // EOF?
break; // while
}
int64_t pts;
player->readCount += packet.size;
int pid = avfc->streams[packet.stream_index]->id;
Track *_videoTrack = videoTrack;
Track *_audioTrack = audioTrack;
Track *_subtitleTrack = subtitleTrack;
Track *_teletextTrack = teletextTrack;
if (_videoTrack && (_videoTrack->pid == pid)) {
currentVideoPts = pts = calcPts(avfc, _videoTrack->stream, packet.pts);
if (!player->output.Write(avfc, _videoTrack->stream, &packet, currentVideoPts))
int64_t pts = calcPts(avfc, _videoTrack->stream, packet.pts);
if (!player->output.Write(avfc, _videoTrack->stream, &packet, pts))
fprintf(stderr, "writing data to video device failed\n");
} else if (_audioTrack && (_audioTrack->pid == pid)) {
if (restart_audio_resampling) {
restart_audio_resampling = false;
player->output.Write(avfc, _audioTrack->stream, NULL, currentAudioPts);
player->output.Write(avfc, _audioTrack->stream, NULL, 0);
}
if (!player->isBackWard) {
currentAudioPts = pts = calcPts(avfc, _audioTrack->stream, packet.pts);
if (!player->output.Write(avfc, _audioTrack->stream, &packet, currentAudioPts))
int64_t pts = calcPts(avfc, _audioTrack->stream, packet.pts);
if (!player->output.Write(avfc, _audioTrack->stream, &packet, pts))
fprintf(stderr, "writing data to audio device failed\n");
}
} else if (_subtitleTrack && (_subtitleTrack->pid == pid)) {
float duration = 3.0;
if (((AVStream *) _subtitleTrack->stream)->codec->codec) {
AVSubtitle sub;
memset(&sub, 0, sizeof(sub));
int got_sub_ptr = 0;
pts = calcPts(avfc, _subtitleTrack->stream, packet.pts);
err = avcodec_decode_subtitle2(((AVStream *) _subtitleTrack->stream)->codec, &sub, &got_sub_ptr, &packet);
averror(err, avcodec_decode_subtitle2);
if (duration > 0.0) {
/* is there a decoder ? */
if (((AVStream *) _subtitleTrack->stream)->codec->codec) {
AVSubtitle sub;
memset(&sub, 0, sizeof(sub));
int got_sub_ptr;
if (avcodec_decode_subtitle2(((AVStream *) _subtitleTrack->stream)->codec, &sub, &got_sub_ptr, &packet) < 0) {
fprintf(stderr, "error decoding subtitle\n");
}
if (got_sub_ptr && sub.num_rects > 0) {
switch (sub.rects[0]->type) {
case SUBTITLE_TEXT: // FIXME?
case SUBTITLE_ASS:
dvbsub_ass_write(((AVStream *) _subtitleTrack->stream)->codec, &sub, pid);
break;
case SUBTITLE_BITMAP:
dvbsub_write(&sub, pts);
// avsubtitle_free() will be called by handler
break;
default:
break;
if (got_sub_ptr && sub.num_rects > 0) {
switch (sub.rects[0]->type) {
case SUBTITLE_TEXT: // FIXME?
case SUBTITLE_ASS:
dvbsub_ass_write(((AVStream *) _subtitleTrack->stream)->codec, &sub, pid);
break;
case SUBTITLE_BITMAP: {
int64_t pts = calcPts(avfc, _subtitleTrack->stream, packet.pts);
dvbsub_write(&sub, calcPts(avfc, _subtitleTrack->stream, pts));
// avsubtitle_free() will be called by handler
break;
}
default:
break;
}
}
} /* duration */
}
} else if (_teletextTrack && (_teletextTrack->pid == pid)) {
teletext_write(pid, packet.data, packet.size);
}
@@ -262,12 +235,14 @@ bool Input::Play()
av_free_packet(&packet);
} /* while */
if (player && player->abortRequested)
if (player->abortRequested)
player->output.Clear();
else
player->output.Flush();
dvbsub_ass_clear();
player->abortPlayback = 1;
hasPlayThreadStarted = 0;
abortPlayback = true;
hasPlayThreadStarted = false;
return true;
}
@@ -275,7 +250,10 @@ bool Input::Play()
/*static*/ int interrupt_cb(void *arg)
{
Player *player = (Player *) arg;
return player->abortPlayback | player->abortRequested;
bool res = player->input.abortPlayback || player->abortRequested;
if (res)
fprintf(stderr, "%s %s %d: abort requested (%d/%d)\n", __FILE__, __func__, __LINE__, player->input.abortPlayback, player->abortRequested);
return res;
}
static void log_callback(void *ptr __attribute__ ((unused)), int lvl __attribute__ ((unused)), const char *format, va_list ap)
@@ -293,11 +271,16 @@ bool Input::ReadSubtitle(const char *filename, const char *format, int pid)
strcpy(subfile, filename);
strcpy(subfile + (lastDot + 1 - filename), format);
if (access(subfile, R_OK))
return false;
AVFormatContext *subavfc = avformat_alloc_context();
if (avformat_open_input(&subavfc, subfile, av_find_input_format(format), 0)) {
int err = avformat_open_input(&subavfc, subfile, av_find_input_format(format), 0);
if (averror(err, avformat_open_input)) {
avformat_free_context(subavfc);
return false;
}
avformat_find_stream_info(subavfc, NULL);
if (subavfc->nb_streams != 1) {
avformat_free_context(subavfc);
@@ -311,12 +294,12 @@ bool Input::ReadSubtitle(const char *filename, const char *format, int pid)
return false;
}
// fprintf(stderr, "codec=%s\n", avcodec_get_name(c->codec_id));
if (avcodec_open2(c, codec, NULL) < 0) {
fprintf(stderr, "%s %d: avcodec_open\n", __FILE__, __LINE__);
err = avcodec_open2(c, codec, NULL);
if (averror(err, avcodec_open2)) {
avformat_free_context(subavfc);
return false;
}
AVPacket avpkt;
av_init_packet(&avpkt);
@@ -356,47 +339,30 @@ bool Input::ReadSubtitles(const char *filename) {
bool Input::Init(const char *filename)
{
int err;
abortPlayback = false;
av_log_set_callback(log_callback);
if (filename == NULL) {
if (!filename) {
fprintf(stderr, "filename NULL\n");
return false;
}
fprintf(stderr, "%s %s %d: %s\n", __FILE__, __func__, __LINE__, filename);
if (isContainerRunning) {
fprintf(stderr, "ups already running?\n");
return false;
}
isContainerRunning = true;
/* initialize ffmpeg */
avcodec_register_all();
av_register_all();
avformat_network_init();
player->abortRequested = 0;
player->abortPlayback = 0;
videoTrack = NULL;
audioTrack = NULL;
subtitleTrack = NULL;
teletextTrack = NULL;
avfc = avformat_alloc_context();
avfc->interrupt_callback.callback = interrupt_cb;
avfc->interrupt_callback.opaque = (void *) &player;
avfc->interrupt_callback.opaque = (void *) player;
if ((err = avformat_open_input(&avfc, filename, NULL, 0)) != 0) {
char error[512];
fprintf(stderr, "avformat_open_input failed %d (%s)\n", err, filename);
av_strerror(err, error, 512);
fprintf(stderr, "Cause: %s\n", error);
isContainerRunning = false;
int err = avformat_open_input(&avfc, filename, NULL, 0);
if (averror(err, avformat_open_input))
return false;
}
avfc->iformat->flags |= AVFMT_SEEK_TO_PTS;
avfc->flags = AVFMT_FLAG_GENPTS;
@@ -405,17 +371,10 @@ bool Input::Init(const char *filename)
avfc->probesize = 8192;
}
if (avformat_find_stream_info(avfc, NULL) < 0) {
fprintf(stderr, "Error avformat_find_stream_info\n");
#ifdef this_is_ok
/* crow reports that sometimes this returns an error
* but the file is played back well. so remove this
* until other works are done and we can prove this.
*/
err = avformat_find_stream_info(avfc, NULL);
if (averror(err, avformat_open_input)) {
avformat_close_input(&avfc);
isContainerRunning = false;
return false;
#endif
}
terminating = false;
@@ -424,7 +383,6 @@ bool Input::Init(const char *filename)
if (!videoTrack && !audioTrack) {
avformat_close_input(&avfc);
isContainerRunning = false;
return false;
}
@@ -525,9 +483,9 @@ bool Input::UpdateTracks()
snprintf(tmp, sizeof(tmp), "teletext_%d", i);
t = av_dict_get(stream->metadata, tmp, NULL, 0);
if (t) {
char lang[strlen(t->value)];
if (5 == sscanf(t->value, "%d %s %d %d %d", &track.pid, lang, &track.type, &track.mag, &track.page)) {
track.Name = lang;
char language[strlen(t->value)];
if (5 == sscanf(t->value, "%d %s %d %d %d", &track.pid, language, &track.type, &track.mag, &track.page)) {
track.Name = language;
player->manager.addTeletextTrack(track);
}
}
@@ -552,7 +510,6 @@ bool Input::UpdateTracks()
fprintf(stderr, "not handled or unknown codec_type %d\n", stream->codec->codec_type);
break;
}
}
return true;
@@ -560,11 +517,7 @@ bool Input::UpdateTracks()
bool Input::Stop()
{
if (!isContainerRunning) {
fprintf(stderr, "Container not running\n");
return false;
}
player->abortRequested = 1;
abortPlayback = true;
while (hasPlayThreadStarted != 0)
usleep(100000);
@@ -574,8 +527,6 @@ bool Input::Stop()
if (avfc)
avformat_close_input(&avfc);
isContainerRunning = false;
avformat_network_deinit();
return true;
@@ -594,16 +545,19 @@ bool Input::GetDuration(double &duration)
{
duration = 0.0;
if (videoTrack && videoTrack->duration != 0.0) {
duration = videoTrack->duration / 1000.0;
Track *track = videoTrack;
if (track && track->duration != 0.0) {
duration = track->duration / 1000.0;
return true;
}
if (audioTrack && audioTrack->duration != 0.0) {
duration = audioTrack->duration / 1000.0;
track = audioTrack;
if (track && track->duration != 0.0) {
duration = track->duration / 1000.0;
return true;
}
if (subtitleTrack && subtitleTrack->duration != 0.0) {
duration = subtitleTrack->duration / 1000.0;
track = subtitleTrack;
if (track && track->duration != 0.0) {
duration = track->duration / 1000.0;
return true;
}
if (avfc && avfc->duration != 0.0) {
@@ -665,11 +619,8 @@ bool Input::GetMetadata(std::vector<std::string> &keys, std::vector<std::string>
keys.push_back(tag->key);
values.push_back(tag->value);
}
return true;
}
return false;
return true;
}
bool Input::GetReadCount(uint64_t &readcount)

View File

@@ -1,10 +1,12 @@
/*
* manager handling.
* manager class
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
* Copyright (C) 2014 martii
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
@@ -13,8 +15,7 @@
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
#include <stdlib.h>
@@ -22,132 +23,95 @@
#include "manager.h"
#include "player.h"
void Manager::addVideoTrack(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 = videoTracks.find(track.pid);
if (it == videoTracks.end()) {
std::map<int,Track*>::iterator it = tracks.find(track.pid);
if (it == tracks.end()) {
Track *t = new Track;
*t = track;
videoTracks[track.pid] = t;
tracks[track.pid] = t;
} else
*it->second = track;
}
void Manager::addVideoTrack(Track &track)
{
addTrack(videoTracks, track);
}
void Manager::addAudioTrack(Track &track)
{
OpenThreads::ScopedLock<OpenThreads::Mutex> m_lock(mutex);
std::map<int,Track*>::iterator it = audioTracks.find(track.pid);
if (it == audioTracks.end()) {
Track *t = new Track;
*t = track;
audioTracks[track.pid] = t;
} else
*it->second = track;
addTrack(audioTracks, track);
}
void Manager::addSubtitleTrack(Track &track)
{
OpenThreads::ScopedLock<OpenThreads::Mutex> m_lock(mutex);
std::map<int,Track*>::iterator it = subtitleTracks.find(track.pid);
if (it == subtitleTracks.end()) {
Track *t = new Track;
*t = track;
subtitleTracks[track.pid] = t;
} else
*it->second = track;
addTrack(subtitleTracks, track);
}
void Manager::addTeletextTrack(Track &track)
{
addTrack(teletextTracks, track);
}
std::vector<Track> Manager::getTracks(std::map<int,Track*> &tracks)
{
player->input.UpdateTracks();
std::vector<Track> res;
OpenThreads::ScopedLock<OpenThreads::Mutex> m_lock(mutex);
std::map<int,Track*>::iterator it = teletextTracks.find(track.pid);
if (it == teletextTracks.end()) {
Track *t = new Track;
*t = track;
teletextTracks[track.pid] = t;
} else
*it->second = track;
for(std::map<int,Track*>::iterator it = tracks.begin(); it != tracks.end(); ++it)
if (!it->second->inactive)
res.push_back(*it->second);
return res;
}
std::vector<Track> Manager::getVideoTracks()
{
player->input.UpdateTracks();
std::vector<Track> res;
OpenThreads::ScopedLock<OpenThreads::Mutex> m_lock(mutex);
for(std::map<int,Track*>::iterator it = videoTracks.begin(); it != videoTracks.end(); ++it)
if (!it->second->inactive)
res.push_back(*it->second);
return res;
return getTracks(videoTracks);
}
std::vector<Track> Manager::getAudioTracks()
{
player->input.UpdateTracks();
std::vector<Track> res;
OpenThreads::ScopedLock<OpenThreads::Mutex> m_lock(mutex);
for(std::map<int,Track*>::iterator it = audioTracks.begin(); it != audioTracks.end(); ++it)
if (!it->second->inactive)
res.push_back(*it->second);
return res;
return getTracks(audioTracks);
}
std::vector<Track> Manager::getSubtitleTracks()
{
player->input.UpdateTracks();
std::vector<Track> res;
OpenThreads::ScopedLock<OpenThreads::Mutex> m_lock(mutex);
for(std::map<int,Track*>::iterator it = subtitleTracks.begin(); it != subtitleTracks.end(); ++it)
if (!it->second->inactive)
res.push_back(*it->second);
return res;
return getTracks(subtitleTracks);
}
std::vector<Track> Manager::getTeletextTracks()
{
player->input.UpdateTracks();
std::vector<Track> res;
OpenThreads::ScopedLock<OpenThreads::Mutex> m_lock(mutex);
for(std::map<int,Track*>::iterator it = teletextTracks.begin(); it != teletextTracks.end(); ++it)
if (!it->second->inactive)
res.push_back(*it->second);
return res;
return getTracks(teletextTracks);
}
Track *Manager::getVideoTrack(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 = videoTracks.find(pid);
if (it != videoTracks.end() && !it->second->inactive)
std::map<int,Track*>::iterator it = tracks.find(pid);
if (it != tracks.end() && !it->second->inactive)
return it->second;
return NULL;
}
Track *Manager::getVideoTrack(int pid)
{
return getTrack(videoTracks, pid);
}
Track *Manager::getAudioTrack(int pid)
{
OpenThreads::ScopedLock<OpenThreads::Mutex> m_lock(mutex);
std::map<int,Track*>::iterator it = audioTracks.find(pid);
if (it != audioTracks.end() && !it->second->inactive)
return it->second;
return NULL;
return getTrack(audioTracks, pid);
}
Track *Manager::getSubtitleTrack(int pid)
{
OpenThreads::ScopedLock<OpenThreads::Mutex> m_lock(mutex);
std::map<int,Track*>::iterator it = subtitleTracks.find(pid);
if (it != subtitleTracks.end() && !it->second->inactive)
return it->second;
return NULL;
return getTrack(subtitleTracks, pid);
}
Track *Manager::getTeletextTrack(int pid)
{
OpenThreads::ScopedLock<OpenThreads::Mutex> m_lock(mutex);
std::map<int,Track*>::iterator it = teletextTracks.find(pid);
if (it != teletextTracks.end() && !it->second->inactive)
return it->second;
return NULL;
return getTrack(teletextTracks, pid);
}
bool Manager::initTrackUpdate()

View File

@@ -1,10 +1,14 @@
/*
* LinuxDVB Output handling.
* output class
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
* based on libeplayer3 LinuxDVB Output handling.
*
* Copyright (C) 2014 martii
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
@@ -13,8 +17,7 @@
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
#include <stdio.h>
@@ -209,12 +212,8 @@ bool Output::Continue()
bool Output::Mute(bool b)
{
OpenThreads::ScopedLock<OpenThreads::Mutex> a_lock(audioMutex);
//AUDIO_SET_MUTE has no effect with new player
if (audiofd > -1 && dioctl(audiofd, b ? AUDIO_STOP : AUDIO_PLAY, NULL))
return false;
return true;
return audiofd > -1 && !dioctl(audiofd, b ? AUDIO_STOP : AUDIO_PLAY, NULL);
}
@@ -237,48 +236,31 @@ bool Output::Flush()
bool Output::FastForward(int speed)
{
OpenThreads::ScopedLock<OpenThreads::Mutex> v_lock(videoMutex);
if (videofd > -1 && dioctl(videofd, VIDEO_FAST_FORWARD, speed))
return false;
return true;
return videofd > -1 && !dioctl(videofd, VIDEO_FAST_FORWARD, speed);
}
bool Output::SlowMotion(int speed)
{
OpenThreads::ScopedLock<OpenThreads::Mutex> v_lock(videoMutex);
if (videofd > -1 && dioctl(videofd, VIDEO_SLOWMOTION, speed))
return false;
return true;
return videofd > -1 && !dioctl(videofd, VIDEO_SLOWMOTION, speed);
}
bool Output::AVSync(bool b)
{
OpenThreads::ScopedLock<OpenThreads::Mutex> a_lock(audioMutex);
if (audiofd > -1 && dioctl(audiofd, AUDIO_SET_AV_SYNC, b))
return false;
return true;
return audiofd > -1 && !dioctl(audiofd, AUDIO_SET_AV_SYNC, b);
}
bool Output::ClearAudio()
{
OpenThreads::ScopedLock<OpenThreads::Mutex> a_lock(audioMutex);
if (audiofd > -1 && dioctl(audiofd, AUDIO_CLEAR_BUFFER, NULL))
return false;
return true;
return audiofd > -1 && !dioctl(audiofd, AUDIO_CLEAR_BUFFER, NULL);
}
bool Output::ClearVideo()
{
OpenThreads::ScopedLock<OpenThreads::Mutex> v_lock(videoMutex);
if (videofd > -1 && dioctl(videofd, VIDEO_CLEAR_BUFFER, NULL))
return false;
return true;
return videofd > -1 && !dioctl(videofd, VIDEO_CLEAR_BUFFER, NULL);
}
bool Output::Clear()
@@ -349,20 +331,16 @@ bool Output::SwitchVideo(AVStream *stream)
return true;
}
bool Output::Write(AVFormatContext *avfc, AVStream *stream, AVPacket *packet, int64_t &Pts)
bool Output::Write(AVFormatContext *avfc, AVStream *stream, AVPacket *packet, int64_t pts)
{
switch (stream->codec->codec_type) {
case AVMEDIA_TYPE_VIDEO: {
OpenThreads::ScopedLock<OpenThreads::Mutex> v_lock(videoMutex);
if (videofd > -1 && videoWriter)
return videoWriter->Write(videofd, avfc, stream, packet, Pts);
return false;
return videofd > -1 && videoWriter && videoWriter->Write(videofd, avfc, stream, packet, pts);
}
case AVMEDIA_TYPE_AUDIO: {
OpenThreads::ScopedLock<OpenThreads::Mutex> a_lock(audioMutex);
if (audiofd > -1 && audioWriter)
return audioWriter->Write(audiofd, avfc, stream, packet, Pts);
return false;
return audiofd > -1 && audioWriter && audioWriter->Write(audiofd, avfc, stream, packet, pts);
}
default:
return false;

View File

@@ -1,19 +1,30 @@
/*
* GPL
* duckbox 2010
* linuxdvb output/writer handling
*
* Copyright (C) 2010 duckbox
* Copyright (C) 2014 martii (based on code from libeplayer3)
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <sys/socket.h>
#include <netdb.h>
#include <sys/types.h>
#include <dirent.h>
#include <errno.h>
#include <poll.h>
#include <pthread.h>
#include <sys/prctl.h>
#include "player.h"
#include "misc.h"
@@ -21,71 +32,56 @@
#define cMaxSpeed_ff 128 /* fixme: revise */
#define cMaxSpeed_fr -320 /* fixme: revise */
static pthread_t supervisorThread;
Player::Player()
{
input.player = this;
output.player = this;
manager.player = this;
hasThreadStarted = 0;
hasThreadStarted = false;
}
void *Player::SupervisorThread(void *arg)
{
char threadname[17];
strncpy(threadname, __func__, sizeof(threadname));
threadname[16] = 0;
prctl(PR_SET_NAME, (unsigned long) &threadname);
Player *player = (Player *) arg;
player->hasThreadStarted = 1;
player->hasThreadStarted = true;
player->input.Play();
player->hasThreadStarted = 2;
player->Terminate();
fprintf(stderr, "terminating\n");
player->hasThreadStarted = 0;
player->hasThreadStarted = false;
player->Stop();
pthread_exit(NULL);
}
bool Player::Open(const char *Url)
bool Player::Open(const char *Url, bool _noprobe)
{
if (isPlaying)
Stop(); // shouldn't happen. Most definitely a bug
fprintf(stderr, "URL=%s\n", Url);
if (isPlaying) { // shouldn't happen
fprintf(stderr, "playback already running\n");
return false;
}
isHttp = false;
noprobe = _noprobe;
abortRequested = false;
isHttp = 0;
if (!strncmp("file://", Url, 7) || !strncmp("myts://", Url, 7)) {
if (!strncmp("myts://", Url, 7)) {
url = "file";
url += (Url + 4);
noprobe = 1;
} else {
noprobe = 0;
url = Url;
}
} else if (strstr(Url, "://")) {
isHttp = 1;
if (!strncmp("mms://", Url, 6)) {
url = "mmst";
url += (Url + 3);
} else
url = Url;
} else {
fprintf(stderr, "Unknown stream (%s)\n", Url);
return false;
}
manager.clearTracks();
if (*Url == '/') {
url = "file://";
url += Url;
} else if (!strncmp("mms://", Url, 6)) {
url = "mmst";
url += Url + 3;
isHttp = true;
} else if (strstr(Url, "://")) {
url = Url;
} else {
fprintf(stderr, "%s %s %d: Unknown stream (%s)\n", __FILE__, __func__, __LINE__, Url);
return false;
}
if (!input.Init(url.c_str()))
return false;
fprintf(stderr, "exiting with value 0\n");
return true;
}
@@ -93,11 +89,11 @@ bool Player::Close()
{
bool ret = true;
isPaused = 0;
isPlaying = 0;
isForwarding = 0;
isBackWard = 0;
isSlowMotion = 0;
isPaused = false;
isPlaying = false;
isForwarding = false;
isBackWard = false;
isSlowMotion = false;
Speed = 0;
url.clear();
@@ -106,55 +102,41 @@ bool Player::Close()
bool Player::Play()
{
pthread_attr_t attr;
bool ret = true;
if (!isPlaying) {
AVSync = 1;
output.AVSync(true);
output.AVSync(true);
isCreationPhase = 1; // allows the created thread to go into wait mode
ret = output.Play();
ret = output.Play();
if (!ret) {
isCreationPhase = 0; // allow thread to go into next state
} else {
isPlaying = 1;
isPaused = 0;
isForwarding = 0;
if (isBackWard) {
isBackWard = 0;
output.Mute(false);
}
isSlowMotion = 0;
Speed = 1;
if (ret) {
isPlaying = true;
isPaused = false;
isForwarding = false;
if (isBackWard) {
isBackWard = false;
output.Mute(false);
}
isSlowMotion = false;
Speed = 1;
if (hasThreadStarted == 0) {
int error;
pthread_attr_init(&attr);
pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
if (!hasThreadStarted) {
int err = pthread_create(&supervisorThread, NULL, SupervisorThread, this);
if ((error = pthread_create(&supervisorThread, &attr, SupervisorThread, this))) {
fprintf(stderr, "Error creating thread, error:%d:%s\n", error, strerror(error));
ret = false;
} else {
fprintf(stderr, "Created thread\n");
if (err) {
fprintf(stderr, "%s %s %d: pthread_create: %d (%s)\n", __FILE__, __func__, __LINE__, err, strerror(err));
ret = false;
isPlaying = false;
} else {
pthread_detach(supervisorThread);
}
}
}
fprintf(stderr, "clearing isCreationPhase!\n");
isCreationPhase = 0; // allow thread to go into next state
}
} else {
fprintf(stderr,"playback already running\n");
ret = false;
}
fprintf(stderr, "exiting with value %d\n", ret);
return ret;
}
@@ -164,27 +146,24 @@ bool Player::Pause()
if (isPlaying && !isPaused) {
if (isSlowMotion)
output.Clear();
if (isSlowMotion)
output.Clear();
output.Pause();
output.Pause();
isPaused = 1;
//isPlaying = 1;
isForwarding = 0;
if (isBackWard) {
isBackWard = 0;
output.Mute(false);
}
isSlowMotion = 0;
isPaused = true;
//isPlaying = 1;
isForwarding = false;
if (isBackWard) {
isBackWard = false;
output.Mute(false);
}
isSlowMotion = false;
Speed = 1;
} else {
fprintf(stderr,"playback not playing or already in pause mode\n");
ret = false;
}
fprintf(stderr, "exiting with value %d\n", ret);
return ret;
}
@@ -199,14 +178,14 @@ bool Player::Continue()
output.Continue();
isPaused = 0;
isPaused = false;
//isPlaying = 1;
isForwarding = 0;
isForwarding = false;
if (isBackWard) {
isBackWard = 0;
isBackWard = false;
output.Mute(false);
}
isSlowMotion = 0;
isSlowMotion = false;
Speed = 1;
} else {
fprintf(stderr,"continue not possible\n");
@@ -219,87 +198,29 @@ bool Player::Continue()
bool Player::Stop()
{
bool ret = true;
int wait_time = 20;
if (isPlaying) {
isPaused = 0;
isPlaying = 0;
isForwarding = 0;
if (isBackWard) {
isBackWard = 0;
output.Mute(false);
}
isSlowMotion = 0;
Speed = 0;
isPaused = false;
isPlaying = false;
isForwarding = false;
if (isBackWard) {
isBackWard = false;
output.Mute(false);
}
isSlowMotion = false;
Speed = 0;
output.Stop();
input.Stop();
output.Stop();
input.Stop();
} else {
fprintf(stderr,"stop not possible\n");
ret = false;
}
while ((hasThreadStarted == 1) && (--wait_time) > 0) {
fprintf(stderr, "Waiting for supervisor thread to terminate itself, will try another %d times\n", wait_time);
while (hasThreadStarted)
usleep(100000);
}
if (wait_time == 0) {
fprintf(stderr,"Timeout waiting for thread!\n");
ret = false;
}
fprintf(stderr, "exiting with value %d\n", ret);
return ret;
}
// FIXME
bool Player::Terminate()
{
bool ret = true;
int wait_time = 20;
fprintf(stderr, "\n");
if (isPlaying) {
if (!abortRequested && !output.Flush()) {
fprintf(stderr,"failed to flush output.\n");
}
ret = input.Stop();
isPaused = 0;
isPlaying = 0;
isForwarding = 0;
isBackWard = 0;
isSlowMotion = 0;
Speed = 0;
} else {
/* fixme: konfetti: we should return an error here but this seems to be a condition which
* can happen and is not a real error, which leads to a dead neutrino. should investigate
* here later.
*/
}
while ((hasThreadStarted == 1) && (--wait_time) > 0) {
fprintf(stderr, "Waiting for supervisor thread to terminate itself, will try another %d times\n", wait_time);
usleep(100000);
}
if (wait_time == 0) {
fprintf(stderr,"Timeout waiting for thread!\n");
ret = false;
}
fprintf(stderr, "exiting with value %d\n", ret);
return ret;
}
@@ -309,7 +230,7 @@ bool Player::FastForward(int speed)
int ret = true;
/* Audio only forwarding not supported */
if (isVideo && !isHttp && !isBackWard && (!isPaused || isPlaying)) {
if (input.videoTrack && !isHttp && !isBackWard && (!isPaused || isPlaying)) {
if ((speed <= 0) || (speed > cMaxSpeed_ff)) {
fprintf(stderr, "speed %d out of range (1 - %d) \n", speed, cMaxSpeed_ff);
@@ -332,7 +253,7 @@ bool Player::FastBackward(int speed)
bool ret = true;
/* Audio only reverse play not supported */
if (isVideo && !isForwarding && (!isPaused || isPlaying)) {
if (input.videoTrack && !isForwarding && (!isPaused || isPlaying)) {
if ((speed > 0) || (speed < cMaxSpeed_fr)) {
fprintf(stderr, "speed %d out of range (0 - %d) \n", speed, cMaxSpeed_fr);
@@ -341,7 +262,7 @@ bool Player::FastBackward(int speed)
if (speed == 0) {
isBackWard = false;
Speed = false; /* reverse end */
Speed = 0; /* reverse end */
} else {
Speed = speed;
isBackWard = true;
@@ -351,7 +272,7 @@ bool Player::FastBackward(int speed)
#if 0
if (output->Command(player, OUTPUT_REVERSE, NULL) < 0) {
fprintf(stderr,"OUTPUT_REVERSE failed\n");
isBackWard = 0;
isBackWard = false;
Speed = 1;
ret = false;
}
@@ -369,7 +290,7 @@ bool Player::FastBackward(int speed)
bool Player::SlowMotion(int repeats)
{
if (isVideo && !isHttp && isPlaying) {
if (input.videoTrack && !isHttp && isPlaying) {
if (isPaused)
Continue();
@@ -398,56 +319,43 @@ bool Player::Seek(float pos, bool absolute)
bool Player::GetPts(int64_t &pts)
{
if (isPlaying)
return output.GetPts(pts);
return false;
pts = INVALID_PTS_VALUE;
return isPlaying && output.GetPts(pts);
}
bool Player::GetFrameCount(int64_t &frameCount)
{
if (isPlaying)
return output.GetFrameCount(frameCount);
return false;
return isPlaying && output.GetFrameCount(frameCount);
}
bool Player::GetDuration(double &duration)
{
duration = -1;
if (isPlaying)
return input.GetDuration(duration);
return false;
return isPlaying && input.GetDuration(duration);
}
bool Player::SwitchVideo(int pid)
{
Track *track = manager.getVideoTrack(pid);
if (track)
input.SwitchVideo(track);
return !!track;
return track && input.SwitchVideo(track);
}
bool Player::SwitchAudio(int pid)
{
Track *track = manager.getAudioTrack(pid);
if (track)
input.SwitchAudio(track);
return !!track;
return track && input.SwitchAudio(track);
}
bool Player::SwitchSubtitle(int pid)
{
Track *track = manager.getSubtitleTrack(pid);
if (track)
input.SwitchSubtitle(track);
return !!track;
return track && input.SwitchSubtitle(track);
}
bool Player::SwitchTeletext(int pid)
{
Track *track = manager.getTeletextTrack(pid);
if (track)
input.SwitchTeletext(track);
return !!track;
return track && input.SwitchTeletext(track);
}
bool Player::GetMetadata(std::vector<std::string> &keys, std::vector<std::string> &values)
@@ -473,3 +381,8 @@ void Player::SetChapters(std::vector<Chapter> &Chapters)
OpenThreads::ScopedLock<OpenThreads::Mutex> m_lock(chapterMutex);
chapters = Chapters;
}
void Player::RequestAbort()
{
abortRequested = true;
}

View File

@@ -1,12 +1,13 @@
/*
* linuxdvb output/writer handling.
* linuxdvb output/writer handling
*
* konfetti 2010 based on linuxdvb.c code from libeplayer2
* Copyright (C) 2010 konfetti (based on code from libeplayer2)
* Copyright (C) 2014 martii (based on code from libeplayer3)
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
@@ -15,8 +16,7 @@
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
#include <stdio.h>
@@ -33,11 +33,11 @@
class WriterAC3 : public Writer
{
public:
bool Write(int fd, AVFormatContext *avfc, AVStream *stream, AVPacket *packet, int64_t &pts);
bool Write(int fd, AVFormatContext *avfc, AVStream *stream, AVPacket *packet, int64_t pts);
WriterAC3();
};
bool WriterAC3::Write(int fd, AVFormatContext * /* avfc */, AVStream * /* stream */, AVPacket *packet, int64_t &pts)
bool WriterAC3::Write(int fd, AVFormatContext * /* avfc */, AVStream * /* stream */, AVPacket *packet, int64_t pts)
{
if (fd < 0 || !packet)
return false;

View File

@@ -1,12 +1,13 @@
/*
* linuxdvb output/writer handling.
* linuxdvb output/writer handling
*
* konfetti 2010 based on linuxdvb.c code from libeplayer2
* Copyright (C) 2010 konfetti (based on code from libeplayer2)
* Copyright (C) 2014 martii (based on code from libeplayer3)
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
@@ -15,8 +16,7 @@
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
#include <stdio.h>
@@ -26,14 +26,7 @@
#include <fcntl.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/ioctl.h>
#include <sys/uio.h>
#include <linux/dvb/video.h>
#include <linux/dvb/audio.h>
#include <linux/dvb/stm_ioctls.h>
#include <memory.h>
#include <asm/types.h>
#include <pthread.h>
#include <errno.h>
#include "misc.h"
@@ -45,7 +38,7 @@ class WriterDIVX : public Writer
private:
bool initialHeader;
public:
bool Write(int fd, AVFormatContext *avfc, AVStream *stream, AVPacket *packet, int64_t &pts);
bool Write(int fd, AVFormatContext *avfc, AVStream *stream, AVPacket *packet, int64_t pts);
void Init();
WriterDIVX();
};
@@ -55,7 +48,7 @@ void WriterDIVX::Init()
initialHeader = true;
}
bool WriterDIVX::Write(int fd, AVFormatContext * /* avfc */, AVStream *stream, AVPacket *packet, int64_t &pts)
bool WriterDIVX::Write(int fd, AVFormatContext * /* avfc */, AVStream *stream, AVPacket *packet, int64_t pts)
{
if (fd < 0 || !packet)
return false;

View File

@@ -1,12 +1,13 @@
/*
* linuxdvb output/writer handling.
* linuxdvb output/writer handling
*
* konfetti 2010 based on linuxdvb.c code from libeplayer2
* Copyright (C) 2010 konfetti (based on code from libeplayer2)
* Copyright (C) 2014 martii (based on code from libeplayer3)
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
@@ -15,8 +16,7 @@
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
#include <stdio.h>
@@ -36,11 +36,11 @@
class WriterDTS : public Writer
{
public:
bool Write(int fd, AVFormatContext *avfc, AVStream *stream, AVPacket *packet, int64_t &pts);
bool Write(int fd, AVFormatContext *avfc, AVStream *stream, AVPacket *packet, int64_t pts);
WriterDTS();
};
bool WriterDTS::Write(int fd, AVFormatContext * /* avfc */, AVStream * /* stream */, AVPacket *packet, int64_t &pts)
bool WriterDTS::Write(int fd, AVFormatContext * /* avfc */, AVStream * /* stream */, AVPacket *packet, int64_t pts)
{
if (fd < 0 || !packet)
return false;

View File

@@ -1,12 +1,13 @@
/*
* linuxdvb output/writer handling.
* linuxdvb output/writer handling
*
* konfetti 2010 based on linuxdvb.c code from libeplayer2
* Copyright (C) 2010 konfetti (based on code from libeplayer2)
* Copyright (C) 2014 martii (based on code from libeplayer3)
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
@@ -15,8 +16,7 @@
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
#include <stdio.h>
@@ -33,11 +33,11 @@
class WriterFLAC : public Writer
{
public:
bool Write(int fd, AVFormatContext * /* avfc */, AVStream *stream, AVPacket *packet, int64_t &pts);
bool Write(int fd, AVFormatContext * /* avfc */, AVStream *stream, AVPacket *packet, int64_t pts);
WriterFLAC();
};
bool WriterFLAC::Write(int fd, AVFormatContext * /* avfc */, AVStream * /* stream */, AVPacket *packet, int64_t &pts)
bool WriterFLAC::Write(int fd, AVFormatContext * /* avfc */, AVStream * /* stream */, AVPacket *packet, int64_t pts)
{
if (fd < 0 || !packet)
return -1;

View File

@@ -1,12 +1,14 @@
/*
* linuxdvb output/writer handling.
* linuxdvb output/writer handling
*
* crow 2010
* Copyright (C) 2010 crow
* Copyright (C) 2010 konfetti (based on code from libeplayer2)
* Copyright (C) 2014 martii (based on code from libeplayer3)
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
@@ -15,8 +17,7 @@
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
#include <stdio.h>
@@ -31,11 +32,11 @@
class WriterH263 : public Writer
{
public:
bool Write(int fd, AVFormatContext *avfc, AVStream *stream, AVPacket *packet, int64_t &pts);
bool Write(int fd, AVFormatContext *avfc, AVStream *stream, AVPacket *packet, int64_t pts);
WriterH263();
};
bool WriterH263::Write(int fd, AVFormatContext * /* avfc */, AVStream * /* stream */, AVPacket *packet, int64_t &pts)
bool WriterH263::Write(int fd, AVFormatContext * /* avfc */, AVStream * /* stream */, AVPacket *packet, int64_t pts)
{
if (fd < 0 || !packet)
return false;

View File

@@ -1,12 +1,15 @@
/*
* linuxdvb output/writer handling.
* linuxdvb output/writer handling
*
* konfetti 2010 based on linuxdvb.c code from libeplayer2
* Copyright (C) 2010 konfetti (based on code from libeplayer2)
* Copyright (C) 2014 martii (based on code from libeplayer3)
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
* Copyright (C) 2014 martii
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
@@ -15,8 +18,7 @@
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
#include <stdio.h>
@@ -52,7 +54,7 @@ class WriterH264 : public Writer
bool initialHeader;
unsigned int NalLengthBytes;
public:
bool Write(int fd, AVFormatContext *avfc, AVStream *stream, AVPacket *packet, int64_t &pts);
bool Write(int fd, AVFormatContext *avfc, AVStream *stream, AVPacket *packet, int64_t pts);
void Init();
WriterH264();
};
@@ -64,12 +66,11 @@ void WriterH264::Init(void)
NalLengthBytes = 1;
}
bool WriterH264::Write(int fd, AVFormatContext * /* avfc */, AVStream *stream, AVPacket *packet, int64_t &pts)
bool WriterH264::Write(int fd, AVFormatContext * /* avfc */, AVStream *stream, AVPacket *packet, int64_t pts)
{
if (fd < 0 || !packet)
return false;
unsigned char PesHeader[PES_MAX_HEADER_SIZE];
unsigned long long int VideoPts;
unsigned int TimeDelta;
unsigned int TimeScale;
int len = 0;
@@ -78,7 +79,6 @@ bool WriterH264::Write(int fd, AVFormatContext * /* avfc */, AVStream *stream, A
TimeDelta = 1000.0 * av_q2d(stream->r_frame_rate); /* rational to double */
TimeScale = (TimeDelta < 23970) ? 1001 : 1000; /* fixme: revise this */
VideoPts = pts;
if ((packet->size > 3)
&& ((packet->data[0] == 0x00 && packet->data[1] == 0x00 && packet->data[2] == 0x00 && packet->data[3] == 0x01)
@@ -251,13 +251,13 @@ bool WriterH264::Write(int fd, AVFormatContext * /* avfc */, AVStream *stream, A
iov[ic++].iov_len = NalLength;
VideoPosition += NalLength;
iov[0].iov_len = InsertPesHeader(PesHeader, NalLength, MPEG_VIDEO_PES_START_CODE, VideoPts, 0);
iov[0].iov_len = InsertPesHeader(PesHeader, NalLength, MPEG_VIDEO_PES_START_CODE, pts, 0);
ssize_t l = writev(fd, iov, ic);
if (l < 0)
return false;
len += l;
VideoPts = INVALID_PTS_VALUE;
pts = INVALID_PTS_VALUE;
}
} while (NalStart < SampleSize);

View File

@@ -1,12 +1,13 @@
/*
* linuxdvb output/writer handling.
* linuxdvb output/writer handling
*
* konfetti 2010 based on linuxdvb.c code from libeplayer2
* Copyright (C) 2010 konfetti (based on code from libeplayer2)
* Copyright (C) 2014 martii (based on code from libeplayer3)
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
@@ -15,8 +16,7 @@
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
#include <stdio.h>
@@ -33,11 +33,11 @@
class WriterMP3 : public Writer
{
public:
bool Write(int fd, AVFormatContext *avfc, AVStream *stream, AVPacket *packet, int64_t &pts);
bool Write(int fd, AVFormatContext *avfc, AVStream *stream, AVPacket *packet, int64_t pts);
WriterMP3();
};
bool WriterMP3::Write(int fd, AVFormatContext * /* avfc */, AVStream * /* stream */, AVPacket *packet, int64_t &pts)
bool WriterMP3::Write(int fd, AVFormatContext * /* avfc */, AVStream * /* stream */, AVPacket *packet, int64_t pts)
{
if (fd < 0 || !packet)
return false;

View File

@@ -1,12 +1,13 @@
/*
* linuxdvb output/writer handling.
* linuxdvb output/writer handling
*
* konfetti 2010 based on linuxdvb.c code from libeplayer2
* Copyright (C) 2010 konfetti (based on code from libeplayer2)
* Copyright (C) 2014 martii (based on code from libeplayer3)
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
@@ -15,8 +16,7 @@
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
#include <stdio.h>
@@ -35,24 +35,22 @@
class WriterMPEG2 : public Writer
{
public:
bool Write(int fd, AVFormatContext *avfc, AVStream *stream, AVPacket *packet, int64_t &pts);
bool Write(int fd, AVFormatContext *avfc, AVStream *stream, AVPacket *packet, int64_t pts);
WriterMPEG2();
};
bool WriterMPEG2::Write(int fd, AVFormatContext * /* avfc */, AVStream * /* stream */, AVPacket *packet, int64_t &pts)
bool WriterMPEG2::Write(int fd, AVFormatContext * /* avfc */, AVStream * /* stream */, AVPacket *packet, int64_t pts)
{
if (fd < 0 || !packet)
return false;
unsigned char PesHeader[PES_MAX_HEADER_SIZE];
int64_t _pts = pts;
for (int Position = 0; Position < packet->size; ) {
int PacketLength = std::min(packet->size - Position, MAX_PES_PACKET_SIZE);
struct iovec iov[2];
iov[0].iov_base = PesHeader;
iov[0].iov_len = InsertPesHeader(PesHeader, PacketLength, 0xe0, _pts, 0);
iov[0].iov_len = InsertPesHeader(PesHeader, PacketLength, 0xe0, pts, 0);
iov[1].iov_base = packet->data + Position;
iov[1].iov_len = PacketLength;
@@ -62,7 +60,7 @@ bool WriterMPEG2::Write(int fd, AVFormatContext * /* avfc */, AVStream * /* stre
break;
}
Position += PacketLength;
_pts = INVALID_PTS_VALUE;
pts = INVALID_PTS_VALUE;
}
return true;
}

View File

@@ -1,7 +1,8 @@
/*
* linuxdvb output/writer handling.
*
* konfetti 2010 based on linuxdvb.c code from libeplayer2
* Copyright (C) 2010 konfetti (based on code from libeplayer2)
* Copyright (C) 2014 martii (based on code from libeplayer3)
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -74,7 +75,7 @@ class WriterPCM : public Writer
bool restart_audio_resampling;
public:
bool Write(int fd, AVFormatContext *avfc, AVStream *stream, AVPacket *packet, int64_t &pts);
bool Write(int fd, AVFormatContext *avfc, AVStream *stream, AVPacket *packet, int64_t pts);
bool prepareClipPlay();
int writePCM(int fd, int64_t Pts, uint8_t *data, unsigned int size);
void Init();
@@ -230,7 +231,7 @@ void WriterPCM::Init()
extern int64_t calcPts(AVFormatContext *, AVStream *, int64_t);
bool WriterPCM::Write(int fd, AVFormatContext *avfc, AVStream *stream, AVPacket *packet, int64_t &pts)
bool WriterPCM::Write(int fd, AVFormatContext *avfc, AVStream *stream, AVPacket *packet, int64_t pts)
{
if (fd < 0)
return false;
@@ -325,7 +326,6 @@ bool WriterPCM::Write(int fd, AVFormatContext *avfc, AVStream *stream, AVPacket
continue;
}
// FIXME. PTS calculation is probably broken.
int64_t pts;
int64_t next_in_pts = av_rescale(av_frame_get_best_effort_timestamp(decoded_frame),
stream->time_base.num * (int64_t) out_sample_rate * c->sample_rate,
stream->time_base.den);

View File

@@ -1,7 +1,8 @@
/*
* linuxdvb output/writer handling.
*
* konfetti 2010 based on linuxdvb.c code from libeplayer2
* Copyright (C) 2010 konfetti (based on code from libeplayer2)
* Copyright (C) 2014 martii (based on code from libeplayer3)
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -19,10 +20,6 @@
*
*/
/* ***************************** */
/* Includes */
/* ***************************** */
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
@@ -35,87 +32,85 @@
int InsertVideoPrivateDataHeader(unsigned char *data, int payload_size)
{
BitPacker_t ld2 = { data, 0, 32 };
int i;
BitPacker_t ld2 = { data, 0, 32 };
int i;
PutBits(&ld2, PES_PRIVATE_DATA_FLAG, 8);
PutBits(&ld2, payload_size & 0xff, 8);
PutBits(&ld2, (payload_size >> 8) & 0xff, 8);
PutBits(&ld2, (payload_size >> 16) & 0xff, 8);
PutBits(&ld2, PES_PRIVATE_DATA_FLAG, 8);
PutBits(&ld2, payload_size & 0xff, 8);
PutBits(&ld2, (payload_size >> 8) & 0xff, 8);
PutBits(&ld2, (payload_size >> 16) & 0xff, 8);
for (i = 4; i < (PES_PRIVATE_DATA_LENGTH + 1); i++)
PutBits(&ld2, 0, 8);
for (i = 4; i < (PES_PRIVATE_DATA_LENGTH + 1); i++)
PutBits(&ld2, 0, 8);
FlushBits(&ld2);
FlushBits(&ld2);
return PES_PRIVATE_DATA_LENGTH + 1;
return PES_PRIVATE_DATA_LENGTH + 1;
}
int InsertPesHeader(unsigned char *data, int size, unsigned char stream_id,
unsigned long long int pts, int pic_start_code)
int InsertPesHeader(uint8_t *data, int size, unsigned char stream_id, int64_t pts, int pic_start_code)
{
BitPacker_t ld2 = { data, 0, 32 };
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
//4
PutBits(&ld2, size + 3 + (pts != INVALID_PTS_VALUE ? 5 : 0) + (pic_start_code ? (5) : 0), 16); // PES_packet_length
//6 = 4+2
PutBits(&ld2, 0x2, 2); // 10
PutBits(&ld2, 0x0, 2); // PES_Scrambling_control
PutBits(&ld2, 0x0, 1); // PES_Priority
PutBits(&ld2, 0x0, 1); // data_alignment_indicator
PutBits(&ld2, 0x0, 1); // Copyright
PutBits(&ld2, 0x0, 1); // Original or Copy
//7 = 6+1
if (pts != INVALID_PTS_VALUE)
PutBits(&ld2, 0x2, 2);
else
PutBits(&ld2, 0x0, 2); // PTS_DTS flag
PutBits(&ld2, 0x0, 1); // ESCR_flag
PutBits(&ld2, 0x0, 1); // ES_rate_flag
PutBits(&ld2, 0x0, 1); // DSM_trick_mode_flag
PutBits(&ld2, 0x0, 1); // additional_copy_ingo_flag
PutBits(&ld2, 0x0, 1); // PES_CRC_flag
PutBits(&ld2, 0x0, 1); // PES_extension_flag
//8 = 7+1
if (pts != INVALID_PTS_VALUE)
PutBits(&ld2, 0x5, 8);
else
PutBits(&ld2, 0x0, 8); // PES_header_data_length
//9 = 8+1
if (pts != INVALID_PTS_VALUE) {
PutBits(&ld2, 0x2, 4);
PutBits(&ld2, (pts >> 30) & 0x7, 3);
PutBits(&ld2, 0x1, 1);
PutBits(&ld2, (pts >> 15) & 0x7fff, 15);
PutBits(&ld2, 0x1, 1);
PutBits(&ld2, pts & 0x7fff, 15);
PutBits(&ld2, 0x1, 1);
}
//14 = 9+5
if (pic_start_code) {
PutBits(&ld2, 0x0, 8);
PutBits(&ld2, 0x0, 8);
PutBits(&ld2, 0x1, 8); // Start Code
PutBits(&ld2, pic_start_code & 0xff, 8); // 00, for picture start
PutBits(&ld2, (pic_start_code >> 8) & 0xff, 8); // For any extra information (like in mpeg4p2, the pic_start_code)
//14 + 4 = 18
}
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
//6 = 4+2
PutBits(&ld2, 0x2, 2); // 10
PutBits(&ld2, 0x0, 2); // PES_Scrambling_control
PutBits(&ld2, 0x0, 1); // PES_Priority
PutBits(&ld2, 0x0, 1); // data_alignment_indicator
PutBits(&ld2, 0x0, 1); // Copyright
PutBits(&ld2, 0x0, 1); // Original or Copy
//7 = 6+1
FlushBits(&ld2);
if (pts != INVALID_PTS_VALUE)
PutBits(&ld2, 0x2, 2);
else
PutBits(&ld2, 0x0, 2); // PTS_DTS flag
return (ld2.Ptr - data);
PutBits(&ld2, 0x0, 1); // ESCR_flag
PutBits(&ld2, 0x0, 1); // ES_rate_flag
PutBits(&ld2, 0x0, 1); // DSM_trick_mode_flag
PutBits(&ld2, 0x0, 1); // additional_copy_ingo_flag
PutBits(&ld2, 0x0, 1); // PES_CRC_flag
PutBits(&ld2, 0x0, 1); // PES_extension_flag
//8 = 7+1
if (pts != INVALID_PTS_VALUE)
PutBits(&ld2, 0x5, 8);
else
PutBits(&ld2, 0x0, 8); // PES_header_data_length
//9 = 8+1
if (pts != INVALID_PTS_VALUE) {
PutBits(&ld2, 0x2, 4);
PutBits(&ld2, (pts >> 30) & 0x7, 3);
PutBits(&ld2, 0x1, 1);
PutBits(&ld2, (pts >> 15) & 0x7fff, 15);
PutBits(&ld2, 0x1, 1);
PutBits(&ld2, pts & 0x7fff, 15);
PutBits(&ld2, 0x1, 1);
}
//14 = 9+5
if (pic_start_code) {
PutBits(&ld2, 0x0, 8);
PutBits(&ld2, 0x0, 8);
PutBits(&ld2, 0x1, 8); // Start Code
PutBits(&ld2, pic_start_code & 0xff, 8); // 00, for picture start
PutBits(&ld2, (pic_start_code >> 8) & 0xff, 8); // For any extra information (like in mpeg4p2, the pic_start_code)
//14 + 4 = 18
}
FlushBits(&ld2);
return (ld2.Ptr - data);
}

View File

@@ -1,12 +1,15 @@
/*
* linuxdvb output/writer handling.
* linuxdvb output/writer handling
*
* konfetti 2010 based on linuxdvb.c code from libeplayer2
* Copyright (C) 2010 konfetti (based on code from libeplayer2)
* Copyright (C) 2014 martii (based on code from libeplayer3)
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
* Copyright (C) 2014 martii
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
@@ -15,8 +18,7 @@
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
#include <stdio.h>
@@ -50,7 +52,7 @@ class WriterVC1 : public Writer
unsigned char FrameHeaderSeen;
double frameRate;
public:
bool Write(int fd, AVFormatContext *avfc, AVStream *stream, AVPacket *packet, int64_t &pts);
bool Write(int fd, AVFormatContext *avfc, AVStream *stream, AVPacket *packet, int64_t pts);
void Init();
WriterVC1();
};
@@ -60,7 +62,7 @@ void WriterVC1::Init()
initialHeader = true;
}
bool WriterVC1::Write(int fd, AVFormatContext *avfc, AVStream *stream, AVPacket *packet, int64_t &pts)
bool WriterVC1::Write(int fd, AVFormatContext * /* avfc */, AVStream *stream, AVPacket *packet, int64_t pts)
{
if (fd < 0 || !packet)
return false;
@@ -138,8 +140,6 @@ bool WriterVC1::Write(int fd, AVFormatContext *avfc, AVStream *stream, AVPacket
initialHeader = false;
}
int64_t _pts = pts;
if (packet->size > 0) {
int Position = 0;
unsigned char insertSampleHeader = 1;
@@ -147,7 +147,7 @@ bool WriterVC1::Write(int fd, AVFormatContext *avfc, AVStream *stream, AVPacket
while (Position < packet->size) {
int PacketLength = std::min(packet->size - Position, MAX_PES_PACKET_SIZE);
unsigned char PesHeader[PES_MAX_HEADER_SIZE];
int HeaderLength = InsertPesHeader(PesHeader, PacketLength, VC1_VIDEO_PES_START_CODE, _pts, 0);
int HeaderLength = InsertPesHeader(PesHeader, PacketLength, VC1_VIDEO_PES_START_CODE, pts, 0);
if (insertSampleHeader) {
const unsigned char Vc1FrameStartCode[] = { 0, 0, 1, VC1_FRAME_START_CODE };
@@ -172,7 +172,7 @@ bool WriterVC1::Write(int fd, AVFormatContext *avfc, AVStream *stream, AVPacket
return false;
Position += PacketLength;
_pts = INVALID_PTS_VALUE;
pts = INVALID_PTS_VALUE;
}
}

View File

@@ -1,12 +1,15 @@
/*
* linuxdvb output/writer handling.
* linuxdvb output/writer handling
*
* konfetti 2010 based on linuxdvb.c code from libeplayer2
* Copyright (C) 2010 konfetti (based on code from libeplayer2)
* Copyright (C) 2014 martii (based on code from libeplayer3)
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
* Copyright (C) 2014 martii
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
@@ -15,8 +18,7 @@
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
#include <stdio.h>
@@ -56,7 +58,7 @@ class WriterWMV : public Writer
private:
bool initialHeader;
public:
bool Write(int fd, AVFormatContext *avfc, AVStream *stream, AVPacket *packet, int64_t &pts);
bool Write(int fd, AVFormatContext *avfc, AVStream *stream, AVPacket *packet, int64_t pts);
void Init();
WriterWMV();
};
@@ -66,7 +68,7 @@ void WriterWMV::Init()
initialHeader = 1;
}
bool WriterWMV::Write(int fd, AVFormatContext * /* avfc */, AVStream *stream, AVPacket *packet, int64_t &pts)
bool WriterWMV::Write(int fd, AVFormatContext * /* avfc */, AVStream *stream, AVPacket *packet, int64_t pts)
{
if (fd < 0 || !packet)
return false;
@@ -120,14 +122,12 @@ bool WriterWMV::Write(int fd, AVFormatContext * /* avfc */, AVStream *stream, AV
int Position = 0;
bool insertSampleHeader = true;
uint64_t _pts = pts;
while (Position < packet->size) {
int PacketLength = std::min(packet->size - Position, MAX_PES_PACKET_SIZE);
unsigned char PesHeader[PES_MAX_HEADER_SIZE] = { 0 };
int HeaderLength = InsertPesHeader(PesHeader, PacketLength, VC1_VIDEO_PES_START_CODE, _pts, 0);
int HeaderLength = InsertPesHeader(PesHeader, PacketLength, VC1_VIDEO_PES_START_CODE, pts, 0);
if (insertSampleHeader) {
unsigned int PesLength;
@@ -152,7 +152,7 @@ bool WriterWMV::Write(int fd, AVFormatContext * /* avfc */, AVStream *stream, AV
return false;
Position += PacketLength;
_pts = INVALID_PTS_VALUE;
pts = INVALID_PTS_VALUE;
}
}

View File

@@ -1,12 +1,12 @@
/*
* linuxdvb output/writer handling.
* linuxdvb output/writer handling
*
* konfetti 2010
* Copyright (C) 2014 martii
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
@@ -15,19 +15,13 @@
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <unistd.h>
#include <fcntl.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/ioctl.h>
#include <sys/uio.h>
#include <string>
#include <map>
@@ -37,18 +31,17 @@
// This does suck ... the original idea was to just link the object files and let them register themselves.
// Alas, that didn't work as expected.
#include "ac3.cpp"
#include "divx.cpp"
#include "dts.cpp"
#include "flac.cpp"
#include "h263.cpp"
#include "h264.cpp"
#include "mp3.cpp"
#include "vc1.cpp"
#include "wmv.cpp"
#include "ac3.cpp"
#include "dts.cpp"
#include "flac.cpp"
#include "mpeg2.cpp"
#include "pcm.cpp"
#include "vc1.cpp"
#include "wmv.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)));
@@ -66,7 +59,7 @@ void Writer::Register(Writer *w, enum AVCodecID id, audio_encoding_t encoding)
aencoding[id] = encoding;
}
bool Writer::Write(int /* fd */, AVFormatContext * /* avfc */, AVStream * /*stream*/, AVPacket * /* packet */, int64_t & /* pts */)
bool Writer::Write(int /* fd */, AVFormatContext * /* avfc */, AVStream * /*stream*/, AVPacket * /* packet */, int64_t /* pts */)
{
return false;
}
@@ -75,26 +68,21 @@ static Writer writer __attribute__ ((init_priority (300)));
Writer *Writer::GetWriter(enum AVCodecID id, enum AVMediaType codec_type)
{
fprintf(stderr, "%s %s %d\n", __FILE__,__func__,__LINE__);
std::map<enum AVCodecID,Writer*>::iterator it = writers.find(id);
if (it != writers.end())
return it->second;
fprintf(stderr, "%s %s %d: no writer found\n", __FILE__,__func__,__LINE__);
switch (codec_type) {
case AVMEDIA_TYPE_AUDIO:
if (id == AV_CODEC_ID_INJECTPCM) // should not happen
break;
fprintf(stderr, "%s %s %d: returning injectpcm\n", __FILE__,__func__,__LINE__);
return GetWriter(AV_CODEC_ID_INJECTPCM, codec_type);
case AVMEDIA_TYPE_VIDEO:
if (id == AV_CODEC_ID_MPEG2TS) // should not happen
break;
fprintf(stderr, "%s %s %d: returning mpeg2video\n", __FILE__,__func__,__LINE__);
return GetWriter(AV_CODEC_ID_MPEG2TS, codec_type);
default:
break;
}
fprintf(stderr, "%s %s %d: returning dummy writer\n", __FILE__,__func__,__LINE__);
return &writer;
}