From f0b471c6697824f0120c08b35592059dd0c68b20 Mon Sep 17 00:00:00 2001 From: marc Date: Mon, 18 Feb 2013 17:18:18 +0000 Subject: [PATCH 1/7] dxva-h264: Fix an AMD driver issue with playback of streams that don't start with an I-Frame --- libavcodec/dxva2_h264.c | 8 ++++++++ libavcodec/h264_slice.c | 1 + libavcodec/h264dec.c | 1 + libavcodec/h264dec.h | 2 ++ 4 files changed, 12 insertions(+) diff --git a/libavcodec/dxva2_h264.c b/libavcodec/dxva2_h264.c index 5b23b28f1202b..c0a8d80f3b1c0 100644 --- a/libavcodec/dxva2_h264.c +++ b/libavcodec/dxva2_h264.c @@ -504,6 +504,14 @@ static int dxva2_h264_end_frame(AVCodecContext *avctx) if (ctx_pic->slice_count <= 0 || ctx_pic->bitstream_size <= 0) return -1; + + // Wait for an I-frame before start decoding. Workaround for ATI UVD and UVD+ GPUs + if (!h->got_first_iframe) { + if (!(ctx_pic->pp.wBitFields & (1 << 15))) + return -1; + h->got_first_iframe = 1; + } + ret = ff_dxva2_common_end_frame(avctx, h->cur_pic_ptr->f, &ctx_pic->pp, sizeof(ctx_pic->pp), &ctx_pic->qm, sizeof(ctx_pic->qm), diff --git a/libavcodec/h264_slice.c b/libavcodec/h264_slice.c index 713953778ae1e..db8363e4cc988 100644 --- a/libavcodec/h264_slice.c +++ b/libavcodec/h264_slice.c @@ -928,6 +928,7 @@ static int h264_slice_header_init(H264Context *h) h->first_field = 0; h->prev_interlaced_frame = 1; + h->got_first_iframe = 0; init_scan_tables(h); ret = ff_h264_alloc_tables(h); diff --git a/libavcodec/h264dec.c b/libavcodec/h264dec.c index 6270ea80dff09..5eedeb3c275de 100644 --- a/libavcodec/h264dec.c +++ b/libavcodec/h264dec.c @@ -467,6 +467,7 @@ void ff_h264_flush_change(H264Context *h) h->next_outputed_poc = INT_MIN; h->prev_interlaced_frame = 1; + h->got_first_iframe = 0; idr(h); h->poc.prev_frame_num = -1; diff --git a/libavcodec/h264dec.h b/libavcodec/h264dec.h index 29c4d4e42c1e3..a419615124b20 100644 --- a/libavcodec/h264dec.h +++ b/libavcodec/h264dec.h @@ -539,6 +539,8 @@ typedef struct H264Context { * slices) anymore */ int setup_finished; + int got_first_iframe; + int cur_chroma_format_idc; int cur_bit_depth_luma; int16_t slice_row[MAX_SLICES]; ///< to detect when MAX_SLICES is too low From 02642caa2a577c6a8f3a66851b618f52c4f3c7ac Mon Sep 17 00:00:00 2001 From: Rechi Date: Tue, 21 Nov 2017 08:16:53 +0100 Subject: [PATCH 2/7] use Kodi as extra version --- Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Makefile b/Makefile index 45a22b0cb3c89..76454245bb2f1 100644 --- a/Makefile +++ b/Makefile @@ -120,7 +120,7 @@ GIT_LOG = $(SRC_PATH)/.git/logs/HEAD .version: M=@ libavutil/ffversion.h .version: - $(M)$(VERSION_SH) $(SRC_PATH) libavutil/ffversion.h $(EXTRA_VERSION) + $(M)$(VERSION_SH) $(SRC_PATH) libavutil/ffversion.h Kodi $(Q)touch .version # force version.sh to run whenever version might have changed From 32d4754a4c08f5f74292f9b857bc3a1aad83b90e Mon Sep 17 00:00:00 2001 From: Rechi Date: Tue, 21 Nov 2017 08:16:53 +0100 Subject: [PATCH 3/7] common.mak: never ignore an error if strip doesn't succeed --- ffbuild/common.mak | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ffbuild/common.mak b/ffbuild/common.mak index a60d27c9bd365..9efe74108688d 100644 --- a/ffbuild/common.mak +++ b/ffbuild/common.mak @@ -79,7 +79,7 @@ COMPILE_NVCC = $(call COMPILE,NVCC) %.o: %.asm $(COMPILE_X86ASM) - -$(if $(ASMSTRIPFLAGS), $(STRIP) $(ASMSTRIPFLAGS) $@) + $(if $(STRIP), $(if $(ASMSTRIPFLAGS), $(STRIP) $(ASMSTRIPFLAGS) $@)) %.o: %.rc $(WINDRES) $(IFLAGS) --preprocessor "$(DEPWINDRES) -E -xc-header -DRC_INVOKED $(CC_DEPFLAGS)" -o $@ $< From e01f7698314dc07f9ab14c4d8a9778c726acc392 Mon Sep 17 00:00:00 2001 From: wsnipex Date: Tue, 21 Nov 2017 08:16:53 +0100 Subject: [PATCH 4/7] only check for a git rev if the src tree is in a git repo fixes the version string when building from the kodi depends src tree --- ffbuild/version.sh | 2 ++ 1 file changed, 2 insertions(+) diff --git a/ffbuild/version.sh b/ffbuild/version.sh index edc4dd33c5420..239a138ca77d8 100755 --- a/ffbuild/version.sh +++ b/ffbuild/version.sh @@ -2,6 +2,7 @@ # Usage: version.sh +if [ -d $1/.git ]; then # only check for a git rev, if the src tree is in a git repo # check for git short hash if ! test "$revision"; then if (cd "$1" && grep git RELEASE 2> /dev/null >/dev/null) ; then @@ -27,6 +28,7 @@ if [ -z "$revision" ]; then git_hash="${srcdir##*-}";; esac fi +fi # no revision number found test "$revision" || revision=$(cd "$1" && cat RELEASE 2> /dev/null) From 8a7b4627e4485a1f649daf33a6630a144f478a17 Mon Sep 17 00:00:00 2001 From: Anton Fedchin Date: Fri, 11 Jan 2019 10:47:43 +0100 Subject: [PATCH 5/7] after 153b36f there is a possibility to crash when trying to get index of a surface which points to nirvana. it may occurs when a stream starts with non i-frame. --- libavcodec/dxva2.c | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/libavcodec/dxva2.c b/libavcodec/dxva2.c index 32416112bfd9c..dfae50044488f 100644 --- a/libavcodec/dxva2.c +++ b/libavcodec/dxva2.c @@ -771,16 +771,18 @@ unsigned ff_dxva2_get_surface_index(const AVCodecContext *avctx, #if CONFIG_D3D11VA if (avctx->pix_fmt == AV_PIX_FMT_D3D11) return (intptr_t)frame->data[1]; - if (avctx->pix_fmt == AV_PIX_FMT_D3D11VA_VLD) { + if (avctx->pix_fmt == AV_PIX_FMT_D3D11VA_VLD && surface) { D3D11_VIDEO_DECODER_OUTPUT_VIEW_DESC viewDesc; ID3D11VideoDecoderOutputView_GetDesc((ID3D11VideoDecoderOutputView*) surface, &viewDesc); return viewDesc.Texture2D.ArraySlice; } #endif #if CONFIG_DXVA2 - for (i = 0; i < DXVA_CONTEXT_COUNT(avctx, ctx); i++) { - if (avctx->pix_fmt == AV_PIX_FMT_DXVA2_VLD && ctx->dxva2.surface[i] == surface) - return i; + if (avctx->pix_fmt == AV_PIX_FMT_DXVA2_VLD) { + for (i = 0; i < DXVA_CONTEXT_COUNT(avctx, ctx); i++) { + if (ctx->dxva2.surface[i] == surface) + return i; + } } #endif From 5a1e9dc3e20b4b3b296683ac499c2baca71eed4c Mon Sep 17 00:00:00 2001 From: Rainer Hochecker Date: Sat, 26 Jan 2019 19:48:35 +0100 Subject: [PATCH 6/7] avcodec/vaapi_h264: skip decode if pic has no slices This fixes / workarounds https://bugs.freedesktop.org/show_bug.cgi?id=105368. It was hit frequently when watching h264 channels received via DVB-X. Corresponding kodi bug: https://github.com/xbmc/xbmc/issues/15704 --- libavcodec/vaapi_h264.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/libavcodec/vaapi_h264.c b/libavcodec/vaapi_h264.c index 9332aa6f3106a..d4494beebf8a8 100644 --- a/libavcodec/vaapi_h264.c +++ b/libavcodec/vaapi_h264.c @@ -314,6 +314,11 @@ static int vaapi_h264_end_frame(AVCodecContext *avctx) H264SliceContext *sl = &h->slice_ctx[0]; int ret; + if (pic->nb_slices == 0) { + ret = AVERROR_INVALIDDATA; + goto finish; + } + ret = ff_vaapi_decode_issue(avctx, pic); if (ret < 0) goto finish; From 47bf241d173b38c0462a4c34104179bd399e0c24 Mon Sep 17 00:00:00 2001 From: quietvoid <39477805+quietvoid@users.noreply.github.com> Date: Tue, 24 Nov 2020 13:50:29 -0500 Subject: [PATCH 7/7] Implement MatroskaBlockAdditionMapping (#2) Adds Matroska BlockAdditionMapping elements parsing. Creates AVDOVIDecoderConfigurationRecord and adds it to track side data. --- libavformat/isom.c | 91 +++++++++++++++++++++++++++++++++++++++ libavformat/isom.h | 9 ++++ libavformat/matroska.h | 7 +++ libavformat/matroskadec.c | 57 +++++++++++++++++++++++- libavformat/matroskaenc.c | 30 +++++++++++++ 5 files changed, 192 insertions(+), 2 deletions(-) diff --git a/libavformat/isom.c b/libavformat/isom.c index 44c7b13038c9d..8d30cd5800f7e 100644 --- a/libavformat/isom.c +++ b/libavformat/isom.c @@ -665,6 +665,97 @@ void ff_mov_write_chan(AVIOContext *pb, int64_t channel_layout) avio_wb32(pb, 0); // mNumberChannelDescriptions } +int ff_mov_parse_dvcc_dvvc(AVFormatContext *s, AVStream *st, GetBitContext *gb) +{ + AVDOVIDecoderConfigurationRecord *dovi; + size_t dovi_size; + int ret; + + if (gb->size_in_bits < 32) + return AVERROR_INVALIDDATA; + + dovi = av_dovi_alloc(&dovi_size); + if (!dovi) + return AVERROR(ENOMEM); + + dovi->dv_version_major = get_bits(gb, 8); + dovi->dv_version_minor = get_bits(gb, 8); + + dovi->dv_profile = get_bits(gb, 7); + dovi->dv_level = get_bits(gb, 6); + dovi->rpu_present_flag = get_bits1(gb); + dovi->el_present_flag = get_bits1(gb); + dovi->bl_present_flag = get_bits1(gb); + if (gb->size_in_bits >= 24 * 8) { + dovi->dv_bl_signal_compatibility_id = get_bits(gb, 4); + } else { + // 0 stands for None + // Dolby Vision V1.2.93 profiles and levels + dovi->dv_bl_signal_compatibility_id = 0; + } + + ret = av_stream_add_side_data(st, AV_PKT_DATA_DOVI_CONF, + (uint8_t *)dovi, dovi_size); + if (ret < 0) { + av_free(dovi); + return ret; + } + + av_log(s, AV_LOG_TRACE, "DOVI in dvcC/dvvC box, version: %d.%d, profile: %d, level: %d, " + "rpu flag: %d, el flag: %d, bl flag: %d, compatibility id: %d\n", + dovi->dv_version_major, dovi->dv_version_minor, + dovi->dv_profile, dovi->dv_level, + dovi->rpu_present_flag, + dovi->el_present_flag, + dovi->bl_present_flag, + dovi->dv_bl_signal_compatibility_id + ); + + return 0; +} + +int ff_mov_put_dvcc_dvvc(AVFormatContext *s, uint8_t *out, int size, uint32_t *type, + AVDOVIDecoderConfigurationRecord *dovi) +{ + PutBitContext pb; + init_put_bits(&pb, out, size); + + if (size < MOV_DVCC_DVVC_SIZE) + return AVERROR(EINVAL); + + if (dovi->dv_profile > 7) + *type = MKBETAG('d', 'v', 'v', 'C'); + else + *type = MKBETAG('d', 'v', 'c', 'C'); + + put_bits(&pb, 8, dovi->dv_version_major); + put_bits(&pb, 8, dovi->dv_version_minor); + put_bits(&pb, 7, dovi->dv_profile); + put_bits(&pb, 6, dovi->dv_level); + put_bits(&pb, 1, dovi->rpu_present_flag); + put_bits(&pb, 1, dovi->el_present_flag); + put_bits(&pb, 1, dovi->bl_present_flag); + put_bits(&pb, 4, dovi->dv_bl_signal_compatibility_id); + put_bits(&pb, 28, 0); /* reserved */ + put_bits32(&pb, 0); /* reserved */ + put_bits32(&pb, 0); /* reserved */ + put_bits32(&pb, 0); /* reserved */ + put_bits32(&pb, 0); /* reserved */ + flush_put_bits(&pb); + + av_log(s, AV_LOG_DEBUG, "DOVI in %s box, version: %d.%d, profile: %d, level: %d, " + "rpu flag: %d, el flag: %d, bl flag: %d, compatibility id: %d\n", + dovi->dv_profile > 7 ? "dvvC" : "dvcC", + dovi->dv_version_major, dovi->dv_version_minor, + dovi->dv_profile, dovi->dv_level, + dovi->rpu_present_flag, + dovi->el_present_flag, + dovi->bl_present_flag, + dovi->dv_bl_signal_compatibility_id); + + return put_bits_count(&pb) / 8; +} + const struct AVCodecTag *avformat_get_mov_video_tags(void) { return ff_codec_movvideo_tags; diff --git a/libavformat/isom.h b/libavformat/isom.h index 41a9c64c11962..e42549c5c9778 100644 --- a/libavformat/isom.h +++ b/libavformat/isom.h @@ -27,6 +27,10 @@ #include #include +#include "libavcodec/get_bits.h" +#include "libavcodec/put_bits.h" + +#include "libavutil/dovi_meta.h" #include "libavutil/encryption_info.h" #include "libavutil/mastering_display_metadata.h" #include "libavutil/spherical.h" @@ -362,6 +366,11 @@ int ff_mov_read_esds(AVFormatContext *fc, AVIOContext *pb); int ff_mov_read_stsd_entries(MOVContext *c, AVIOContext *pb, int entries); void ff_mov_write_chan(AVIOContext *pb, int64_t channel_layout); +#define MOV_DVCC_DVVC_SIZE 24 +int ff_mov_parse_dvcc_dvvc(AVFormatContext *s, AVStream *st, GetBitContext *gb); +int ff_mov_put_dvcc_dvvc(AVFormatContext *s, uint8_t *out, int size, uint32_t *type, + AVDOVIDecoderConfigurationRecord *dovi); + #define FF_MOV_FLAG_MFRA_AUTO -1 #define FF_MOV_FLAG_MFRA_DTS 1 #define FF_MOV_FLAG_MFRA_PTS 2 diff --git a/libavformat/matroska.h b/libavformat/matroska.h index 6f198f06e6a74..9d4ca869bbb65 100644 --- a/libavformat/matroska.h +++ b/libavformat/matroska.h @@ -106,6 +106,7 @@ #define MATROSKA_ID_TRACKCONTENTENCODING 0x6240 #define MATROSKA_ID_TRACKTIMECODESCALE 0x23314F #define MATROSKA_ID_TRACKMAXBLKADDID 0x55EE +#define MATROSKA_ID_TRACKBLKADDMAPPING 0x41E4 /* IDs in the trackvideo master */ #define MATROSKA_ID_VIDEOFRAMERATE 0x2383E3 @@ -184,6 +185,12 @@ #define MATROSKA_ID_ENCODINGSIGKEYID 0x47E4 #define MATROSKA_ID_ENCODINGSIGNATURE 0x47E3 +/* IDs in the block addition mapping master */ +#define MATROSKA_ID_BLKADDIDVALUE 0x41F0 +#define MATROSKA_ID_BLKADDIDNAME 0x41A4 +#define MATROSKA_ID_BLKADDIDTYPE 0x41E7 +#define MATROSKA_ID_BLKADDIDEXTRADATA 0x41ED + /* ID in the cues master */ #define MATROSKA_ID_POINTENTRY 0xBB diff --git a/libavformat/matroskadec.c b/libavformat/matroskadec.c index cff7f0cb54ab6..a06c93142d674 100644 --- a/libavformat/matroskadec.c +++ b/libavformat/matroskadec.c @@ -226,6 +226,13 @@ typedef struct MatroskaTrackOperation { EbmlList combine_planes; } MatroskaTrackOperation; +typedef struct MatroskaBlockAdditionMapping { + int value; + char *name; + int type; + EbmlBin extradata; +} MatroskaBlockAdditionMapping; + typedef struct MatroskaTrack { uint64_t num; uint64_t uid; @@ -251,6 +258,7 @@ typedef struct MatroskaTrack { int ms_compat; int needs_decoding; uint64_t max_block_additional_id; + EbmlList block_addition_mappings; uint32_t palette[AVPALETTE_COUNT]; int has_palette; @@ -397,8 +405,8 @@ typedef struct MatroskaDemuxContext { // incomplete type (6.7.2 in C90, 6.9.2 in C99). // Removing the sizes breaks MSVC. static EbmlSyntax ebml_syntax[3], matroska_segment[9], matroska_track_video_color[15], matroska_track_video[19], - matroska_track[27], matroska_track_encoding[6], matroska_track_encodings[2], - matroska_track_combine_planes[2], matroska_track_operation[2], matroska_tracks[2], + matroska_track[28], matroska_track_encoding[6], matroska_track_encodings[2], + matroska_track_combine_planes[2], matroska_track_operation[2], matroska_block_addition_mapping[5], matroska_tracks[2], matroska_attachments[2], matroska_chapter_entry[9], matroska_chapter[6], matroska_chapters[2], matroska_index_entry[3], matroska_index[2], matroska_tag[3], matroska_tags[2], matroska_seekhead[2], matroska_blockadditions[2], matroska_blockgroup[8], matroska_cluster_parsing[8]; @@ -548,6 +556,14 @@ static EbmlSyntax matroska_track_operation[] = { CHILD_OF(matroska_track) }; +static EbmlSyntax matroska_block_addition_mapping[] = { + { MATROSKA_ID_BLKADDIDVALUE, EBML_UINT, 0, offsetof(MatroskaBlockAdditionMapping, value) }, + { MATROSKA_ID_BLKADDIDNAME, EBML_STR, 0, offsetof(MatroskaBlockAdditionMapping, name) }, + { MATROSKA_ID_BLKADDIDTYPE, EBML_UINT, 0, offsetof(MatroskaBlockAdditionMapping, type) }, + { MATROSKA_ID_BLKADDIDEXTRADATA, EBML_BIN, 0, offsetof(MatroskaBlockAdditionMapping, extradata) }, + CHILD_OF(matroska_track) +}; + static EbmlSyntax matroska_track[] = { { MATROSKA_ID_TRACKNUMBER, EBML_UINT, 0, offsetof(MatroskaTrack, num) }, { MATROSKA_ID_TRACKNAME, EBML_UTF8, 0, offsetof(MatroskaTrack, name) }, @@ -566,6 +582,7 @@ static EbmlSyntax matroska_track[] = { { MATROSKA_ID_TRACKOPERATION, EBML_NEST, 0, offsetof(MatroskaTrack, operation), { .n = matroska_track_operation } }, { MATROSKA_ID_TRACKCONTENTENCODINGS, EBML_NEST, 0, 0, { .n = matroska_track_encodings } }, { MATROSKA_ID_TRACKMAXBLKADDID, EBML_UINT, 0, offsetof(MatroskaTrack, max_block_additional_id) }, + { MATROSKA_ID_TRACKBLKADDMAPPING, EBML_NEST, sizeof(MatroskaBlockAdditionMapping), offsetof(MatroskaTrack, block_addition_mappings), { .n = matroska_block_addition_mapping } }, { MATROSKA_ID_SEEKPREROLL, EBML_UINT, 0, offsetof(MatroskaTrack, seek_preroll) }, { MATROSKA_ID_TRACKFLAGENABLED, EBML_NONE }, { MATROSKA_ID_TRACKFLAGLACING, EBML_NONE }, @@ -2259,6 +2276,38 @@ static int mkv_parse_video_projection(AVStream *st, const MatroskaTrack *track, return 0; } +static int mkv_parse_dvcc_dvvc(AVFormatContext *s, AVStream *st, const MatroskaTrack *track, + EbmlBin *bin) +{ + GetBitContext gb; + init_get_bits8(&gb, bin->data, bin->size); + return ff_mov_parse_dvcc_dvvc(s, st, &gb); +} + +static int mkv_parse_block_addition_mappings(AVFormatContext *s, AVStream *st, const MatroskaTrack *track) +{ + int i, ret; + const EbmlList *mappings_list = &track->block_addition_mappings; + MatroskaBlockAdditionMapping *mappings = mappings_list->elem; + + for (i = 0; i < mappings_list->nb_elem; i++) { + MatroskaBlockAdditionMapping *mapping = &mappings[i]; + switch (mapping->type) { + case MKBETAG('d','v','c','C'): + case MKBETAG('d','v','v','C'): + if ((ret = mkv_parse_dvcc_dvvc(st, track, &mapping->extradata, s)) < 0) + return ret; + break; + default: + av_log(s, AV_LOG_DEBUG, + "Unknown block additional mapping type %i, value %i, name \"%s\"\n", + mapping->type, mapping->value, mapping->name ? mapping->name : ""); + } + } + + return 0; +} + static int get_qt_codec(MatroskaTrack *track, uint32_t *fourcc, enum AVCodecID *codec_id) { const AVCodecTag *codec_tags; @@ -2822,6 +2871,10 @@ static int matroska_parse_tracks(AVFormatContext *s) } else if (track->type == MATROSKA_TRACK_TYPE_SUBTITLE) { st->codecpar->codec_type = AVMEDIA_TYPE_SUBTITLE; } + + ret = mkv_parse_block_addition_mappings(st, track, matroska->ctx); + if (ret < 0) + return ret; } return 0; diff --git a/libavformat/matroskaenc.c b/libavformat/matroskaenc.c index eaed02bc92d3f..1bbc370ad826b 100644 --- a/libavformat/matroskaenc.c +++ b/libavformat/matroskaenc.c @@ -1110,6 +1110,33 @@ static int mkv_write_stereo_mode(AVFormatContext *s, AVIOContext *pb, return 0; } +static int mkv_write_dovi(AVFormatContext *s, AVIOContext *pb, AVStream *st) +{ + int ret; + AVDOVIDecoderConfigurationRecord *dovi = (AVDOVIDecoderConfigurationRecord *) + av_stream_get_side_data(st, AV_PKT_DATA_DOVI_CONF, NULL); + + if (dovi) { + ebml_master mapping; + uint8_t buf[MOV_DVCC_DVVC_SIZE]; + uint32_t type; + int size; + + if ((ret = ff_mov_put_dvcc_dvvc(s, buf, sizeof(buf), &type, dovi)) < 0) + return ret; + + size = ret; + + mapping = start_ebml_master(pb, MATROSKA_ID_TRACKBLKADDMAPPING, 0); + put_ebml_uint(pb, MATROSKA_ID_BLKADDIDVALUE, 0); + put_ebml_uint(pb, MATROSKA_ID_BLKADDIDTYPE, type); + put_ebml_binary(pb, MATROSKA_ID_BLKADDIDEXTRADATA, buf, size); + end_ebml_master(pb, mapping); + } + + return 0; +} + static int mkv_write_track(AVFormatContext *s, MatroskaMuxContext *mkv, AVStream *st, mkv_track *track, AVIOContext *pb, int is_default) @@ -1370,6 +1397,9 @@ static int mkv_write_track(AVFormatContext *s, MatroskaMuxContext *mkv, end_ebml_master(pb, track_master); + if ((ret = mkv_write_dovi(s, pb, st)) < 0) + return ret; + return 0; }