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 + +// 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 #include #include +#include #include #include @@ -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; }