On 9/9/2018 7:08 PM, Mark Thompson wrote: > --- > Against versions which people might have seen before: > * Removed all of the vestigial annex B support (not useful, we are going to > ensure that AVPackets in FFmpeg never hold annex B data). > * gm_params subexp parsing made sensible - it doesn't compute the actual > gm_params values any more, but the code actually makes sense rather than > being opaque pasta from the standard. > * Metadata support added. > * Tile-group / tile-info / frame-with-tiles OBUs are combined in a hopefully > better way. > * Miscellaneous small fixes. > > Thanks to James Almer for testing and various fixes incorporated into this. > > > configure | 2 + > libavcodec/Makefile | 1 + > libavcodec/av1.h | 88 ++ > libavcodec/cbs.c | 6 + > libavcodec/cbs_av1.c | 1293 ++++++++++++++++++++ > libavcodec/cbs_av1.h | 429 +++++++ > libavcodec/cbs_av1_syntax_template.c | 1676 ++++++++++++++++++++++++++ > libavcodec/cbs_internal.h | 1 + > 8 files changed, 3496 insertions(+) > create mode 100644 libavcodec/cbs_av1.c > create mode 100644 libavcodec/cbs_av1.h > create mode 100644 libavcodec/cbs_av1_syntax_template.c
[...] > +static int cbs_av1_split_fragment(CodedBitstreamContext *ctx, > + CodedBitstreamFragment *frag, > + int header) > +{ > + GetBitContext gbc; > + uint8_t *data; > + size_t size; > + uint64_t obu_length; > + int pos, err; > + > + data = frag->data; > + size = frag->data_size; > + > + while (size > 0) { > + AV1RawOBUHeader header; > + uint64_t obu_size; > + > + init_get_bits(&gbc, data, 8 * size); > + > + err = cbs_av1_read_obu_header(ctx, &gbc, &header); This is generating a lot of noise when using the trace_headers bsf. Basically printing the header fields twice per OBU, first when splitting, then again when decomposing. You can get rid of that and simplify this function a lot if you use the ff_av1_packet_split() API from av1_parse.h doing more or less the same to what you're doing for h2645: static int cbs_av1_split_fragment(CodedBitstreamContext *ctx, CodedBitstreamFragment *frag, int header) { CodedBitstreamAV1Context *priv = ctx->priv_data; int err; err = ff_av1_packet_split(&priv->read_packet, frag->data, frag->data_size, ctx->log_ctx); if (err < 0) return err; for (int i = 0; i < priv->read_packet.nb_obus; i++) { const AV1OBU *obu = &priv->read_packet.obus[i]; uint8_t *data = (uint8_t *)obu->raw_data; size_t size = obu->raw_size; err = ff_cbs_insert_unit_data(ctx, frag, -1, obu->type, data, size, frag->data_ref); if (err < 0) return err; } return 0; } [...] > +static int FUNC(uncompressed_header)(CodedBitstreamContext *ctx, RWContext > *rw, > + AV1RawFrameHeader *current) > +{ > + CodedBitstreamAV1Context *priv = ctx->priv_data; > + const AV1RawSequenceHeader *seq; > + int id_len, all_frames, frame_is_intra, order_hint_bits; > + int i, err; > + > + if (!priv->sequence_header) { > + av_log(ctx->log_ctx, AV_LOG_ERROR, "No sequence header available: " > + "unable to decode frame header.\n"); > + return AVERROR_INVALIDDATA; > + } > + seq = priv->sequence_header; > + > + id_len = seq->additional_frame_id_length_minus_1 + > + seq->delta_frame_id_length_minus_2 + 3; > + all_frames = (1 << AV1_NUM_REF_FRAMES) - 1; > + > + if (seq->reduced_still_picture_header) { > + infer(show_existing_frame, 0); > + infer(frame_type, AV1_FRAME_KEY); > + infer(show_frame, 1); > + infer(showable_frame, 0); > + frame_is_intra = 1; > + > + } else { > + flag(show_existing_frame); > + > + if (current->show_existing_frame) { > + AV1ReferenceFrameState *frame; > + > + fb(3, frame_to_show_map_idx); > + frame = &priv->ref[current->frame_to_show_map_idx]; > + > + if (seq->decoder_model_info_present_flag && > + !seq->timing_info.equal_picture_interval) { > + > fb(seq->decoder_model_info.frame_presentation_time_length_minus_1 + 1, > + frame_presentation_time); > + } > + > + if (seq->frame_id_numbers_present_flag) > + fb(id_len, display_frame_id); > + > + if (frame->frame_type == AV1_FRAME_KEY) > + infer(refresh_frame_flags, all_frames); > + else > + infer(refresh_frame_flags, 0); > + > + return 0; > + } > + > + fb(2, frame_type); > + frame_is_intra = (current->frame_type == AV1_FRAME_INTRA_ONLY || > + current->frame_type == AV1_FRAME_KEY); > + > + flag(show_frame); > + if (current->show_frame && > + seq->decoder_model_info_present_flag && > + !seq->timing_info.equal_picture_interval) { > + > fb(seq->decoder_model_info.frame_presentation_time_length_minus_1 + 1, > + frame_presentation_time); > + } > + if (current->show_frame) > + infer(showable_frame, current->frame_type != AV1_FRAME_KEY); > + else > + flag(showable_frame); > + > + if (current->frame_type == AV1_FRAME_SWITCH || > + (current->frame_type == AV1_FRAME_KEY && current->show_frame)) > + infer(error_resilient_mode, 1); > + else > + flag(error_resilient_mode); > + } > + > + if (current->frame_type == AV1_FRAME_KEY && current->show_frame) { > + for (i = 0; i < AV1_NUM_REF_FRAMES; i++) { > + priv->ref[i].valid = 0; > + priv->ref[i].order_hint = 0; > + } > + } > + > + flag(disable_cdf_update); > + > + if (seq->seq_force_screen_content_tools == > + AV1_SELECT_SCREEN_CONTENT_TOOLS) { > + flag(allow_screen_content_tools); > + } else { > + infer(allow_screen_content_tools, > + seq->seq_force_screen_content_tools); > + } > + if (current->allow_screen_content_tools) { > + if (seq->seq_force_integer_mv == AV1_SELECT_INTEGER_MV) > + flag(force_integer_mv); > + else > + infer(force_integer_mv, seq->seq_force_integer_mv); > + } else { > + infer(force_integer_mv, 0); > + } > + > + if (seq->frame_id_numbers_present_flag) > + fb(id_len, current_frame_id); At this point you should call a mark_ref_frames() function that compares current_frame_id with that of reference frames, which can result in any of those references set as invalid. Looks good otherwise. Couldn't find other issues after a quick glance, and it works with all the samples i tried. Great work! _______________________________________________ ffmpeg-devel mailing list ffmpeg-devel@ffmpeg.org http://ffmpeg.org/mailman/listinfo/ffmpeg-devel