Skip to content

Commit

Permalink
libde265: add callback mechanism to parse events
Browse files Browse the repository at this point in the history
Add a mechanism that allows a decoder tool to get a callback for
every NAL unit, slice content, and image that it is interested on.
The idea is for the decoder tool to subscribe to the event it wants
to hear about, and then get the parser object.

This requires:

* replace C linkage with C++ linkage, so that we can add classes in the
callback
* move error codes to separate file, to break the circular dependency
between several files (e.g. `[sps|pps|vps].h`) and de265.h

Tested:

Wrote a decoder that subscribes to all the events, and just calls the
`dump` method for every object.
  • Loading branch information
chemag committed Apr 19, 2019
1 parent c172dd8 commit 4f94230
Show file tree
Hide file tree
Showing 11 changed files with 159 additions and 81 deletions.
1 change: 1 addition & 0 deletions libde265/Makefile.am
Original file line number Diff line number Diff line change
Expand Up @@ -120,4 +120,5 @@ EXTRA_DIST = Makefile.vc7 \

libde265_la_HEADERS = \
de265.h \
de265-error.h \
de265-version.h
1 change: 0 additions & 1 deletion libde265/contextmodel.h
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,6 @@
#define DE265_CONTEXTMODEL_H

#include "libde265/cabac.h"
#include "libde265/de265.h"

#include <string.h>
#include <string>
Expand Down
86 changes: 86 additions & 0 deletions libde265/de265-error.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,86 @@
/*
* H.265 video codec.
* Copyright (c) 2013-2014 struktur AG, Dirk Farin <[email protected]>
*
* This file is part of libde265.
*
* libde265 is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as
* published by the Free Software Foundation, either version 3 of
* the License, or (at your option) any later version.
*
* libde265 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 Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with libde265. If not, see <http://www.gnu.org/licenses/>.
*/


#ifndef DE265_ERROR_H
#define DE265_ERROR_H

/* === error codes === */

typedef enum {
DE265_OK = 0,
DE265_ERROR_NO_SUCH_FILE=1,
//DE265_ERROR_NO_STARTCODE=2, obsolete
//DE265_ERROR_EOF=3,
DE265_ERROR_COEFFICIENT_OUT_OF_IMAGE_BOUNDS=4,
DE265_ERROR_CHECKSUM_MISMATCH=5,
DE265_ERROR_CTB_OUTSIDE_IMAGE_AREA=6,
DE265_ERROR_OUT_OF_MEMORY=7,
DE265_ERROR_CODED_PARAMETER_OUT_OF_RANGE=8,
DE265_ERROR_IMAGE_BUFFER_FULL=9,
DE265_ERROR_CANNOT_START_THREADPOOL=10,
DE265_ERROR_LIBRARY_INITIALIZATION_FAILED=11,
DE265_ERROR_LIBRARY_NOT_INITIALIZED=12,
DE265_ERROR_WAITING_FOR_INPUT_DATA=13,
DE265_ERROR_CANNOT_PROCESS_SEI=14,
DE265_ERROR_PARAMETER_PARSING=15,
DE265_ERROR_NO_INITIAL_SLICE_HEADER=16,
DE265_ERROR_PREMATURE_END_OF_SLICE=17,
DE265_ERROR_UNSPECIFIED_DECODING_ERROR=18,

// --- errors that should become obsolete in later libde265 versions ---

//DE265_ERROR_MAX_THREAD_CONTEXTS_EXCEEDED = 500, obsolete
//DE265_ERROR_MAX_NUMBER_OF_SLICES_EXCEEDED = 501, obsolete
DE265_ERROR_NOT_IMPLEMENTED_YET = 502,
//DE265_ERROR_SCALING_LIST_NOT_IMPLEMENTED = 502, obsolete

// --- warnings ---

DE265_WARNING_NO_WPP_CANNOT_USE_MULTITHREADING = 1000,
DE265_WARNING_WARNING_BUFFER_FULL=1001,
DE265_WARNING_PREMATURE_END_OF_SLICE_SEGMENT=1002,
DE265_WARNING_INCORRECT_ENTRY_POINT_OFFSET=1003,
DE265_WARNING_CTB_OUTSIDE_IMAGE_AREA=1004,
DE265_WARNING_SPS_HEADER_INVALID=1005,
DE265_WARNING_PPS_HEADER_INVALID=1006,
DE265_WARNING_SLICEHEADER_INVALID=1007,
DE265_WARNING_INCORRECT_MOTION_VECTOR_SCALING=1008,
DE265_WARNING_NONEXISTING_PPS_REFERENCED=1009,
DE265_WARNING_NONEXISTING_SPS_REFERENCED=1010,
DE265_WARNING_BOTH_PREDFLAGS_ZERO=1011,
DE265_WARNING_NONEXISTING_REFERENCE_PICTURE_ACCESSED=1012,
DE265_WARNING_NUMMVP_NOT_EQUAL_TO_NUMMVQ=1013,
DE265_WARNING_NUMBER_OF_SHORT_TERM_REF_PIC_SETS_OUT_OF_RANGE=1014,
DE265_WARNING_SHORT_TERM_REF_PIC_SET_OUT_OF_RANGE=1015,
DE265_WARNING_FAULTY_REFERENCE_PICTURE_LIST=1016,
DE265_WARNING_EOSS_BIT_NOT_SET=1017,
DE265_WARNING_MAX_NUM_REF_PICS_EXCEEDED=1018,
DE265_WARNING_INVALID_CHROMA_FORMAT=1019,
DE265_WARNING_SLICE_SEGMENT_ADDRESS_INVALID=1020,
DE265_WARNING_DEPENDENT_SLICE_WITH_ADDRESS_ZERO=1021,
DE265_WARNING_NUMBER_OF_THREADS_LIMITED_TO_MAXIMUM=1022,
DE265_NON_EXISTING_LT_REFERENCE_CANDIDATE_IN_SLICE_HEADER=1023,
DE265_WARNING_CANNOT_APPLY_SAO_OUT_OF_MEMORY=1024,
DE265_WARNING_SPS_MISSING_CANNOT_DECODE_SEI=1025,
DE265_WARNING_COLLOCATED_MOTION_VECTOR_OUTSIDE_IMAGE_AREA=1026
} de265_error;

#endif
14 changes: 12 additions & 2 deletions libde265/de265.cc
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,6 @@
// TODO: should be in some vps.c related header
de265_error read_vps(decoder_context* ctx, bitreader* reader, video_parameter_set* vps);

extern "C" {
LIBDE265_API const char *de265_get_version(void)
{
return (LIBDE265_VERSION);
Expand Down Expand Up @@ -468,6 +467,18 @@ LIBDE265_API int de265_change_framerate(de265_decoder_context* de265ctx,int mor
return ctx->change_framerate(more);
}

LIBDE265_API void de265_callback_register(de265_decoder_context* de265ctx, de265_callback_block* cbb)
{
decoder_context* ctx = (decoder_context*)de265ctx;
ctx->callback_register(cbb);
}

LIBDE265_API void de265_callback_unregister(de265_decoder_context* de265ctx)
{
decoder_context* ctx = (decoder_context*)de265ctx;
ctx->callback_unregister();
}


LIBDE265_API de265_error de265_get_warning(de265_decoder_context* de265ctx)
{
Expand Down Expand Up @@ -708,4 +719,3 @@ LIBDE265_API void de265_get_image_NAL_header(const struct de265_image* img,
if (nuh_layer_id) *nuh_layer_id = img->nal_hdr.nuh_layer_id;
if (nuh_temporal_id) *nuh_temporal_id = img->nal_hdr.nuh_temporal_id;
}
}
87 changes: 20 additions & 67 deletions libde265/de265.h
Original file line number Diff line number Diff line change
Expand Up @@ -22,9 +22,6 @@
#ifndef DE265_H
#define DE265_H

#ifdef __cplusplus
extern "C" {
#endif

#include <libde265/de265-version.h>

Expand Down Expand Up @@ -66,6 +63,11 @@ extern "C" {
#define LIBDE265_INLINE inline
#endif

#include "de265-error.h"
#include "vps.h"
#include "pps.h"
#include "sps.h"

/* === version numbers === */

// version of linked libde265 library
Expand All @@ -77,67 +79,7 @@ LIBDE265_API int de265_get_version_number_minor(void);
LIBDE265_API int de265_get_version_number_maintenance(void);


/* === error codes === */

typedef enum {
DE265_OK = 0,
DE265_ERROR_NO_SUCH_FILE=1,
//DE265_ERROR_NO_STARTCODE=2, obsolet
//DE265_ERROR_EOF=3,
DE265_ERROR_COEFFICIENT_OUT_OF_IMAGE_BOUNDS=4,
DE265_ERROR_CHECKSUM_MISMATCH=5,
DE265_ERROR_CTB_OUTSIDE_IMAGE_AREA=6,
DE265_ERROR_OUT_OF_MEMORY=7,
DE265_ERROR_CODED_PARAMETER_OUT_OF_RANGE=8,
DE265_ERROR_IMAGE_BUFFER_FULL=9,
DE265_ERROR_CANNOT_START_THREADPOOL=10,
DE265_ERROR_LIBRARY_INITIALIZATION_FAILED=11,
DE265_ERROR_LIBRARY_NOT_INITIALIZED=12,
DE265_ERROR_WAITING_FOR_INPUT_DATA=13,
DE265_ERROR_CANNOT_PROCESS_SEI=14,
DE265_ERROR_PARAMETER_PARSING=15,
DE265_ERROR_NO_INITIAL_SLICE_HEADER=16,
DE265_ERROR_PREMATURE_END_OF_SLICE=17,
DE265_ERROR_UNSPECIFIED_DECODING_ERROR=18,

// --- errors that should become obsolete in later libde265 versions ---

//DE265_ERROR_MAX_THREAD_CONTEXTS_EXCEEDED = 500, obsolet
//DE265_ERROR_MAX_NUMBER_OF_SLICES_EXCEEDED = 501, obsolet
DE265_ERROR_NOT_IMPLEMENTED_YET = 502,
//DE265_ERROR_SCALING_LIST_NOT_IMPLEMENTED = 502, obsolet

// --- warnings ---

DE265_WARNING_NO_WPP_CANNOT_USE_MULTITHREADING = 1000,
DE265_WARNING_WARNING_BUFFER_FULL=1001,
DE265_WARNING_PREMATURE_END_OF_SLICE_SEGMENT=1002,
DE265_WARNING_INCORRECT_ENTRY_POINT_OFFSET=1003,
DE265_WARNING_CTB_OUTSIDE_IMAGE_AREA=1004,
DE265_WARNING_SPS_HEADER_INVALID=1005,
DE265_WARNING_PPS_HEADER_INVALID=1006,
DE265_WARNING_SLICEHEADER_INVALID=1007,
DE265_WARNING_INCORRECT_MOTION_VECTOR_SCALING=1008,
DE265_WARNING_NONEXISTING_PPS_REFERENCED=1009,
DE265_WARNING_NONEXISTING_SPS_REFERENCED=1010,
DE265_WARNING_BOTH_PREDFLAGS_ZERO=1011,
DE265_WARNING_NONEXISTING_REFERENCE_PICTURE_ACCESSED=1012,
DE265_WARNING_NUMMVP_NOT_EQUAL_TO_NUMMVQ=1013,
DE265_WARNING_NUMBER_OF_SHORT_TERM_REF_PIC_SETS_OUT_OF_RANGE=1014,
DE265_WARNING_SHORT_TERM_REF_PIC_SET_OUT_OF_RANGE=1015,
DE265_WARNING_FAULTY_REFERENCE_PICTURE_LIST=1016,
DE265_WARNING_EOSS_BIT_NOT_SET=1017,
DE265_WARNING_MAX_NUM_REF_PICS_EXCEEDED=1018,
DE265_WARNING_INVALID_CHROMA_FORMAT=1019,
DE265_WARNING_SLICE_SEGMENT_ADDRESS_INVALID=1020,
DE265_WARNING_DEPENDENT_SLICE_WITH_ADDRESS_ZERO=1021,
DE265_WARNING_NUMBER_OF_THREADS_LIMITED_TO_MAXIMUM=1022,
DE265_NON_EXISTING_LT_REFERENCE_CANDIDATE_IN_SLICE_HEADER=1023,
DE265_WARNING_CANNOT_APPLY_SAO_OUT_OF_MEMORY=1024,
DE265_WARNING_SPS_MISSING_CANNOT_DECODE_SEI=1025,
DE265_WARNING_COLLOCATED_MOTION_VECTOR_OUTSIDE_IMAGE_AREA=1026
} de265_error;

/* === error code management === */
LIBDE265_API const char* de265_get_error_text(de265_error err);

/* Returns true, if 'err' is DE265_OK or a warning.
Expand Down Expand Up @@ -387,6 +329,20 @@ enum de265_param {
//DE265_DECODER_PARAM_DISABLE_INTRA_RESIDUAL_IDCT=10 // (bool) disable decoding of IDCT residuals in MC blocks
};

/* --- callback --- */
struct de265_callback_block
{
void (*get_vps)(video_parameter_set* vps);
void (*get_sps)(seq_parameter_set* sps);
void (*get_pps)(pic_parameter_set* pps);
void (*get_image)(de265_image* img);
};
LIBDE265_API void de265_callback_register(de265_decoder_context*, de265_callback_block*);
LIBDE265_API void de265_callback_unregister(de265_decoder_context*);

/* The user data pointer will be given to the get_buffer() and release_buffer() functions
in de265_image_allocation. */

// sorted such that a large ID includes all optimizations from lower IDs
enum de265_acceleration {
de265_acceleration_SCALAR = 0, // only fallback implementation
Expand Down Expand Up @@ -430,8 +386,5 @@ LIBDE265_API de265_error de265_init(void);
LIBDE265_API de265_error de265_free(void);


#ifdef __cplusplus
}
#endif

#endif
30 changes: 30 additions & 0 deletions libde265/decctx.cc
Original file line number Diff line number Diff line change
Expand Up @@ -301,6 +301,7 @@ decoder_context::decoder_context()
*/


cbb = NULL;

// --- internal data ---

Expand Down Expand Up @@ -540,6 +541,10 @@ de265_error decoder_context::read_vps_NAL(bitreader& reader)
new_vps->dump(param_vps_headers_fd);
}

if (cbb != NULL && cbb->get_vps != NULL) {
cbb->get_vps(new_vps.get());
}

vps[ new_vps->video_parameter_set_id ] = new_vps;

return DE265_OK;
Expand All @@ -560,6 +565,10 @@ de265_error decoder_context::read_sps_NAL(bitreader& reader)
new_sps->dump(param_sps_headers_fd);
}

if (cbb != NULL && cbb->get_sps != NULL) {
cbb->get_sps(new_sps.get());
}

sps[ new_sps->seq_parameter_set_id ] = new_sps;

return DE265_OK;
Expand All @@ -577,6 +586,10 @@ de265_error decoder_context::read_pps_NAL(bitreader& reader)
new_pps->dump(param_pps_headers_fd);
}

if (cbb != NULL && cbb->get_pps != NULL) {
cbb->get_pps(new_pps.get());
}

if (success) {
pps[ (int)new_pps->pic_parameter_set_id ] = new_pps;
}
Expand All @@ -596,6 +609,7 @@ de265_error decoder_context::read_sei_NAL(bitreader& reader, bool suffix)

if ((err=read_sei(&reader,&sei, suffix, current_sps.get())) == DE265_OK) {
dump_sei(&sei, current_sps.get());
// TODO: add SEI callback here

if (image_units.empty()==false && suffix) {
image_units.back()->suffix_SEIs.push_back(sei);
Expand Down Expand Up @@ -635,6 +649,7 @@ de265_error decoder_context::read_slice_NAL(bitreader& reader, NAL_unit* nal, na
shdr->dump_slice_segment_header(this, param_slice_headers_fd);
}

// TODO: add slice_header callback here

if (process_slice_segment_header(shdr, &err, nal->pts, &nal_hdr, nal->user_data) == false)
{
Expand Down Expand Up @@ -778,6 +793,9 @@ de265_error decoder_context::decode_some(bool* did_work)
break;
}

if (cbb != NULL && cbb->get_image != NULL) {
cbb->get_image(imgunit->img);
}

push_picture_to_output_queue(imgunit);

Expand Down Expand Up @@ -2228,6 +2246,18 @@ void decoder_context::calc_tid_and_framerate_ratio()
}


void decoder_context::callback_register(de265_callback_block* cbb_)
{
cbb = cbb_;
}


void decoder_context::callback_unregister()
{
cbb = NULL;
}


void error_queue::add_warning(de265_error warning, bool once)
{
// check if warning was already shown
Expand Down
7 changes: 7 additions & 0 deletions libde265/decctx.h
Original file line number Diff line number Diff line change
Expand Up @@ -412,6 +412,11 @@ class decoder_context : public base_context {
int change_framerate(int more_vs_less); // 1: more, -1: less
void set_framerate_ratio(int percent);

// --- decode callback ---

void callback_register(de265_callback_block* cbb);
void callback_unregister();

private:
// input parameters
int limit_HighestTid; // never switch to a layer above this one
Expand All @@ -429,6 +434,8 @@ class decoder_context : public base_context {
} framedrop_tab[100+1];
int framedrop_tid_index[6+1];

de265_callback_block* cbb;

void compute_framedrop_table();
void calc_tid_and_framerate_ratio();

Expand Down
8 changes: 0 additions & 8 deletions libde265/en265.h
Original file line number Diff line number Diff line change
Expand Up @@ -23,10 +23,6 @@
#ifndef EN265_H
#define EN265_H

#ifdef __cplusplus
extern "C" {
#endif

#include <libde265/de265.h>


Expand Down Expand Up @@ -210,9 +206,5 @@ LIBDE265_API void en265_free_packet(en265_encoder_context*, struct en265_packet*

LIBDE265_API int en265_number_of_queued_packets(en265_encoder_context*);

#ifdef __cplusplus
}
#endif


#endif
2 changes: 1 addition & 1 deletion libde265/sps.h
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@
#include "libde265/vui.h"
#include "libde265/bitstream.h"
#include "libde265/refpic.h"
#include "libde265/de265.h"
#include "libde265/de265-error.h"
#include "libde265/cabac.h"

#include <vector>
Expand Down
2 changes: 1 addition & 1 deletion libde265/vps.h
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@
#endif

#include "libde265/bitstream.h"
#include "libde265/de265.h"
#include "libde265/de265-error.h"
#include "libde265/cabac.h"

#include <vector>
Expand Down
Loading

0 comments on commit 4f94230

Please sign in to comment.