summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorUoti Urpala <uau@mplayer2.org>2011-08-20 20:25:43 +0300
committerUoti Urpala <uau@mplayer2.org>2011-08-20 20:25:43 +0300
commit9c7c4e5b7dd7745ad071ec330abab49a8f4e314b (patch)
treefefbae9c04f401be71f363129bbc30783c19f8f6
parente2ca8853a6a26ca1afcababea0e4a743b525daa2 (diff)
downloadmpv-9c7c4e5b7dd7745ad071ec330abab49a8f4e314b.tar.bz2
mpv-9c7c4e5b7dd7745ad071ec330abab49a8f4e314b.tar.xz
core, demux, vd_ffmpeg: pass side data from demux_lavf to vd_ffmpeg
Pass the libavformat packet side_data field from demux_lavf to vd_ffmpeg. Libavcodec/libavformat use this field for palette data, and passing it is required for the playback of some paletted video codecs. The implementation works by giving vd_ffmpeg a copy of the struct demux_packet used to store the video packet (from which it can access the avpacket field). The definition of struct demux_packet is moved to new file demux_packet.h so that vd_ffmpeg.c can use it without including all of demuxer.h.
-rw-r--r--libmpcodecs/dec_video.c5
-rw-r--r--libmpcodecs/dec_video.h5
-rw-r--r--libmpcodecs/vd.h17
-rw-r--r--libmpcodecs/vd_ffmpeg.c12
-rw-r--r--libmpdemux/demux_packet.h39
-rw-r--r--libmpdemux/demuxer.c10
-rw-r--r--libmpdemux/demuxer.h17
-rw-r--r--mplayer.c26
8 files changed, 91 insertions, 40 deletions
diff --git a/libmpcodecs/dec_video.c b/libmpcodecs/dec_video.c
index f49eb79218..8dbd733fd7 100644
--- a/libmpcodecs/dec_video.c
+++ b/libmpcodecs/dec_video.c
@@ -393,7 +393,8 @@ int init_best_video_codec(sh_video_t *sh_video, char **video_codec_list,
return 1; // success
}
-void *decode_video(sh_video_t *sh_video, unsigned char *start, int in_size,
+void *decode_video(sh_video_t *sh_video, struct demux_packet *packet,
+ unsigned char *start, int in_size,
int drop_frame, double pts)
{
mp_image_t *mpi = NULL;
@@ -433,7 +434,7 @@ void *decode_video(sh_video_t *sh_video, unsigned char *start, int in_size,
}
if (sh_video->vd_driver->decode2) {
- mpi = sh_video->vd_driver->decode2(sh_video, start, in_size,
+ mpi = sh_video->vd_driver->decode2(sh_video, packet, start, in_size,
drop_frame, &pts);
} else {
mpi = sh_video->vd_driver->decode(sh_video, start, in_size,
diff --git a/libmpcodecs/dec_video.h b/libmpcodecs/dec_video.h
index f4b72a7d3f..be087d09b9 100644
--- a/libmpcodecs/dec_video.h
+++ b/libmpcodecs/dec_video.h
@@ -29,7 +29,10 @@ void vfm_help(void);
int init_best_video_codec(sh_video_t *sh_video, char** video_codec_list, char** video_fm_list);
void uninit_video(sh_video_t *sh_video);
-void *decode_video(sh_video_t *sh_video, unsigned char *start, int in_size, int drop_frame, double pts);
+struct demux_packet;
+void *decode_video(sh_video_t *sh_video, struct demux_packet *packet,
+ unsigned char *start, int in_size, int drop_frame,
+ double pts);
int filter_video(sh_video_t *sh_video, void *frame, double pts);
int get_video_quality_max(sh_video_t *sh_video);
diff --git a/libmpcodecs/vd.h b/libmpcodecs/vd.h
index 76f3d00553..88837188f6 100644
--- a/libmpcodecs/vd.h
+++ b/libmpcodecs/vd.h
@@ -25,16 +25,19 @@
typedef mp_codec_info_t vd_info_t;
+struct demux_packet;
+
/* interface of video decoder drivers */
typedef struct vd_functions
{
- const vd_info_t *info;
- int (*init)(sh_video_t *sh);
- void (*uninit)(sh_video_t *sh);
- int (*control)(sh_video_t *sh,int cmd,void* arg, ...);
- mp_image_t* (*decode)(sh_video_t *sh,void* data,int len,int flags);
- struct mp_image *(*decode2)(struct sh_video *sh, void *data, int len,
- int flags, double *reordered_pts);
+ const vd_info_t *info;
+ int (*init)(sh_video_t *sh);
+ void (*uninit)(sh_video_t *sh);
+ int (*control)(sh_video_t *sh,int cmd,void* arg, ...);
+ mp_image_t* (*decode)(sh_video_t *sh,void* data,int len,int flags);
+ struct mp_image *(*decode2)(struct sh_video *sh, struct demux_packet *pkt,
+ void *data, int len, int flags,
+ double *reordered_pts);
} vd_functions_t;
// NULL terminated array of all drivers
diff --git a/libmpcodecs/vd_ffmpeg.c b/libmpcodecs/vd_ffmpeg.c
index 9d33d5d963..f67db0692b 100644
--- a/libmpcodecs/vd_ffmpeg.c
+++ b/libmpcodecs/vd_ffmpeg.c
@@ -36,6 +36,7 @@
#include "vd.h"
#include "img_format.h"
#include "libmpdemux/stheader.h"
+#include "libmpdemux/demux_packet.h"
#include "codec-cfg.h"
#include "osdep/numcores.h"
@@ -713,8 +714,9 @@ static av_unused void swap_palette(void *pal)
}
// decode a frame
-static struct mp_image *decode(struct sh_video *sh, void *data, int len,
- int flags, double *reordered_pts)
+static struct mp_image *decode(struct sh_video *sh, struct demux_packet *packet,
+ void *data, int len, int flags,
+ double *reordered_pts)
{
int got_picture=0;
int ret;
@@ -755,6 +757,12 @@ static struct mp_image *decode(struct sh_video *sh, void *data, int len,
pkt.size = len;
// HACK: make PNGs decode normally instead of as CorePNG delta frames
pkt.flags = AV_PKT_FLAG_KEY;
+#if LIBAVCODEC_VERSION_MAJOR >= 53
+ if (packet && packet->avpacket) {
+ pkt.side_data = packet->avpacket->side_data;
+ pkt.side_data_elems = packet->avpacket->side_data_elems;
+ }
+#endif
// The avcodec opaque field stupidly supports only int64_t type
union pts { int64_t i; double d; };
avctx->reordered_opaque = (union pts){.d = *reordered_pts}.i;
diff --git a/libmpdemux/demux_packet.h b/libmpdemux/demux_packet.h
new file mode 100644
index 0000000000..30cd0010f5
--- /dev/null
+++ b/libmpdemux/demux_packet.h
@@ -0,0 +1,39 @@
+/*
+ * This file is part of mplayer2.
+ *
+ * mplayer2 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.
+ *
+ * mplayer2 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 mplayer2; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#ifndef MPLAYER_DEMUX_PACKET_H
+#define MPLAYER_DEMUX_PACKET_H
+
+#include <sys/types.h>
+
+// Holds one packet/frame/whatever
+typedef struct demux_packet {
+ int len;
+ double pts;
+ double duration;
+ double stream_pts;
+ off_t pos; // position in index (AVI) or file (MPG)
+ unsigned char *buffer;
+ int flags; // keyframe, etc
+ int refcount; // counter for the master packet, if 0, buffer can be free()d
+ struct demux_packet *master; //in clones, pointer to the master packet
+ struct demux_packet *next;
+ struct AVPacket *avpacket; // original libavformat packet (demux_lavf)
+} demux_packet_t;
+
+#endif /* MPLAYER_DEMUX_PACKET_H */
diff --git a/libmpdemux/demuxer.c b/libmpdemux/demuxer.c
index d4c43ad657..6ae2ca8b7f 100644
--- a/libmpdemux/demuxer.c
+++ b/libmpdemux/demuxer.c
@@ -21,6 +21,7 @@
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
+#include <assert.h>
#include <unistd.h>
#include <sys/types.h>
@@ -846,6 +847,15 @@ int ds_get_packet_sub(demux_stream_t *ds, unsigned char **start)
return len;
}
+struct demux_packet *ds_get_packet2(struct demux_stream *ds)
+{
+ // This shouldn't get used together with partial reads
+ assert(ds->buffer_pos >= ds->buffer_size);
+ ds_fill_buffer(ds);
+ ds->buffer_pos = ds->buffer_size;
+ return ds->current;
+}
+
double ds_get_next_pts(demux_stream_t *ds)
{
demuxer_t *demux = ds->demuxer;
diff --git a/libmpdemux/demuxer.h b/libmpdemux/demuxer.h
index 5585cf73ed..1b885f28d3 100644
--- a/libmpdemux/demuxer.h
+++ b/libmpdemux/demuxer.h
@@ -27,6 +27,7 @@
#include "bstr.h"
#include "mpcommon.h"
+#include "demux_packet.h"
struct MPOpts;
@@ -124,21 +125,6 @@ enum timestamp_type {
// demux_lavf can pass lavf buffers using FF_INPUT_BUFFER_PADDING_SIZE instead
#define MP_INPUT_BUFFER_PADDING_SIZE 8
-// Holds one packet/frame/whatever
-typedef struct demux_packet {
- int len;
- double pts;
- double duration;
- double stream_pts;
- off_t pos; // position in index (AVI) or file (MPG)
- unsigned char *buffer;
- int flags; // keyframe, etc
- int refcount; // counter for the master packet, if 0, buffer can be free()d
- struct demux_packet *master; //in clones, pointer to the master packet
- struct demux_packet *next;
- struct AVPacket *avpacket; // original libavformat packet (demux_lavf)
-} demux_packet_t;
-
typedef struct demux_stream {
int buffer_pos; // current buffer position
int buffer_size; // current buffer size
@@ -360,6 +346,7 @@ int ds_get_packet(struct demux_stream *ds, unsigned char **start);
int ds_get_packet_pts(struct demux_stream *ds, unsigned char **start,
double *pts);
int ds_get_packet_sub(struct demux_stream *ds, unsigned char **start);
+struct demux_packet *ds_get_packet2(struct demux_stream *ds);
double ds_get_next_pts(struct demux_stream *ds);
int ds_parse(struct demux_stream *sh, uint8_t **buffer, int *len, double pts,
off_t pos);
diff --git a/mplayer.c b/mplayer.c
index 5433fe41c8..e853103bb9 100644
--- a/mplayer.c
+++ b/mplayer.c
@@ -2892,8 +2892,8 @@ static double update_video_nocorrect_pts(struct MPContext *mpctx)
decoded_frame = mp_dvdnav_restore_smpi(mpctx, &in_size, &packet, NULL);
if (in_size >= 0 && !decoded_frame)
#endif
- decoded_frame = decode_video(sh_video, packet, in_size, framedrop_type,
- sh_video->pts);
+ decoded_frame = decode_video(sh_video, NULL, packet, in_size,
+ framedrop_type, sh_video->pts);
#ifdef CONFIG_DVDNAV
// Save last still frame for future display
mp_dvdnav_save_smpi(mpctx, in_size, packet, decoded_frame);
@@ -2958,17 +2958,17 @@ static double update_video(struct MPContext *mpctx)
// timer now
if (vf_output_queued_frame(sh_video->vfilter))
break;
- unsigned char *packet = NULL;
- int in_size = ds_get_packet_pts(mpctx->d_video, &packet, &pts);
+ int in_size = 0;
+ unsigned char *buf = NULL;
+ pts = MP_NOPTS_VALUE;
+ struct demux_packet *pkt = ds_get_packet2(mpctx->d_video);
+ if (pkt) {
+ in_size = pkt->len;
+ buf = pkt->buffer;
+ pts = pkt->pts;
+ }
if (pts != MP_NOPTS_VALUE)
pts += mpctx->video_offset;
- bool hit_eof = false;
- if (in_size < 0) {
- // try to extract last frames in case of decoder lag
- in_size = 0;
- pts = MP_NOPTS_VALUE;
- hit_eof = true;
- }
if (in_size > max_framesize)
max_framesize = in_size;
current_module = "decode video";
@@ -2976,13 +2976,13 @@ static double update_video(struct MPContext *mpctx)
mpctx->hrseek_framedrop = false;
int framedrop_type = mpctx->hrseek_framedrop ? 1 :
check_framedrop(mpctx, sh_video->frametime);
- void *decoded_frame = decode_video(sh_video, packet, in_size,
+ void *decoded_frame = decode_video(sh_video, pkt, buf, in_size,
framedrop_type, pts);
if (decoded_frame) {
determine_frame_pts(mpctx);
current_module = "filter video";
filter_video(sh_video, decoded_frame, sh_video->pts);
- } else if (hit_eof) {
+ } else if (!pkt) {
if (vo_get_buffered_frame(video_out, true) < 0)
return -1;
}