FFmpeg  4.4.4
hcom.c
Go to the documentation of this file.
1 /*
2  * HCOM audio decoder
3  *
4  * This file is part of FFmpeg.
5  *
6  * FFmpeg is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU Lesser General Public
8  * License as published by the Free Software Foundation; either
9  * version 2.1 of the License, or (at your option) any later version.
10  *
11  * FFmpeg is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14  * Lesser General Public License for more details.
15  *
16  * You should have received a copy of the GNU Lesser General Public
17  * License along with FFmpeg; if not, write to the Free Software
18  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
19  */
20 
21 #include "libavutil/intreadwrite.h"
22 
23 #include "avcodec.h"
24 #include "get_bits.h"
25 #include "internal.h"
26 
27 typedef struct HEntry {
28  int16_t l, r;
29 } HEntry;
30 
31 typedef struct HCOMContext {
33 
39 
41 } HCOMContext;
42 
43 static av_cold int hcom_init(AVCodecContext *avctx)
44 {
45  HCOMContext *s = avctx->priv_data;
46 
47  if (avctx->channels != 1) {
48  av_log(avctx, AV_LOG_ERROR, "invalid number of channels\n");
49  return AVERROR_INVALIDDATA;
50  }
51 
52  if (avctx->extradata_size <= 7)
53  return AVERROR_INVALIDDATA;
54  s->dict_entries = AV_RB16(avctx->extradata);
55  if (avctx->extradata_size < s->dict_entries * 4 + 7 ||
56  s->dict_entries == 0)
57  return AVERROR_INVALIDDATA;
58  s->delta_compression = AV_RB32(avctx->extradata + 2);
59  s->sample = s->first_sample = avctx->extradata[avctx->extradata_size - 1];
60 
61  s->dict = av_calloc(s->dict_entries, sizeof(*s->dict));
62  if (!s->dict)
63  return AVERROR(ENOMEM);
64  for (int i = 0; i < s->dict_entries; i++) {
65  s->dict[i].l = AV_RB16(avctx->extradata + 6 + 4 * i);
66  s->dict[i].r = AV_RB16(avctx->extradata + 6 + 4 * i + 2);
67  if (s->dict[i].l >= 0 &&
68  (s->dict[i].l >= s->dict_entries ||
69  s->dict[i].r >= s->dict_entries ||
70  s->dict[i].r < 0 ))
71  return AVERROR_INVALIDDATA;
72  }
73  if (s->dict[0].l < 0)
74  return AVERROR_INVALIDDATA;
75 
77  s->dict_entry = 0;
78 
79  return 0;
80 }
81 
82 static int hcom_decode(AVCodecContext *avctx, void *data,
83  int *got_frame, AVPacket *pkt)
84 {
85  HCOMContext *s = avctx->priv_data;
86  AVFrame *frame = data;
87  GetBitContext gb;
88  int ret, n = 0;
89 
90  if (pkt->size > INT16_MAX)
91  return AVERROR_INVALIDDATA;
92 
93  frame->nb_samples = pkt->size * 8;
94  if ((ret = ff_get_buffer(avctx, frame, 0)) < 0)
95  return ret;
96 
97  if ((ret = init_get_bits8(&gb, pkt->data, pkt->size)) < 0)
98  return ret;
99 
100  while (get_bits_left(&gb) > 0) {
101  if (get_bits1(&gb))
102  s->dict_entry = s->dict[s->dict_entry].r;
103  else
104  s->dict_entry = s->dict[s->dict_entry].l;
105 
106  if (s->dict[s->dict_entry].l < 0) {
107  int16_t datum;
108 
109  datum = s->dict[s->dict_entry].r;
110 
111  if (!s->delta_compression)
112  s->sample = 0;
113  s->sample = (s->sample + datum) & 0xFF;
114 
115  frame->data[0][n++] = s->sample;
116 
117  s->dict_entry = 0;
118  }
119  }
120 
121  frame->nb_samples = n;
122 
123  *got_frame = 1;
124 
125  return pkt->size;
126 }
127 
129 {
130  HCOMContext *s = avctx->priv_data;
131 
132  av_freep(&s->dict);
133 
134  return 0;
135 }
136 
138  .name = "hcom",
139  .long_name = NULL_IF_CONFIG_SMALL("HCOM Audio"),
140  .type = AVMEDIA_TYPE_AUDIO,
141  .id = AV_CODEC_ID_HCOM,
142  .priv_data_size = sizeof(HCOMContext),
143  .init = hcom_init,
144  .close = hcom_close,
145  .decode = hcom_decode,
146  .capabilities = AV_CODEC_CAP_DR1,
147  .caps_internal = FF_CODEC_CAP_INIT_CLEANUP,
148 };
#define av_cold
Definition: attributes.h:88
AV_SAMPLE_FMT_U8
uint8_t
Libavcodec external API header.
#define AV_RB32
Definition: intreadwrite.h:130
#define AV_RB16
Definition: intreadwrite.h:53
static av_cold int init(AVCodecContext *avctx)
Definition: avrndec.c:31
#define s(width, name)
Definition: cbs_vp9.c:257
int ff_get_buffer(AVCodecContext *avctx, AVFrame *frame, int flags)
Get a buffer for a frame.
Definition: decode.c:1900
static void decode(AVCodecContext *dec_ctx, AVPacket *pkt, AVFrame *frame, FILE *outfile)
Definition: decode_audio.c:71
static AVFrame * frame
bitstream reader API header.
static int get_bits_left(GetBitContext *gb)
Definition: get_bits.h:849
static unsigned int get_bits1(GetBitContext *s)
Definition: get_bits.h:498
static int init_get_bits8(GetBitContext *s, const uint8_t *buffer, int byte_size)
Initialize GetBitContext.
Definition: get_bits.h:677
#define AV_CODEC_CAP_DR1
Codec uses get_buffer() or get_encode_buffer() for allocating buffers and supports custom allocators.
Definition: codec.h:52
@ AV_CODEC_ID_HCOM
Definition: codec_id.h:514
#define AVERROR_INVALIDDATA
Invalid data found when processing input.
Definition: error.h:59
#define AVERROR(e)
Definition: error.h:43
#define AV_LOG_ERROR
Something went wrong and cannot losslessly be recovered.
Definition: log.h:194
void * av_calloc(size_t nmemb, size_t size)
Non-inlined equivalent of av_mallocz_array().
Definition: mem.c:245
@ AVMEDIA_TYPE_AUDIO
Definition: avutil.h:202
int i
Definition: input.c:407
static av_cold int hcom_init(AVCodecContext *avctx)
Definition: hcom.c:43
AVCodec ff_hcom_decoder
Definition: hcom.c:137
static av_cold int hcom_close(AVCodecContext *avctx)
Definition: hcom.c:128
static int hcom_decode(AVCodecContext *avctx, void *data, int *got_frame, AVPacket *pkt)
Definition: hcom.c:82
#define FF_CODEC_CAP_INIT_CLEANUP
The codec allows calling the close function for deallocation even if the init function returned a fai...
Definition: internal.h:49
common internal API header
#define NULL_IF_CONFIG_SMALL(x)
Return NULL if CONFIG_SMALL is true, otherwise the argument without modification.
Definition: internal.h:117
const char data[16]
Definition: mxf.c:142
main external API structure.
Definition: avcodec.h:536
enum AVSampleFormat sample_fmt
audio sample format
Definition: avcodec.h:1204
uint8_t * extradata
some codecs need / can use extradata like Huffman tables.
Definition: avcodec.h:637
int channels
number of audio channels
Definition: avcodec.h:1197
int extradata_size
Definition: avcodec.h:638
void * priv_data
Definition: avcodec.h:563
AVCodec.
Definition: codec.h:197
const char * name
Name of the codec implementation.
Definition: codec.h:204
This structure describes decoded (raw) audio or video data.
Definition: frame.h:318
int nb_samples
number of audio samples (per channel) described by this frame
Definition: frame.h:384
uint8_t * data[AV_NUM_DATA_POINTERS]
pointer to the picture/channel planes.
Definition: frame.h:332
This structure stores compressed data.
Definition: packet.h:346
int size
Definition: packet.h:370
uint8_t * data
Definition: packet.h:369
int delta_compression
Definition: hcom.c:38
uint8_t sample
Definition: hcom.c:35
HEntry * dict
Definition: hcom.c:40
AVCodecContext * avctx
Definition: hcom.c:32
uint8_t first_sample
Definition: hcom.c:34
int dict_entry
Definition: hcom.c:37
int dict_entries
Definition: hcom.c:36
Definition: hcom.c:27
int16_t r
Definition: hcom.c:28
int16_t l
Definition: hcom.c:28
#define av_freep(p)
#define av_log(a,...)
AVPacket * pkt
Definition: movenc.c:59