mirror of
https://github.com/tuxbox-neutrino/libstb-hal.git
synced 2025-08-27 07:23:11 +02:00
libeplayer3: modify fast-backward
This commit is contained in:
@@ -25,6 +25,7 @@
|
|||||||
|
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
|
#include <stdint.h>
|
||||||
#include <sys/ioctl.h>
|
#include <sys/ioctl.h>
|
||||||
#include <fcntl.h>
|
#include <fcntl.h>
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
@@ -111,7 +112,7 @@ static long long int latestPts = 0;
|
|||||||
static int restart_audio_resampling = 0;
|
static int restart_audio_resampling = 0;
|
||||||
static off_t seek_target_bytes = 0;
|
static off_t seek_target_bytes = 0;
|
||||||
static int do_seek_target_bytes = 0;
|
static int do_seek_target_bytes = 0;
|
||||||
static float seek_target_seconds = 0.0;
|
static int64_t seek_target_seconds = 0.0;
|
||||||
static int do_seek_target_seconds = 0;
|
static int do_seek_target_seconds = 0;
|
||||||
static int seek_target_flag = 0;
|
static int seek_target_flag = 0;
|
||||||
|
|
||||||
@@ -120,7 +121,6 @@ static int seek_target_flag = 0;
|
|||||||
/* ***************************** */
|
/* ***************************** */
|
||||||
static int container_ffmpeg_seek_bytes(off_t pos);
|
static int container_ffmpeg_seek_bytes(off_t pos);
|
||||||
static int container_ffmpeg_seek(Context_t *context, float sec, int absolute);
|
static int container_ffmpeg_seek(Context_t *context, float sec, int absolute);
|
||||||
static int container_ffmpeg_seek_rel(Context_t *context, off_t pos, long long int pts, float sec);
|
|
||||||
|
|
||||||
/* ***************************** */
|
/* ***************************** */
|
||||||
/* MISC Functions */
|
/* MISC Functions */
|
||||||
@@ -328,9 +328,7 @@ static void FFMPEGThread(Context_t *context) {
|
|||||||
strncpy(threadname, __func__, sizeof(threadname));
|
strncpy(threadname, __func__, sizeof(threadname));
|
||||||
threadname[16] = 0;
|
threadname[16] = 0;
|
||||||
prctl (PR_SET_NAME, (unsigned long)&threadname);
|
prctl (PR_SET_NAME, (unsigned long)&threadname);
|
||||||
off_t lastSeek = -1;
|
int64_t lastPts = -1, currentVideoPts = -1, currentAudioPts = -1, showtime = 0, bofcount = 0;
|
||||||
long long int lastPts = -1, currentVideoPts = -1, currentAudioPts = -1, showtime = 0, bofcount = 0;
|
|
||||||
int err = 0;
|
|
||||||
AudioVideoOut_t avOut;
|
AudioVideoOut_t avOut;
|
||||||
|
|
||||||
SwrContext *swr = NULL;
|
SwrContext *swr = NULL;
|
||||||
@@ -383,32 +381,36 @@ static void FFMPEGThread(Context_t *context) {
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(lastPts == -1)
|
if (lastPts < 0)
|
||||||
{
|
lastPts = (currentVideoPts > 0) ? currentVideoPts : currentAudioPts;
|
||||||
if(currentVideoPts != -1)
|
|
||||||
lastPts = currentVideoPts;
|
|
||||||
else
|
|
||||||
lastPts = currentAudioPts;
|
|
||||||
}
|
|
||||||
|
|
||||||
if((err = container_ffmpeg_seek_rel(context, lastSeek, lastPts, (float) context->playback->Speed)) < 0)
|
if (lastPts > 0) {
|
||||||
{
|
do_seek_target_seconds = 1;
|
||||||
ffmpeg_err( "Error seeking\n");
|
do_seek_target_bytes = 0;
|
||||||
|
lastPts += context->playback->Speed * 8 * AV_TIME_BASE;
|
||||||
if (err == cERR_CONTAINER_FFMPEG_END_OF_FILE)
|
seek_target_seconds = lastPts;
|
||||||
{
|
seek_target_flag = 0;
|
||||||
bofcount = 1;
|
showtime = av_gettime() + 300000; //jump back every 300ms
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
|
bofcount = 0;
|
||||||
|
if (!context->playback->BackWard)
|
||||||
|
lastPts = -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (do_seek_target_seconds || do_seek_target_bytes) {
|
if (do_seek_target_seconds || do_seek_target_bytes) {
|
||||||
|
int res;
|
||||||
if (do_seek_target_seconds) {
|
if (do_seek_target_seconds) {
|
||||||
float seek_target_seconds_min = seek_target_seconds - 15 * AV_TIME_BASE;
|
int64_t seek_target_seconds_min = seek_target_seconds - 15 * AV_TIME_BASE;
|
||||||
|
if (seek_target_seconds < 0)
|
||||||
avformat_seek_file(avContext, -1, seek_target_seconds_min, seek_target_seconds, INT64_MAX, seek_target_flag);
|
seek_target_seconds = 0;
|
||||||
|
if (seek_target_seconds_min < 0)
|
||||||
|
seek_target_seconds_min = 0;
|
||||||
|
res = avformat_seek_file(avContext, -1, seek_target_seconds_min, seek_target_seconds, INT64_MAX, seek_target_flag);
|
||||||
} else
|
} else
|
||||||
container_ffmpeg_seek_bytes(seek_target_bytes);
|
res = container_ffmpeg_seek_bytes(seek_target_bytes);
|
||||||
|
if (res < 0 && context->playback->BackWard)
|
||||||
|
bofcount = 1;
|
||||||
do_seek_target_seconds = do_seek_target_bytes = 0;
|
do_seek_target_seconds = do_seek_target_bytes = 0;
|
||||||
restart_audio_resampling = 1;
|
restart_audio_resampling = 1;
|
||||||
latestPts = 0;
|
latestPts = 0;
|
||||||
@@ -419,12 +421,7 @@ static void FFMPEGThread(Context_t *context) {
|
|||||||
for (i = 0; i < avContext->nb_streams; i++)
|
for (i = 0; i < avContext->nb_streams; i++)
|
||||||
if (avContext->streams[i]->codec && avContext->streams[i]->codec->codec)
|
if (avContext->streams[i]->codec && avContext->streams[i]->codec->codec)
|
||||||
avcodec_flush_buffers(avContext->streams[i]->codec);
|
avcodec_flush_buffers(avContext->streams[i]->codec);
|
||||||
}
|
|
||||||
|
|
||||||
if (context->playback->BackWard) {
|
|
||||||
lastPts = lastPts + (context->playback->Speed * 90000);
|
|
||||||
showtime = av_gettime() + 300000; //jump back all 300ms
|
|
||||||
context->output->Command(context, OUTPUT_AUDIOMUTE, "0");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
AVPacket packet;
|
AVPacket packet;
|
||||||
@@ -1429,13 +1426,9 @@ static int container_ffmpeg_stop(Context_t *context) {
|
|||||||
|
|
||||||
static int container_ffmpeg_seek_bytes(off_t pos) {
|
static int container_ffmpeg_seek_bytes(off_t pos) {
|
||||||
int flag = AVSEEK_FLAG_BYTE;
|
int flag = AVSEEK_FLAG_BYTE;
|
||||||
off_t current_pos = avio_tell(avContext->pb);
|
|
||||||
|
|
||||||
ffmpeg_printf(20, "seeking to position %lld (bytes)\n", pos);
|
ffmpeg_printf(20, "seeking to position %lld (bytes)\n", pos);
|
||||||
|
|
||||||
if (current_pos > pos)
|
|
||||||
flag |= AVSEEK_FLAG_BACKWARD;
|
|
||||||
|
|
||||||
if (avformat_seek_file(avContext, -1, INT64_MIN, pos, INT64_MAX, flag) < 0)
|
if (avformat_seek_file(avContext, -1, INT64_MIN, pos, INT64_MAX, flag) < 0)
|
||||||
{
|
{
|
||||||
ffmpeg_err( "Error seeking\n");
|
ffmpeg_err( "Error seeking\n");
|
||||||
@@ -1447,86 +1440,6 @@ static int container_ffmpeg_seek_bytes(off_t pos) {
|
|||||||
return cERR_CONTAINER_FFMPEG_NO_ERROR;
|
return cERR_CONTAINER_FFMPEG_NO_ERROR;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* seeking relative to a given byteposition N seconds ->for reverse playback needed */
|
|
||||||
static int container_ffmpeg_seek_rel(Context_t *context, off_t pos, long long int pts, float sec) {
|
|
||||||
Track_t * videoTrack = NULL;
|
|
||||||
Track_t * audioTrack = NULL;
|
|
||||||
Track_t * current = NULL;
|
|
||||||
seek_target_flag = 0;
|
|
||||||
|
|
||||||
ffmpeg_printf(10, "seeking %f sec relativ to %lld\n", sec, pos);
|
|
||||||
|
|
||||||
context->manager->video->Command(context, MANAGER_GET_TRACK, &videoTrack);
|
|
||||||
context->manager->audio->Command(context, MANAGER_GET_TRACK, &audioTrack);
|
|
||||||
|
|
||||||
if (videoTrack != NULL)
|
|
||||||
current = videoTrack;
|
|
||||||
else if (audioTrack != NULL)
|
|
||||||
current = audioTrack;
|
|
||||||
|
|
||||||
if (current == NULL) {
|
|
||||||
ffmpeg_err( "no track avaibale to seek\n");
|
|
||||||
return cERR_CONTAINER_FFMPEG_ERR;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (pos == -1)
|
|
||||||
{
|
|
||||||
pos = avio_tell(avContext->pb);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (pts == -1)
|
|
||||||
pts = current->pts;
|
|
||||||
|
|
||||||
if (sec < 0)
|
|
||||||
seek_target_flag |= AVSEEK_FLAG_BACKWARD;
|
|
||||||
|
|
||||||
ffmpeg_printf(10, "iformat->flags %d\n", avContext->iformat->flags);
|
|
||||||
|
|
||||||
if (avContext->iformat->flags & AVFMT_TS_DISCONT)
|
|
||||||
{
|
|
||||||
if (avContext->bit_rate)
|
|
||||||
{
|
|
||||||
sec *= avContext->bit_rate / 8.0;
|
|
||||||
ffmpeg_printf(10, "bit_rate %d\n", avContext->bit_rate);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
sec *= 180000.0;
|
|
||||||
}
|
|
||||||
|
|
||||||
pos += sec;
|
|
||||||
|
|
||||||
if (pos < 0)
|
|
||||||
{
|
|
||||||
ffmpeg_err("end of file reached\n");
|
|
||||||
releaseMutex(FILENAME, __FUNCTION__,__LINE__);
|
|
||||||
return cERR_CONTAINER_FFMPEG_END_OF_FILE;
|
|
||||||
}
|
|
||||||
|
|
||||||
ffmpeg_printf(10, "1. seeking to position %lld bytes ->sec %f\n", pos, sec);
|
|
||||||
|
|
||||||
seek_target_bytes = pos;
|
|
||||||
do_seek_target_bytes = 1;
|
|
||||||
|
|
||||||
return pos;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
sec += ((float) pts / 90000.0f);
|
|
||||||
|
|
||||||
if (sec < 0)
|
|
||||||
sec = 0;
|
|
||||||
|
|
||||||
ffmpeg_printf(10, "2. seeking to position %f sec ->time base %f %d\n", sec, av_q2d(((AVStream*) current->stream)->time_base), AV_TIME_BASE);
|
|
||||||
|
|
||||||
seek_target_seconds = sec * AV_TIME_BASE;
|
|
||||||
do_seek_target_seconds = 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
releaseMutex(FILENAME, __FUNCTION__,__LINE__);
|
|
||||||
return cERR_CONTAINER_FFMPEG_NO_ERROR;
|
|
||||||
}
|
|
||||||
|
|
||||||
static int container_ffmpeg_seek(Context_t *context, float sec, int absolute) {
|
static int container_ffmpeg_seek(Context_t *context, float sec, int absolute) {
|
||||||
Track_t * videoTrack = NULL;
|
Track_t * videoTrack = NULL;
|
||||||
Track_t * audioTrack = NULL;
|
Track_t * audioTrack = NULL;
|
||||||
@@ -1560,9 +1473,6 @@ static int container_ffmpeg_seek(Context_t *context, float sec, int absolute) {
|
|||||||
return cERR_CONTAINER_FFMPEG_ERR;
|
return cERR_CONTAINER_FFMPEG_ERR;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (sec < 0)
|
|
||||||
seek_target_flag |= AVSEEK_FLAG_BACKWARD;
|
|
||||||
|
|
||||||
getMutex(FILENAME, __FUNCTION__,__LINE__);
|
getMutex(FILENAME, __FUNCTION__,__LINE__);
|
||||||
|
|
||||||
if (!context->playback || !context->playback->isPlaying) {
|
if (!context->playback || !context->playback->isPlaying) {
|
||||||
|
@@ -18,7 +18,7 @@ typedef struct PlaybackHandler_s {
|
|||||||
unsigned char isSeeking;
|
unsigned char isSeeking;
|
||||||
unsigned char isCreationPhase;
|
unsigned char isCreationPhase;
|
||||||
|
|
||||||
float BackWard;
|
int BackWard;
|
||||||
int SlowMotion;
|
int SlowMotion;
|
||||||
int Speed;
|
int Speed;
|
||||||
int AVSync;
|
int AVSync;
|
||||||
|
@@ -294,7 +294,10 @@ static int PlaybackPlay(Context_t *context) {
|
|||||||
context->playback->isPlaying = 1;
|
context->playback->isPlaying = 1;
|
||||||
context->playback->isPaused = 0;
|
context->playback->isPaused = 0;
|
||||||
context->playback->isForwarding = 0;
|
context->playback->isForwarding = 0;
|
||||||
|
if (context->playback->BackWard) {
|
||||||
context->playback->BackWard = 0;
|
context->playback->BackWard = 0;
|
||||||
|
context->output->Command(context, OUTPUT_AUDIOMUTE, "0");
|
||||||
|
}
|
||||||
context->playback->SlowMotion = 0;
|
context->playback->SlowMotion = 0;
|
||||||
context->playback->Speed = 1;
|
context->playback->Speed = 1;
|
||||||
|
|
||||||
@@ -355,7 +358,10 @@ static int PlaybackPause(Context_t *context) {
|
|||||||
context->playback->isPaused = 1;
|
context->playback->isPaused = 1;
|
||||||
//context->playback->isPlaying = 1;
|
//context->playback->isPlaying = 1;
|
||||||
context->playback->isForwarding = 0;
|
context->playback->isForwarding = 0;
|
||||||
|
if (context->playback->BackWard) {
|
||||||
context->playback->BackWard = 0;
|
context->playback->BackWard = 0;
|
||||||
|
context->output->Command(context, OUTPUT_AUDIOMUTE, "0");
|
||||||
|
}
|
||||||
context->playback->SlowMotion = 0;
|
context->playback->SlowMotion = 0;
|
||||||
context->playback->Speed = 1;
|
context->playback->Speed = 1;
|
||||||
} else
|
} else
|
||||||
@@ -385,7 +391,10 @@ static int PlaybackContinue(Context_t *context) {
|
|||||||
context->playback->isPaused = 0;
|
context->playback->isPaused = 0;
|
||||||
//context->playback->isPlaying = 1;
|
//context->playback->isPlaying = 1;
|
||||||
context->playback->isForwarding = 0;
|
context->playback->isForwarding = 0;
|
||||||
|
if (context->playback->BackWard) {
|
||||||
context->playback->BackWard = 0;
|
context->playback->BackWard = 0;
|
||||||
|
context->output->Command(context, OUTPUT_AUDIOMUTE, "0");
|
||||||
|
}
|
||||||
context->playback->SlowMotion = 0;
|
context->playback->SlowMotion = 0;
|
||||||
context->playback->Speed = 1;
|
context->playback->Speed = 1;
|
||||||
} else
|
} else
|
||||||
@@ -410,7 +419,10 @@ static int PlaybackStop(Context_t *context) {
|
|||||||
context->playback->isPaused = 0;
|
context->playback->isPaused = 0;
|
||||||
context->playback->isPlaying = 0;
|
context->playback->isPlaying = 0;
|
||||||
context->playback->isForwarding = 0;
|
context->playback->isForwarding = 0;
|
||||||
|
if (context->playback->BackWard) {
|
||||||
context->playback->BackWard = 0;
|
context->playback->BackWard = 0;
|
||||||
|
context->output->Command(context, OUTPUT_AUDIOMUTE, "0");
|
||||||
|
}
|
||||||
context->playback->SlowMotion = 0;
|
context->playback->SlowMotion = 0;
|
||||||
context->playback->Speed = 0;
|
context->playback->Speed = 0;
|
||||||
|
|
||||||
@@ -543,12 +555,11 @@ static int PlaybackFastBackward(Context_t *context,int* speed) {
|
|||||||
{
|
{
|
||||||
context->playback->isSeeking = 1;
|
context->playback->isSeeking = 1;
|
||||||
context->playback->Speed = *speed;
|
context->playback->Speed = *speed;
|
||||||
context->playback->BackWard = 2^(*speed);
|
context->playback->BackWard = 1;
|
||||||
|
|
||||||
playback_printf(1, "S %d B %f\n", context->playback->Speed, context->playback->BackWard);
|
playback_printf(1, "S %d B %d\n", context->playback->Speed, context->playback->BackWard);
|
||||||
}
|
}
|
||||||
|
|
||||||
context->output->Command(context, OUTPUT_AUDIOMUTE, "1");
|
|
||||||
context->output->Command(context, OUTPUT_CLEAR, NULL);
|
context->output->Command(context, OUTPUT_CLEAR, NULL);
|
||||||
if (context->output->Command(context, OUTPUT_REVERSE, NULL) < 0)
|
if (context->output->Command(context, OUTPUT_REVERSE, NULL) < 0)
|
||||||
{
|
{
|
||||||
@@ -564,6 +575,8 @@ static int PlaybackFastBackward(Context_t *context,int* speed) {
|
|||||||
ret = cERR_PLAYBACK_ERROR;
|
ret = cERR_PLAYBACK_ERROR;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (context->playback->BackWard)
|
||||||
|
context->output->Command(context, OUTPUT_AUDIOMUTE, "1");
|
||||||
context->playback->isSeeking = 0;
|
context->playback->isSeeking = 0;
|
||||||
playback_printf(10, "exiting with value %d\n", ret);
|
playback_printf(10, "exiting with value %d\n", ret);
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user