static int adx_parse(AVCodecParserContext *s1, AVCodecContext *avctx, const uint8_t **poutbuf, int *poutbuf_size, const uint8_t *buf, int buf_size) { ADXParseContext *s = s1->priv_data; ParseContext *pc = &s->pc; int next = END_NOT_FOUND; if (!avctx->extradata_size) { int ret; ff_combine_frame(pc, END_NOT_FOUND, &buf, &buf_size); if (!s->header_size && pc->index >= MIN_HEADER_SIZE) { if (ret = avpriv_adx_decode_header(avctx, pc->buffer, pc->index, &s->header_size, NULL)) return AVERROR_INVALIDDATA; s->block_size = BLOCK_SIZE * avctx->channels; } if (s->header_size && s->header_size <= pc->index) { avctx->extradata = av_mallocz(s->header_size + FF_INPUT_BUFFER_PADDING_SIZE); if (!avctx->extradata) return AVERROR(ENOMEM); avctx->extradata_size = s->header_size; memcpy(avctx->extradata, pc->buffer, s->header_size); memmove(pc->buffer, pc->buffer + s->header_size, s->header_size); pc->index -= s->header_size; } *poutbuf = NULL; *poutbuf_size = 0; return buf_size; } if (pc->index - s->buf_pos >= s->block_size) { *poutbuf = &pc->buffer[s->buf_pos]; *poutbuf_size = s->block_size; s->buf_pos += s->block_size; return 0; } if (pc->index && s->buf_pos) { memmove(pc->buffer, &pc->buffer[s->buf_pos], pc->index - s->buf_pos); pc->index -= s->buf_pos; s->buf_pos = 0; } if (buf_size + pc->index >= s->block_size) next = s->block_size - pc->index; if (ff_combine_frame(pc, next, &buf, &buf_size) < 0 || !buf_size) { *poutbuf = NULL; *poutbuf_size = 0; return buf_size; } *poutbuf = buf; *poutbuf_size = buf_size; return next; }
static av_cold int adx_decode_init(AVCodecContext *avctx) { ADXContext *c = avctx->priv_data; int ret, header_size; if (avctx->extradata_size >= 24) { if ((ret = avpriv_adx_decode_header(avctx, avctx->extradata, avctx->extradata_size, &header_size, c->coeff)) < 0) { av_log(avctx, AV_LOG_ERROR, "error parsing ADX header\n"); return AVERROR_INVALIDDATA; } c->channels = avctx->channels; c->header_parsed = 1; } avctx->sample_fmt = AV_SAMPLE_FMT_S16P; return 0; }
static int adx_read_header(AVFormatContext *s) { ADXDemuxerContext *c = s->priv_data; AVCodecContext *avctx; int ret; AVStream *st = avformat_new_stream(s, NULL); if (!st) return AVERROR(ENOMEM); avctx = s->streams[0]->codec; if (avio_rb16(s->pb) != 0x8000) return AVERROR_INVALIDDATA; c->header_size = avio_rb16(s->pb) + 4; avio_seek(s->pb, -4, SEEK_CUR); avctx->extradata = av_mallocz(c->header_size + FF_INPUT_BUFFER_PADDING_SIZE); if (!avctx->extradata) return AVERROR(ENOMEM); if (avio_read(s->pb, avctx->extradata, c->header_size) < c->header_size) { av_freep(&avctx->extradata); return AVERROR(EIO); } avctx->extradata_size = c->header_size; ret = avpriv_adx_decode_header(avctx, avctx->extradata, avctx->extradata_size, &c->header_size, NULL); if (ret) return ret; st->codec->codec_type = AVMEDIA_TYPE_AUDIO; st->codec->codec_id = s->iformat->value; avpriv_set_pts_info(st, 64, BLOCK_SAMPLES, avctx->sample_rate); return 0; }
static int adx_decode_frame(AVCodecContext *avctx, void *data, int *got_frame_ptr, AVPacket *avpkt) { int buf_size = avpkt->size; ADXContext *c = (ADXContext *)avctx->priv_data; int16_t *samples; const uint8_t *buf = avpkt->data; int num_blocks, ch, ret; if (c->eof) { *got_frame_ptr = 0; return buf_size; } if (!c->header_parsed && buf_size >= 2 && AV_RB16(buf) == 0x8000) { int header_size; if ((ret = avpriv_adx_decode_header(avctx, buf, buf_size, &header_size, c->coeff)) < 0) { av_log(avctx, AV_LOG_ERROR, "error parsing ADX header\n"); return AVERROR_INVALIDDATA; } c->channels = avctx->channels; c->header_parsed = 1; if (buf_size < header_size) return AVERROR_INVALIDDATA; buf += header_size; buf_size -= header_size; } if (!c->header_parsed) return AVERROR_INVALIDDATA; /* calculate number of blocks in the packet */ num_blocks = buf_size / (BLOCK_SIZE * c->channels); /* if the packet is not an even multiple of BLOCK_SIZE, check for an EOF packet */ if (!num_blocks || buf_size % (BLOCK_SIZE * avctx->channels)) { if (buf_size >= 4 && (AV_RB16(buf) & 0x8000)) { c->eof = 1; *got_frame_ptr = 0; return avpkt->size; } return AVERROR_INVALIDDATA; } /* get output buffer */ c->frame.nb_samples = num_blocks * BLOCK_SAMPLES; if ((ret = avctx->get_buffer(avctx, &c->frame)) < 0) { av_log(avctx, AV_LOG_ERROR, "get_buffer() failed\n"); return ret; } samples = (int16_t *)c->frame.data[0]; while (num_blocks--) { for (ch = 0; ch < c->channels; ch++) { if (adx_decode(c, samples + ch, buf, ch)) { c->eof = 1; buf = avpkt->data + avpkt->size; break; } buf_size -= BLOCK_SIZE; buf += BLOCK_SIZE; } samples += BLOCK_SAMPLES * c->channels; } *got_frame_ptr = 1; *(AVFrame *)data = c->frame; return buf - avpkt->data; }
static int adx_decode_frame(AVCodecContext *avctx, void *data, int *got_frame_ptr, AVPacket *avpkt) { AVFrame *frame = data; int buf_size = avpkt->size; ADXContext *c = avctx->priv_data; int16_t **samples; int samples_offset; const uint8_t *buf = avpkt->data; const uint8_t *buf_end = buf + avpkt->size; int num_blocks, ch, ret; if (c->eof) { *got_frame_ptr = 0; return buf_size; } if (!c->header_parsed && buf_size >= 2 && AV_RB16(buf) == 0x8000) { int header_size; if ((ret = avpriv_adx_decode_header(avctx, buf, buf_size, &header_size, c->coeff)) < 0) { av_log(avctx, AV_LOG_ERROR, "error parsing ADX header\n"); return AVERROR_INVALIDDATA; } c->channels = avctx->channels; c->header_parsed = 1; if (buf_size < header_size) return AVERROR_INVALIDDATA; buf += header_size; buf_size -= header_size; } if (!c->header_parsed) return AVERROR_INVALIDDATA; /* calculate number of blocks in the packet */ num_blocks = buf_size / (BLOCK_SIZE * c->channels); /* if the packet is not an even multiple of BLOCK_SIZE, check for an EOF packet */ if (!num_blocks || buf_size % (BLOCK_SIZE * avctx->channels)) { if (buf_size >= 4 && (AV_RB16(buf) & 0x8000)) { c->eof = 1; *got_frame_ptr = 0; return avpkt->size; } return AVERROR_INVALIDDATA; } /* get output buffer */ frame->nb_samples = num_blocks * BLOCK_SAMPLES; if ((ret = ff_get_buffer(avctx, frame, 0)) < 0) return ret; samples = (int16_t **)frame->extended_data; samples_offset = 0; while (num_blocks--) { for (ch = 0; ch < c->channels; ch++) { if (buf_end - buf < BLOCK_SIZE || adx_decode(c, samples[ch], samples_offset, buf, ch)) { c->eof = 1; buf = avpkt->data + avpkt->size; break; } buf_size -= BLOCK_SIZE; buf += BLOCK_SIZE; } if (!c->eof) samples_offset += BLOCK_SAMPLES; } frame->nb_samples = samples_offset; *got_frame_ptr = 1; return buf - avpkt->data; }