Skip to content
This repository has been archived by the owner on Jun 4, 2023. It is now read-only.

Implement MatroskaBlockAdditionMapping #18

Closed
wants to merge 7 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
2 changes: 1 addition & 1 deletion Makefile
Expand Up @@ -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
Expand Down
2 changes: 1 addition & 1 deletion ffbuild/common.mak
Expand Up @@ -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 $@ $<
Expand Down
2 changes: 2 additions & 0 deletions ffbuild/version.sh
Expand Up @@ -2,6 +2,7 @@

# Usage: version.sh <ffmpeg-root-dir> <output-version.h> <extra-version>

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
Expand All @@ -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)
Expand Down
10 changes: 6 additions & 4 deletions libavcodec/dxva2.c
Expand Up @@ -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

Expand Down
8 changes: 8 additions & 0 deletions libavcodec/dxva2_h264.c
Expand Up @@ -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),
Expand Down
1 change: 1 addition & 0 deletions libavcodec/h264_slice.c
Expand Up @@ -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);
Expand Down
1 change: 1 addition & 0 deletions libavcodec/h264dec.c
Expand Up @@ -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;
Expand Down
2 changes: 2 additions & 0 deletions libavcodec/h264dec.h
Expand Up @@ -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
Expand Down
5 changes: 5 additions & 0 deletions libavcodec/vaapi_h264.c
Expand Up @@ -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;
Expand Down
91 changes: 91 additions & 0 deletions libavformat/isom.c
Expand Up @@ -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;
Expand Down
9 changes: 9 additions & 0 deletions libavformat/isom.h
Expand Up @@ -27,6 +27,10 @@
#include <stddef.h>
#include <stdint.h>

#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"
Expand Down Expand Up @@ -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
Expand Down
7 changes: 7 additions & 0 deletions libavformat/matroska.h
Expand Up @@ -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
Expand Down Expand Up @@ -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

Expand Down
57 changes: 55 additions & 2 deletions libavformat/matroskadec.c
Expand Up @@ -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;
Expand All @@ -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;
Expand Down Expand Up @@ -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];
Expand Down Expand Up @@ -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) },
Expand All @@ -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 },
Expand Down Expand Up @@ -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;
Expand Down Expand Up @@ -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;
Expand Down