mirror of
https://github.com/tuxbox-neutrino/libstb-hal.git
synced 2025-08-26 23:13:16 +02:00
libeplayer3: continue refresh
This commit is contained in:
@@ -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
|
||||
|
||||
|
@@ -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:
|
||||
* -------
|
||||
|
@@ -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;
|
||||
|
@@ -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) {}
|
||||
};
|
||||
|
||||
@@ -50,6 +62,9 @@ class Manager
|
||||
Player *player;
|
||||
OpenThreads::Mutex mutex;
|
||||
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);
|
||||
|
@@ -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
|
||||
|
@@ -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
|
||||
|
@@ -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
|
||||
|
@@ -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() {}
|
||||
|
@@ -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) {
|
||||
@@ -148,16 +136,14 @@ bool Input::Play()
|
||||
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;
|
||||
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,59 +171,45 @@ 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;
|
||||
|
||||
pts = calcPts(avfc, _subtitleTrack->stream, packet.pts);
|
||||
|
||||
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;
|
||||
int got_sub_ptr = 0;
|
||||
|
||||
if (avcodec_decode_subtitle2(((AVStream *) _subtitleTrack->stream)->codec, &sub, &got_sub_ptr, &packet) < 0) {
|
||||
fprintf(stderr, "error decoding subtitle\n");
|
||||
}
|
||||
err = avcodec_decode_subtitle2(((AVStream *) _subtitleTrack->stream)->codec, &sub, &got_sub_ptr, &packet);
|
||||
averror(err, avcodec_decode_subtitle2);
|
||||
|
||||
if (got_sub_ptr && sub.num_rects > 0) {
|
||||
switch (sub.rects[0]->type) {
|
||||
@@ -245,16 +217,17 @@ bool Input::Play()
|
||||
case SUBTITLE_ASS:
|
||||
dvbsub_ass_write(((AVStream *) _subtitleTrack->stream)->codec, &sub, pid);
|
||||
break;
|
||||
case SUBTITLE_BITMAP:
|
||||
dvbsub_write(&sub, pts);
|
||||
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)
|
||||
|
@@ -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()
|
||||
|
@@ -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;
|
||||
|
@@ -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);
|
||||
|
||||
isCreationPhase = 1; // allows the created thread to go into wait mode
|
||||
ret = output.Play();
|
||||
|
||||
if (!ret) {
|
||||
isCreationPhase = 0; // allow thread to go into next state
|
||||
} else {
|
||||
isPlaying = 1;
|
||||
isPaused = 0;
|
||||
isForwarding = 0;
|
||||
if (ret) {
|
||||
isPlaying = true;
|
||||
isPaused = false;
|
||||
isForwarding = false;
|
||||
if (isBackWard) {
|
||||
isBackWard = 0;
|
||||
isBackWard = false;
|
||||
output.Mute(false);
|
||||
}
|
||||
isSlowMotion = 0;
|
||||
isSlowMotion = false;
|
||||
Speed = 1;
|
||||
|
||||
if (hasThreadStarted == 0) {
|
||||
int error;
|
||||
pthread_attr_init(&attr);
|
||||
pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
|
||||
|
||||
if ((error = pthread_create(&supervisorThread, &attr, SupervisorThread, this))) {
|
||||
fprintf(stderr, "Error creating thread, error:%d:%s\n", error, strerror(error));
|
||||
if (!hasThreadStarted) {
|
||||
int err = pthread_create(&supervisorThread, NULL, SupervisorThread, this);
|
||||
|
||||
if (err) {
|
||||
fprintf(stderr, "%s %s %d: pthread_create: %d (%s)\n", __FILE__, __func__, __LINE__, err, strerror(err));
|
||||
ret = false;
|
||||
isPlaying = false;
|
||||
} else {
|
||||
fprintf(stderr, "Created thread\n");
|
||||
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;
|
||||
}
|
||||
|
||||
@@ -169,22 +151,19 @@ bool Player::Pause()
|
||||
|
||||
output.Pause();
|
||||
|
||||
isPaused = 1;
|
||||
isPaused = true;
|
||||
//isPlaying = 1;
|
||||
isForwarding = 0;
|
||||
isForwarding = false;
|
||||
if (isBackWard) {
|
||||
isBackWard = 0;
|
||||
isBackWard = false;
|
||||
output.Mute(false);
|
||||
}
|
||||
isSlowMotion = 0;
|
||||
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,18 +198,17 @@ bool Player::Continue()
|
||||
bool Player::Stop()
|
||||
{
|
||||
bool ret = true;
|
||||
int wait_time = 20;
|
||||
|
||||
if (isPlaying) {
|
||||
|
||||
isPaused = 0;
|
||||
isPlaying = 0;
|
||||
isForwarding = 0;
|
||||
isPaused = false;
|
||||
isPlaying = false;
|
||||
isForwarding = false;
|
||||
if (isBackWard) {
|
||||
isBackWard = 0;
|
||||
isBackWard = false;
|
||||
output.Mute(false);
|
||||
}
|
||||
isSlowMotion = 0;
|
||||
isSlowMotion = false;
|
||||
Speed = 0;
|
||||
|
||||
output.Stop();
|
||||
@@ -241,65 +219,8 @@ bool Player::Stop()
|
||||
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;
|
||||
}
|
||||
|
@@ -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;
|
||||
|
@@ -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;
|
||||
|
@@ -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;
|
||||
|
@@ -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;
|
||||
|
@@ -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;
|
||||
|
@@ -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);
|
||||
|
||||
|
@@ -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;
|
||||
|
@@ -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;
|
||||
}
|
||||
|
@@ -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);
|
||||
|
@@ -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>
|
||||
@@ -52,8 +49,7 @@ int InsertVideoPrivateDataHeader(unsigned char *data, int payload_size)
|
||||
|
||||
}
|
||||
|
||||
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 };
|
||||
|
||||
@@ -117,5 +113,4 @@ int InsertPesHeader(unsigned char *data, int size, unsigned char stream_id,
|
||||
FlushBits(&ld2);
|
||||
|
||||
return (ld2.Ptr - data);
|
||||
|
||||
}
|
||||
|
@@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
|
@@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
|
@@ -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;
|
||||
}
|
||||
|
||||
|
@@ -47,8 +47,6 @@ bool cPlayback::Open(playmode_t PlayMode)
|
||||
nPlaybackSpeed = 0;
|
||||
init_jump = -1;
|
||||
|
||||
player = new Player();
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -81,23 +79,9 @@ bool cPlayback::Start(char *filename, int vpid, int vtype, int apid, int ac3, un
|
||||
mAudioStream=0;
|
||||
mSubtitleStream=-1;
|
||||
mTeletextStream=-1;
|
||||
char file[strlen(filename) + 1];
|
||||
*file = 0;
|
||||
|
||||
if (!strncmp("file://", filename, 7))
|
||||
filename += 7;
|
||||
|
||||
if(strstr(filename, "://"))
|
||||
isHTTP = true;
|
||||
else if (no_probe)
|
||||
strcat(file, "myts://");
|
||||
else
|
||||
strcat(file, "file://");
|
||||
|
||||
strcat(file, filename);
|
||||
|
||||
//try to open file
|
||||
if(player && player->Open(file)) {
|
||||
if(player && player->Open(filename, no_probe)) {
|
||||
if (pm != PLAYMODE_TS) {
|
||||
player->output.Open();
|
||||
|
||||
@@ -113,14 +97,11 @@ bool cPlayback::Start(char *filename, int vpid, int vtype, int apid, int ac3, un
|
||||
* with the exception of timeshift. but this should be handled
|
||||
* outside this lib or with another function!
|
||||
*/
|
||||
if (pm != PLAYMODE_TS)
|
||||
{
|
||||
if ((ret) && (!isHTTP))
|
||||
{
|
||||
if (pm != PLAYMODE_TS) {
|
||||
if ((ret) && (!isHTTP)) {
|
||||
//pause playback in case of timeshift
|
||||
//FIXME: no picture on tv
|
||||
if (!player || !player->Pause())
|
||||
{
|
||||
if (!player->Pause()) {
|
||||
ret = false;
|
||||
printf("failed to pause playback\n");
|
||||
} else
|
||||
@@ -135,13 +116,11 @@ bool cPlayback::Start(char *filename, int vpid, int vtype, int apid, int ac3, un
|
||||
if (fn_ts.rfind(".ts") == fn_ts.length() - 3)
|
||||
fn_xml = fn_ts.substr(0, fn_ts.length() - 3) + ".xml";
|
||||
|
||||
if (pm == PLAYMODE_TS)
|
||||
{
|
||||
if (pm == PLAYMODE_TS) {
|
||||
struct stat s;
|
||||
if (!stat(filename, &s))
|
||||
last_size = s.st_size;
|
||||
if (player)
|
||||
{
|
||||
if (player) {
|
||||
ret = true;
|
||||
videoDecoder->Stop(false);
|
||||
audioDecoder->Stop();
|
||||
@@ -156,18 +135,9 @@ bool cPlayback::Stop(void)
|
||||
printf("%s:%s playing %d\n", FILENAME, __FUNCTION__, playing);
|
||||
//if(playing==false) return false;
|
||||
|
||||
if(player)
|
||||
player->Stop();
|
||||
|
||||
if(player)
|
||||
player->output.Close();
|
||||
|
||||
if(player)
|
||||
player->Close();
|
||||
if(player) {
|
||||
delete player;
|
||||
player = NULL;
|
||||
}
|
||||
|
||||
playing=false;
|
||||
return true;
|
||||
@@ -177,7 +147,6 @@ bool cPlayback::SetAPid(int pid, bool ac3 __attribute__((unused)))
|
||||
{
|
||||
printf("%s:%s\n", FILENAME, __FUNCTION__);
|
||||
if(pid!=mAudioStream){
|
||||
if(player)
|
||||
player->SwitchAudio(pid);
|
||||
mAudioStream=pid;
|
||||
}
|
||||
@@ -188,7 +157,6 @@ bool cPlayback::SetSubtitlePid(int pid)
|
||||
{
|
||||
printf("%s:%s\n", FILENAME, __FUNCTION__);
|
||||
if(pid!=mSubtitleStream){
|
||||
if(player)
|
||||
player->SwitchSubtitle(pid);
|
||||
mSubtitleStream = pid;
|
||||
}
|
||||
@@ -199,7 +167,6 @@ bool cPlayback::SetTeletextPid(int pid)
|
||||
{
|
||||
printf("%s:%s\n", FILENAME, __FUNCTION__);
|
||||
if(pid!=mTeletextStream){
|
||||
if(player)
|
||||
player->SwitchTeletext(pid);
|
||||
mTeletextStream=pid;
|
||||
}
|
||||
@@ -216,70 +183,48 @@ bool cPlayback::SetSpeed(int speed)
|
||||
videoDecoder->closeDevice();
|
||||
decoders_closed = true;
|
||||
usleep(500000);
|
||||
if (player) {
|
||||
player->output.Open();
|
||||
playing = player->Play();
|
||||
}
|
||||
}
|
||||
|
||||
if(playing==false)
|
||||
return false;
|
||||
|
||||
if(player)
|
||||
{
|
||||
int result = 0;
|
||||
|
||||
nPlaybackSpeed = speed;
|
||||
|
||||
if (speed > 1)
|
||||
{
|
||||
if (speed > 1) {
|
||||
/* direction switch ? */
|
||||
if (player->isBackWard)
|
||||
{
|
||||
if (player->isBackWard) {
|
||||
result = player->FastBackward(0);
|
||||
|
||||
printf("result = %d\n", result);
|
||||
}
|
||||
result = player->FastForward(speed);
|
||||
} else
|
||||
if (speed < 0)
|
||||
{
|
||||
} else if (speed < 0) {
|
||||
/* direction switch ? */
|
||||
if (player->isForwarding)
|
||||
{
|
||||
if (player->isForwarding) {
|
||||
result = player->Continue();
|
||||
|
||||
printf("result = %d\n", result);
|
||||
}
|
||||
|
||||
result = player->FastBackward(speed);
|
||||
}
|
||||
else
|
||||
if (speed == 0)
|
||||
{
|
||||
} else if (speed == 0) {
|
||||
/* konfetti: hmmm accessing the member isn't very proper */
|
||||
if ((player->isForwarding) || (!player->isBackWard))
|
||||
player->Pause();
|
||||
else
|
||||
{
|
||||
else {
|
||||
player->FastForward(0);
|
||||
}
|
||||
} else
|
||||
{
|
||||
} else {
|
||||
result = player->Continue();
|
||||
}
|
||||
|
||||
if (init_jump > -1)
|
||||
{
|
||||
if (init_jump > -1) {
|
||||
SetPosition(init_jump);
|
||||
init_jump = -1;
|
||||
}
|
||||
if (result != 0)
|
||||
{
|
||||
if (!result) {
|
||||
printf("returning false\n");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -292,7 +237,6 @@ bool cPlayback::GetSpeed(int &speed) const
|
||||
|
||||
void cPlayback::GetPts(uint64_t &pts)
|
||||
{
|
||||
if (player)
|
||||
player->GetPts((int64_t &) pts);
|
||||
}
|
||||
|
||||
@@ -325,14 +269,13 @@ bool cPlayback::GetPosition(int &position, int &duration)
|
||||
|
||||
if(playing==false) return false;
|
||||
|
||||
if (player && !player->isPlaying) {
|
||||
if (!player->isPlaying) {
|
||||
printf("cPlayback::%s !!!!EOF!!!! < -1\n", __func__);
|
||||
position = duration + 1000;
|
||||
return false;
|
||||
}
|
||||
|
||||
int64_t vpts = 0;
|
||||
if(player)
|
||||
player->GetPts(vpts);
|
||||
|
||||
if(vpts <= 0) {
|
||||
@@ -347,7 +290,6 @@ bool cPlayback::GetPosition(int &position, int &duration)
|
||||
|
||||
double length = 0;
|
||||
|
||||
if(player)
|
||||
player->GetDuration(length);
|
||||
|
||||
if(length <= 0) {
|
||||
@@ -374,7 +316,6 @@ bool cPlayback::SetPosition(int position, bool absolute)
|
||||
return false;
|
||||
}
|
||||
float pos = (position/1000.0);
|
||||
if(player)
|
||||
player->Seek(pos, absolute);
|
||||
return true;
|
||||
}
|
||||
@@ -384,7 +325,6 @@ void cPlayback::FindAllPids(int *pids, unsigned int *ac3flags, unsigned int *num
|
||||
printf("%s:%s\n", FILENAME, __FUNCTION__);
|
||||
unsigned int i = 0;
|
||||
|
||||
if(player) {
|
||||
std::vector<Track> tracks = player->manager.getAudioTracks();
|
||||
for (std::vector<Track>::iterator it = tracks.begin(); it != tracks.end() && i < *numpids; ++it) {
|
||||
pids[i] = it->pid;
|
||||
@@ -392,7 +332,7 @@ void cPlayback::FindAllPids(int *pids, unsigned int *ac3flags, unsigned int *num
|
||||
language[i] = it->Name;
|
||||
i++;
|
||||
}
|
||||
}
|
||||
|
||||
*numpids = i;
|
||||
}
|
||||
|
||||
@@ -401,14 +341,13 @@ void cPlayback::FindAllSubtitlePids(int *pids, unsigned int *numpids, std::strin
|
||||
printf("%s:%s\n", FILENAME, __FUNCTION__);
|
||||
unsigned int i = 0;
|
||||
|
||||
if(player) {
|
||||
std::vector<Track> tracks = player->manager.getSubtitleTracks();
|
||||
for (std::vector<Track>::iterator it = tracks.begin(); it != tracks.end() && i < *numpids; ++it) {
|
||||
pids[i] = it->pid;
|
||||
language[i] = it->Name;
|
||||
i++;
|
||||
}
|
||||
}
|
||||
|
||||
*numpids = i;
|
||||
}
|
||||
|
||||
@@ -417,7 +356,6 @@ void cPlayback::FindAllTeletextsubtitlePids(int *pids, unsigned int *numpids, st
|
||||
printf("%s:%s\n", FILENAME, __FUNCTION__);
|
||||
unsigned int i = 0;
|
||||
|
||||
if(player) {
|
||||
std::vector<Track> tracks = player->manager.getTeletextTracks();
|
||||
for (std::vector<Track>::iterator it = tracks.begin(); it != tracks.end() && i < *numpids; ++it) {
|
||||
pids[i] = it->pid;
|
||||
@@ -428,37 +366,20 @@ void cPlayback::FindAllTeletextsubtitlePids(int *pids, unsigned int *numpids, st
|
||||
language[i] = std::string(tmp);
|
||||
i++;
|
||||
}
|
||||
}
|
||||
*numpids = i;
|
||||
}
|
||||
|
||||
int cPlayback::GetTeletextPid(void)
|
||||
{
|
||||
printf("%s:%s\n", FILENAME, __FUNCTION__);
|
||||
if(player) {
|
||||
std::vector<Track> tracks = player->manager.getTeletextTracks();
|
||||
for (std::vector<Track>::iterator it = tracks.begin(); it != tracks.end(); ++it) {
|
||||
if (it->type == 1)
|
||||
return it->pid;
|
||||
}
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
#if 0
|
||||
/* dummy functions for subtitles */
|
||||
void cPlayback::FindAllSubs(uint16_t * /*pids*/, unsigned short * /*supp*/, uint16_t *num, std::string * /*lang*/)
|
||||
{
|
||||
*num = 0;
|
||||
}
|
||||
|
||||
bool cPlayback::SelectSubtitles(int pid)
|
||||
{
|
||||
printf("%s:%s pid %d\n", FILENAME, __func__, pid);
|
||||
return false;
|
||||
}
|
||||
#endif
|
||||
|
||||
void cPlayback::GetChapters(std::vector<int> &positions, std::vector<std::string> &titles)
|
||||
{
|
||||
player->GetChapters(positions, titles);
|
||||
@@ -467,8 +388,6 @@ void cPlayback::GetChapters(std::vector<int> &positions, std::vector<std::string
|
||||
void cPlayback::GetMetadata(std::vector<std::string> &keys, std::vector<std::string> &values)
|
||||
{
|
||||
printf("%s:%s\n", FILENAME, __FUNCTION__);
|
||||
if (!player)
|
||||
return;
|
||||
player->input.GetMetadata(keys, values);
|
||||
}
|
||||
|
||||
@@ -476,23 +395,24 @@ cPlayback::cPlayback(int num __attribute__((unused)))
|
||||
{
|
||||
printf("%s:%s\n", FILENAME, __FUNCTION__);
|
||||
playing=false;
|
||||
|
||||
player = new Player();
|
||||
}
|
||||
|
||||
cPlayback::~cPlayback()
|
||||
{
|
||||
printf("%s:%s\n", FILENAME, __FUNCTION__);
|
||||
if(player)
|
||||
delete player;
|
||||
}
|
||||
|
||||
void cPlayback::RequestAbort() {
|
||||
if (player) {
|
||||
player->abortRequested = 1;
|
||||
player->RequestAbort();
|
||||
while (player->isPlaying)
|
||||
usleep(100000);
|
||||
}
|
||||
}
|
||||
|
||||
bool cPlayback::IsPlaying() {
|
||||
if (player)
|
||||
return player->isPlaying;
|
||||
return false;
|
||||
}
|
||||
|
Reference in New Issue
Block a user