diff options
-rw-r--r-- | CMakeLists.txt | 2 | ||||
-rw-r--r-- | debian/.git-dpm | 14 | ||||
-rw-r--r-- | include/kitchensink/internal/kitdecoder.h | 1 | ||||
-rw-r--r-- | include/kitchensink/internal/subtitle/renderers/kitsubrenderer.h | 4 | ||||
-rw-r--r-- | include/kitchensink/internal/utils/kitbuffer.h | 1 | ||||
-rw-r--r-- | src/internal/audio/kitaudio.c | 55 | ||||
-rw-r--r-- | src/internal/kitdecoder.c | 41 | ||||
-rw-r--r-- | src/internal/subtitle/kitsubtitle.c | 6 | ||||
-rw-r--r-- | src/internal/subtitle/renderers/kitsubass.c | 33 | ||||
-rw-r--r-- | src/internal/subtitle/renderers/kitsubimage.c | 4 | ||||
-rw-r--r-- | src/internal/subtitle/renderers/kitsubrenderer.c | 4 | ||||
-rw-r--r-- | src/internal/utils/kitbuffer.c | 4 | ||||
-rw-r--r-- | src/internal/utils/kitringbuffer.c | 33 | ||||
-rw-r--r-- | src/internal/video/kitvideo.c | 41 | ||||
-rw-r--r-- | src/kitplayer.c | 2 | ||||
-rw-r--r-- | src/kitsource.c | 8 |
16 files changed, 153 insertions, 100 deletions
diff --git a/CMakeLists.txt b/CMakeLists.txt index bbe8fa0..0922eaa 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -5,7 +5,7 @@ set(CMAKE_MODULE_PATH ${PROJECT_SOURCE_DIR}/cmake) set(KIT_VERSION_MAJOR "1") set(KIT_VERSION_MINOR "0") -set(KIT_VERSION_PATCH "5") +set(KIT_VERSION_PATCH "6") set(KIT_VERSION ${KIT_VERSION_MAJOR}.${KIT_VERSION_MINOR}.${KIT_VERSION_PATCH}) add_definitions( -DKIT_VERSION_MAJOR=${KIT_VERSION_MAJOR} diff --git a/debian/.git-dpm b/debian/.git-dpm index 1fe78de..2ac5733 100644 --- a/debian/.git-dpm +++ b/debian/.git-dpm @@ -1,8 +1,8 @@ # see git-dpm(1) from git-dpm package -c678b8ac9c590326fc7e7aefd254c910297f2096 -c678b8ac9c590326fc7e7aefd254c910297f2096 -c678b8ac9c590326fc7e7aefd254c910297f2096 -c678b8ac9c590326fc7e7aefd254c910297f2096 -sdl-kitchensink_1.0.5.orig.tar.gz -3f041f644977d709b1d9647bba505c9f46396435 -68427 +25747441205f7973ea8815f1014372378ff34858 +25747441205f7973ea8815f1014372378ff34858 +25747441205f7973ea8815f1014372378ff34858 +25747441205f7973ea8815f1014372378ff34858 +sdl-kitchensink_1.0.6.orig.tar.gz +bd681b4c4913077449985126cc9ec71546164a88 +69103 diff --git a/include/kitchensink/internal/kitdecoder.h b/include/kitchensink/internal/kitdecoder.h index ef3edb7..74134b0 100644 --- a/include/kitchensink/internal/kitdecoder.h +++ b/include/kitchensink/internal/kitdecoder.h @@ -70,6 +70,7 @@ KIT_LOCAL void Kit_ForEachDecoderOutput(Kit_Decoder *dec, Kit_ForEachItemCallbac KIT_LOCAL int Kit_LockDecoderOutput(Kit_Decoder *dec);
KIT_LOCAL void Kit_UnlockDecoderOutput(Kit_Decoder *dec);
KIT_LOCAL void Kit_ClearDecoderOutput(Kit_Decoder *dec);
+KIT_LOCAL unsigned int Kit_GetDecoderOutputLength(Kit_Decoder *dec);
#endif // KITDECODER_H
diff --git a/include/kitchensink/internal/subtitle/renderers/kitsubrenderer.h b/include/kitchensink/internal/subtitle/renderers/kitsubrenderer.h index 3c37b00..8b35c2b 100644 --- a/include/kitchensink/internal/subtitle/renderers/kitsubrenderer.h +++ b/include/kitchensink/internal/subtitle/renderers/kitsubrenderer.h @@ -9,7 +9,7 @@ typedef struct Kit_SubtitleRenderer Kit_SubtitleRenderer; typedef struct Kit_TextureAtlas Kit_TextureAtlas;
typedef struct Kit_Decoder Kit_Decoder;
-typedef void (*ren_render_cb)(Kit_SubtitleRenderer *ren, void *src, double start_pts, double end_pts);
+typedef void (*ren_render_cb)(Kit_SubtitleRenderer *ren, void *src, double pts, double start, double end);
typedef int (*ren_get_data_cb)(Kit_SubtitleRenderer *ren, Kit_TextureAtlas *atlas, SDL_Texture *texture, double current_pts);
typedef void (*ren_set_size_cb)(Kit_SubtitleRenderer *ren, int w, int h);
typedef void (*ren_close_cb)(Kit_SubtitleRenderer *ren);
@@ -24,7 +24,7 @@ struct Kit_SubtitleRenderer { };
KIT_LOCAL Kit_SubtitleRenderer* Kit_CreateSubtitleRenderer(Kit_Decoder *dec);
-KIT_LOCAL void Kit_RunSubtitleRenderer(Kit_SubtitleRenderer *ren, void *src, double start_pts, double end_pts);
+KIT_LOCAL void Kit_RunSubtitleRenderer(Kit_SubtitleRenderer *ren, void *src, double pts, double start, double end);
KIT_LOCAL int Kit_GetSubtitleRendererData(Kit_SubtitleRenderer *ren, Kit_TextureAtlas *atlas, SDL_Texture *texture, double current_pts);
KIT_LOCAL void Kit_SetSubtitleRendererSize(Kit_SubtitleRenderer *ren, int w, int h);
KIT_LOCAL void Kit_CloseSubtitleRenderer(Kit_SubtitleRenderer *ren);
diff --git a/include/kitchensink/internal/utils/kitbuffer.h b/include/kitchensink/internal/utils/kitbuffer.h index 67d93c3..95d75b5 100644 --- a/include/kitchensink/internal/utils/kitbuffer.h +++ b/include/kitchensink/internal/utils/kitbuffer.h @@ -19,6 +19,7 @@ struct Kit_Buffer { KIT_LOCAL Kit_Buffer* Kit_CreateBuffer(unsigned int size, Kit_BufferFreeCallback free_cb); KIT_LOCAL void Kit_DestroyBuffer(Kit_Buffer *buffer); +KIT_LOCAL unsigned int Kit_GetBufferLength(const Kit_Buffer *buffer); KIT_LOCAL void Kit_ClearBuffer(Kit_Buffer *buffer); KIT_LOCAL void* Kit_ReadBuffer(Kit_Buffer *buffer); KIT_LOCAL void* Kit_PeekBuffer(const Kit_Buffer *buffer); diff --git a/src/internal/audio/kitaudio.c b/src/internal/audio/kitaudio.c index e399ff2..3a534bb 100644 --- a/src/internal/audio/kitaudio.c +++ b/src/internal/audio/kitaudio.c @@ -15,7 +15,7 @@ #include "kitchensink/internal/utils/kitringbuffer.h"
#include "kitchensink/internal/utils/kitlog.h"
-#define AUDIO_SYNC_THRESHOLD 0.05
+#define KIT_AUDIO_SYNC_THRESHOLD 0.05
typedef struct Kit_AudioDecoder {
SwrContext *swr;
@@ -275,36 +275,30 @@ double Kit_GetAudioDecoderPTS(Kit_Decoder *dec) { int Kit_GetAudioDecoderData(Kit_Decoder *dec, unsigned char *buf, int len) {
assert(dec != NULL);
- Kit_AudioPacket *packet = Kit_PeekDecoderOutput(dec);
+ Kit_AudioPacket *packet = NULL;
+ int ret = 0;
+ int bytes_per_sample = 0;
+ double bytes_per_second = 0;
+ double sync_ts = 0;
+
+ // First, peek the next packet. Make sure we have something to read.
+ packet = Kit_PeekDecoderOutput(dec);
if(packet == NULL) {
return 0;
}
- int ret = 0;
- int bytes_per_sample = dec->output.bytes * dec->output.channels;
- double bytes_per_second = bytes_per_sample * dec->output.samplerate;
- double sync_ts = _GetSystemTime() - dec->clock_sync;
-
- if(packet->pts > sync_ts + AUDIO_SYNC_THRESHOLD) {
+ // If packet should not yet be played, stop here and wait.
+ // If packet should have already been played, skip it and try to find a better packet.
+ // For audio, it is possible that we cannot find good packet. Then just don't read anything.
+ sync_ts = _GetSystemTime() - dec->clock_sync;
+ if(packet->pts > sync_ts + KIT_AUDIO_SYNC_THRESHOLD) {
return 0;
- } else if(packet->pts < sync_ts - AUDIO_SYNC_THRESHOLD) {
- // Audio is lagging, skip until good pts is found
- while(1) {
- Kit_AdvanceDecoderOutput(dec);
- free_out_audio_packet_cb(packet);
- packet = Kit_PeekDecoderOutput(dec);
- if(packet == NULL) {
- break;
- } else {
- dec->clock_pos = packet->pts;
- }
- if(packet->pts > sync_ts - AUDIO_SYNC_THRESHOLD) {
- break;
- }
- }
}
-
- // If we have no viable packet, just skip
+ while(packet != NULL && packet->pts < sync_ts - KIT_AUDIO_SYNC_THRESHOLD) {
+ Kit_AdvanceDecoderOutput(dec);
+ free_out_audio_packet_cb(packet);
+ packet = Kit_PeekDecoderOutput(dec);
+ }
if(packet == NULL) {
return 0;
}
@@ -312,18 +306,19 @@ int Kit_GetAudioDecoderData(Kit_Decoder *dec, unsigned char *buf, int len) { // Read data from packet ringbuffer
if(len > 0) {
ret = Kit_ReadRingBuffer(packet->rb, (char*)buf, len);
+ if(ret) {
+ bytes_per_sample = dec->output.bytes * dec->output.channels;
+ bytes_per_second = bytes_per_sample * dec->output.samplerate;
+ packet->pts += ((double)ret) / bytes_per_second;
+ }
}
+ dec->clock_pos = packet->pts;
// If ringbuffer is cleared, kill packet and advance buffer.
// Otherwise forward the pts value for the current packet.
if(Kit_GetRingBufferLength(packet->rb) == 0) {
Kit_AdvanceDecoderOutput(dec);
- dec->clock_pos = packet->pts;
free_out_audio_packet_cb(packet);
- } else {
- packet->pts += ((double)ret) / bytes_per_second;
- dec->clock_pos = packet->pts;
}
-
return ret;
}
diff --git a/src/internal/kitdecoder.c b/src/internal/kitdecoder.c index 0855eee..09e46d3 100644 --- a/src/internal/kitdecoder.c +++ b/src/internal/kitdecoder.c @@ -20,6 +20,7 @@ Kit_Decoder* Kit_CreateDecoder(const Kit_Source *src, int stream_index, assert(thread_count > 0);
AVCodecContext *codec_ctx = NULL;
+ AVDictionary *codec_opts = NULL;
AVCodec *codec = NULL;
AVFormatContext *format_ctx = src->format_ctx;
int bsizes[2] = {BUFFER_IN_SIZE, out_b_size};
@@ -39,8 +40,12 @@ Kit_Decoder* Kit_CreateDecoder(const Kit_Source *src, int stream_index, }
// Find audio decoder
+#if LIBAVCODEC_VERSION_INT < AV_VERSION_INT(57, 48, 101)
codec = avcodec_find_decoder(format_ctx->streams[stream_index]->codec->codec_id);
- if(!codec) {
+#else
+ codec = avcodec_find_decoder(format_ctx->streams[stream_index]->codecpar->codec_id);
+#endif
+ if(codec == NULL) {
Kit_SetError("No suitable decoder found for stream %d", stream_index);
goto exit_1;
}
@@ -52,18 +57,33 @@ Kit_Decoder* Kit_CreateDecoder(const Kit_Source *src, int stream_index, goto exit_1;
}
- // Copy context from stream to target codec context
- if(avcodec_copy_context(codec_ctx, format_ctx->streams[stream_index]->codec) != 0) {
+ // Copy params
+#if LIBAVCODEC_VERSION_INT < AV_VERSION_INT(57, 48, 101)
+ if(avcodec_copy_context(codec_ctx, format_ctx->streams[stream_index]->codec) != 0)
+#else
+ if(avcodec_parameters_to_context(codec_ctx, format_ctx->streams[stream_index]->codecpar) < 0)
+#endif
+ {
Kit_SetError("Unable to copy codec context for stream %d", stream_index);
goto exit_2;
}
+ // Required by ffmpeg for now when using the new API.
+#if LIBAVCODEC_VERSION_INT >= AV_VERSION_INT(57, 48, 101)
+ codec_ctx->pkt_timebase = format_ctx->streams[stream_index]->time_base;
+#endif
+
// Set thread count
codec_ctx->thread_count = thread_count;
- codec_ctx->thread_type = FF_THREAD_SLICE;
+ codec_ctx->thread_type = FF_THREAD_SLICE|FF_THREAD_FRAME;
+
+ // This is required for ass_process_chunk() support
+ if(LIBAVCODEC_VERSION_INT >= AV_VERSION_INT(57, 25, 100)) {
+ av_dict_set(&codec_opts, "sub_text_format", "ass", 0);
+ }
// Open the stream
- if(avcodec_open2(codec_ctx, codec, NULL) < 0) {
+ if(avcodec_open2(codec_ctx, codec, &codec_opts) < 0) {
Kit_SetError("Unable to open codec for stream %d", stream_index);
goto exit_2;
}
@@ -98,6 +118,7 @@ exit_3: }
avcodec_close(codec_ctx);
exit_2:
+ av_dict_free(&codec_opts);
avcodec_free_context(&codec_ctx);
exit_1:
free(dec);
@@ -266,6 +287,16 @@ void Kit_AdvanceDecoderOutput(Kit_Decoder *dec) { }
}
+unsigned int Kit_GetDecoderOutputLength(Kit_Decoder *dec) {
+ assert(dec != NULL);
+ unsigned int len = 0;
+ if(SDL_LockMutex(dec->output_lock) == 0) {
+ len = Kit_GetBufferLength(dec->buffer[KIT_DEC_BUF_OUT]);
+ SDL_UnlockMutex(dec->output_lock);
+ }
+ return len;
+}
+
void Kit_ClearDecoderBuffers(Kit_Decoder *dec) {
if(dec == NULL) return;
Kit_ClearDecoderInput(dec);
diff --git a/src/internal/subtitle/kitsubtitle.c b/src/internal/subtitle/kitsubtitle.c index d6bed5d..417b338 100644 --- a/src/internal/subtitle/kitsubtitle.c +++ b/src/internal/subtitle/kitsubtitle.c @@ -59,12 +59,12 @@ static void dec_decode_subtitle_cb(Kit_Decoder *dec, AVPacket *in_packet) { subtitle_dec->scratch_frame.end_display_time = 30000;
}
- start = pts + subtitle_dec->scratch_frame.start_display_time / 1000.0F;
- end = pts + subtitle_dec->scratch_frame.end_display_time / 1000.0F;
+ start = subtitle_dec->scratch_frame.start_display_time / 1000.0F;
+ end = subtitle_dec->scratch_frame.end_display_time / 1000.0F;
// Create a packet. This should be filled by renderer.
Kit_RunSubtitleRenderer(
- subtitle_dec->renderer, &subtitle_dec->scratch_frame, start, end);
+ subtitle_dec->renderer, &subtitle_dec->scratch_frame, pts, start, end);
// Free subtitle since it has now been handled
avsubtitle_free(&subtitle_dec->scratch_frame);
diff --git a/src/internal/subtitle/renderers/kitsubass.c b/src/internal/subtitle/renderers/kitsubass.c index 7db72dd..c229406 100644 --- a/src/internal/subtitle/renderers/kitsubass.c +++ b/src/internal/subtitle/renderers/kitsubass.c @@ -2,6 +2,7 @@ #include <stdlib.h>
#include <SDL_surface.h>
+#include <libavcodec/version.h>
#include "kitchensink/kiterror.h"
#include "kitchensink/internal/utils/kitlog.h"
@@ -40,7 +41,7 @@ static void Kit_ProcessAssImage(SDL_Surface *surface, const ASS_Image *img) { }
}
-static void ren_render_ass_cb(Kit_SubtitleRenderer *ren, void *src, double start_pts, double end_pts) {
+static void ren_render_ass_cb(Kit_SubtitleRenderer *ren, void *src, double pts, double start, double end) {
assert(ren != NULL);
assert(src != NULL);
@@ -48,11 +49,26 @@ static void ren_render_ass_cb(Kit_SubtitleRenderer *ren, void *src, double start AVSubtitle *sub = src;
// Read incoming subtitle packets to libASS
+ long long start_ms = (start + pts) * 1000;
+ long long end_ms = end * 1000;
if(Kit_LockDecoderOutput(ren->dec) == 0) {
for(int r = 0; r < sub->num_rects; r++) {
if(sub->rects[r]->ass == NULL)
continue;
- ass_process_data(ass_ren->track, sub->rects[r]->ass, strlen(sub->rects[r]->ass));
+ if(LIBAVCODEC_VERSION_INT < AV_VERSION_INT(57,25,100)) {
+ ass_process_data(
+ ass_ren->track,
+ sub->rects[r]->ass,
+ strlen(sub->rects[r]->ass));
+ } else {
+ // This requires the sub_text_format codec_opt set for ffmpeg
+ ass_process_chunk(
+ ass_ren->track,
+ sub->rects[r]->ass,
+ strlen(sub->rects[r]->ass),
+ start_ms,
+ end_ms);
+ }
}
Kit_UnlockDecoderOutput(ren->dec);
}
@@ -150,7 +166,12 @@ Kit_SubtitleRenderer* Kit_CreateASSSubtitleRenderer(Kit_Decoder *dec, int video_ // Read fonts from attachment streams and give them to libass
for(int j = 0; j < dec->format_ctx->nb_streams; j++) {
AVStream *st = dec->format_ctx->streams[j];
- if(st->codec->codec_type == AVMEDIA_TYPE_ATTACHMENT && attachment_is_font(st)) {
+#if LIBAVCODEC_VERSION_INT < AV_VERSION_INT(57, 48, 101)
+ AVCodecContext *codec = st->codec;
+#else
+ AVCodecParameters *codec = st->codecpar;
+#endif
+ if(codec->codec_type == AVMEDIA_TYPE_ATTACHMENT && attachment_is_font(st)) {
const AVDictionaryEntry *tag = av_dict_get(
st->metadata,
"filename",
@@ -159,9 +180,9 @@ Kit_SubtitleRenderer* Kit_CreateASSSubtitleRenderer(Kit_Decoder *dec, int video_ if(tag) {
ass_add_font(
state->libass_handle,
- tag->value,
- (char*)st->codec->extradata,
- st->codec->extradata_size);
+ tag->value,
+ (char*)codec->extradata,
+ codec->extradata_size);
}
}
}
diff --git a/src/internal/subtitle/renderers/kitsubimage.c b/src/internal/subtitle/renderers/kitsubimage.c index 0cd0cce..b9a8e48 100644 --- a/src/internal/subtitle/renderers/kitsubimage.c +++ b/src/internal/subtitle/renderers/kitsubimage.c @@ -17,13 +17,15 @@ typedef struct Kit_ImageSubtitleRenderer { float scale_y;
} Kit_ImageSubtitleRenderer;
-static void ren_render_image_cb(Kit_SubtitleRenderer *ren, void *sub_src, double start_pts, double end_pts) {
+static void ren_render_image_cb(Kit_SubtitleRenderer *ren, void *sub_src, double pts, double start, double end) {
assert(ren != NULL);
assert(sub_src != NULL);
AVSubtitle *sub = sub_src;
SDL_Surface *dst = NULL;
SDL_Surface *src = NULL;
+ double start_pts = pts + start;
+ double end_pts = pts + end;
// If this subtitle has no rects, we still need to clear screen from old subs
if(sub->num_rects == 0) {
diff --git a/src/internal/subtitle/renderers/kitsubrenderer.c b/src/internal/subtitle/renderers/kitsubrenderer.c index 77ad201..d41d61d 100644 --- a/src/internal/subtitle/renderers/kitsubrenderer.c +++ b/src/internal/subtitle/renderers/kitsubrenderer.c @@ -17,11 +17,11 @@ Kit_SubtitleRenderer* Kit_CreateSubtitleRenderer(Kit_Decoder *dec) { return ren;
}
-void Kit_RunSubtitleRenderer(Kit_SubtitleRenderer *ren, void *src, double start_pts, double end_pts) {
+void Kit_RunSubtitleRenderer(Kit_SubtitleRenderer *ren, void *src, double pts, double start, double end) {
if(ren == NULL)
return;
if(ren->ren_render != NULL)
- ren->ren_render(ren, src, start_pts, end_pts);
+ ren->ren_render(ren, src, pts, start, end);
}
int Kit_GetSubtitleRendererData(Kit_SubtitleRenderer *ren, Kit_TextureAtlas *atlas, SDL_Texture *texture, double current_pts) {
diff --git a/src/internal/utils/kitbuffer.c b/src/internal/utils/kitbuffer.c index 0133154..60ca831 100644 --- a/src/internal/utils/kitbuffer.c +++ b/src/internal/utils/kitbuffer.c @@ -18,6 +18,10 @@ Kit_Buffer* Kit_CreateBuffer(unsigned int size, Kit_BufferFreeCallback free_cb) return b; } +unsigned int Kit_GetBufferLength(const Kit_Buffer *buffer) { + return buffer->write_p - buffer->read_p; +} + void Kit_DestroyBuffer(Kit_Buffer *buffer) { if(buffer == NULL) return; Kit_ClearBuffer(buffer); diff --git a/src/internal/utils/kitringbuffer.c b/src/internal/utils/kitringbuffer.c index 70fd24f..e6fa136 100644 --- a/src/internal/utils/kitringbuffer.c +++ b/src/internal/utils/kitringbuffer.c @@ -68,6 +68,17 @@ int Kit_WriteRingBuffer(Kit_RingBuffer *rb, const char* data, int len) { return 0; } +static void _ReadRingBufferData(const Kit_RingBuffer *rb, char *data, const int len) { + int k; + if(len + rb->rpos > rb->size) { + k = (len + rb->rpos) % rb->size; + memcpy(data, rb->data + rb->rpos, len - k); + memcpy(data + (len - k), rb->data, k); + } else { + memcpy(data, rb->data + rb->rpos, len); + } +} + /** * Reads data from ringbuffer. If ringbuffer has less data than was requested, * only the available data will be read. @@ -76,17 +87,10 @@ int Kit_WriteRingBuffer(Kit_RingBuffer *rb, const char* data, int len) { * @param len How much data do we want * @return Amount of data that was actually read. */ -int Kit_ReadRingBuffer(Kit_RingBuffer *rb, char* data, int len) { - int k; +int Kit_ReadRingBuffer(Kit_RingBuffer *rb, char *data, int len) { len = (len > rb->len) ? rb->len : len; if(rb->len > 0) { - if(len + rb->rpos > rb->size) { - k = (len + rb->rpos) % rb->size; - memcpy(data, (rb->data + rb->rpos), len-k); - memcpy(data+(len-k), (rb->data), k); - } else { - memcpy(data, (rb->data + rb->rpos), len); - } + _ReadRingBufferData(rb, data, len); rb->len -= len; rb->rpos += len; if(rb->rpos >= rb->size) { @@ -106,17 +110,10 @@ int Kit_ReadRingBuffer(Kit_RingBuffer *rb, char* data, int len) { * @param len How much data do we need * @return Amount of data actually read */ -int Kit_PeekRingBuffer(const Kit_RingBuffer *rb, char* data, int len) { - int k; +int Kit_PeekRingBuffer(const Kit_RingBuffer *rb, char *data, int len) { len = (len > rb->len) ? rb->len : len; if(rb->len > 0) { - if(len + rb->rpos > rb->size) { - k = (len + rb->rpos) % rb->size; - memcpy(data, (rb->data + rb->rpos), len-k); - memcpy(data+(len-k), (rb->data), k); - } else { - memcpy(data, (rb->data + rb->rpos), len); - } + _ReadRingBufferData(rb, data, len); return len; } return 0; diff --git a/src/internal/video/kitvideo.c b/src/internal/video/kitvideo.c index 350d3c5..568c178 100644 --- a/src/internal/video/kitvideo.c +++ b/src/internal/video/kitvideo.c @@ -12,7 +12,7 @@ #include "kitchensink/internal/video/kitvideo.h"
#include "kitchensink/internal/utils/kitlog.h"
-#define KIT_VIDEO_SYNC_THRESHOLD 0.01
+#define KIT_VIDEO_SYNC_THRESHOLD 0.02
enum AVPixelFormat supported_list[] = {
AV_PIX_FMT_YUV420P,
@@ -248,35 +248,30 @@ int Kit_GetVideoDecoderData(Kit_Decoder *dec, SDL_Texture *texture) { assert(dec != NULL);
assert(texture != NULL);
- Kit_VideoPacket *packet = Kit_PeekDecoderOutput(dec);
+ Kit_VideoPacket *packet = NULL;
+ double sync_ts = 0;
+ unsigned int limit_rounds = 0;
+
+ // First, peek the next packet. Make sure we have something to read.
+ packet = Kit_PeekDecoderOutput(dec);
if(packet == NULL) {
return 0;
}
- double sync_ts = _GetSystemTime() - dec->clock_sync;
-
- // Check if we want the packet
+ // If packet should not yet be played, stop here and wait.
+ // If packet should have already been played, skip it and try to find a better packet.
+ // For video, we *try* to return a frame, even if we are out of sync. It is better than
+ // not showing anything.
+ sync_ts = _GetSystemTime() - dec->clock_sync;
if(packet->pts > sync_ts + KIT_VIDEO_SYNC_THRESHOLD) {
- // Video is ahead, don't show yet.
return 0;
- } else if(packet->pts < sync_ts - KIT_VIDEO_SYNC_THRESHOLD) {
- // Video is lagging, skip until we find a good PTS to continue from.
- while(packet != NULL) {
- Kit_AdvanceDecoderOutput(dec);
- free_out_video_packet_cb(packet);
- packet = Kit_PeekDecoderOutput(dec);
- if(packet == NULL) {
- break;
- } else {
- dec->clock_pos = packet->pts;
- }
- if(packet->pts > sync_ts - KIT_VIDEO_SYNC_THRESHOLD) {
- break;
- }
- }
}
-
- // If we have no viable packet, just skip
+ limit_rounds = Kit_GetDecoderOutputLength(dec);
+ while(packet != NULL && packet->pts < sync_ts - KIT_VIDEO_SYNC_THRESHOLD && --limit_rounds) {
+ Kit_AdvanceDecoderOutput(dec);
+ free_out_video_packet_cb(packet);
+ packet = Kit_PeekDecoderOutput(dec);
+ }
if(packet == NULL) {
return 0;
}
diff --git a/src/kitplayer.c b/src/kitplayer.c index d2a4604..0baf57b 100644 --- a/src/kitplayer.c +++ b/src/kitplayer.c @@ -435,7 +435,7 @@ int Kit_PlayerSeek(Kit_Player *player, double seek_set) { // First, tell ffmpeg to seek stream. If not capable, stop here. // Failure here probably means that stream is unseekable someway, eg. streamed media - if(avformat_seek_file(format_ctx, -1, INT64_MIN, seek_target, INT64_MAX, flags) < 0) { + if(avformat_seek_file(format_ctx, -1, seek_target, seek_target, INT64_MAX, flags) < 0) { Kit_SetError("Unable to seek source"); SDL_UnlockMutex(player->dec_lock); return 1; diff --git a/src/kitsource.c b/src/kitsource.c index 588f829..1a3bb00 100644 --- a/src/kitsource.c +++ b/src/kitsource.c @@ -177,7 +177,13 @@ int Kit_GetSourceStreamInfo(const Kit_Source *src, Kit_SourceStreamInfo *info, i } AVStream *stream = format_ctx->streams[index]; - switch(stream->codec->codec_type) { + enum AVMediaType codec_type; +#if LIBAVCODEC_VERSION_INT < AV_VERSION_INT(57, 48, 101) + codec_type = stream->codec->codec_type; +#else + codec_type = stream->codecpar->codec_type; +#endif + switch(codec_type) { case AVMEDIA_TYPE_UNKNOWN: info->type = KIT_STREAMTYPE_UNKNOWN; break; case AVMEDIA_TYPE_DATA: info->type = KIT_STREAMTYPE_DATA; break; case AVMEDIA_TYPE_VIDEO: info->type = KIT_STREAMTYPE_VIDEO; break; |