diff --git a/doc/examples/decode_audio.c b/doc/examples/decode_audio.c index 9cad373047..8ad9f06fa2 100644 --- a/doc/examples/decode_audio.c +++ b/doc/examples/decode_audio.c @@ -39,14 +39,46 @@ #define AUDIO_INBUF_SIZE 20480 #define AUDIO_REFILL_THRESH 4096 +static void decode(AVCodecContext *dec_ctx, AVPacket *pkt, AVFrame *frame, + FILE *outfile) +{ + int len, got_frame; + + while (pkt->size > 0) { + len = avcodec_decode_audio4(dec_ctx, frame, &got_frame, pkt); + if (len < 0) { + fprintf(stderr, "Error while decoding\n"); + exit(1); + } + if (got_frame) { + int i, ch; + /* if a frame has been decoded, output it */ + int data_size = av_get_bytes_per_sample(dec_ctx->sample_fmt); + if (data_size < 0) { + /* This should not occur, checking just for paranoia */ + fprintf(stderr, "Failed to calculate data size\n"); + exit(1); + } + for (i = 0; i < frame->nb_samples; i++) + for (ch = 0; ch < dec_ctx->channels; ch++) + fwrite(frame->data[ch] + data_size*i, 1, data_size, outfile); + } + pkt->size -= len; + pkt->data += len; + } +} + int main(int argc, char **argv) { const char *outfilename, *filename; const AVCodec *codec; AVCodecContext *c= NULL; - int len; + AVCodecParserContext *parser = NULL; + int len, ret; FILE *f, *outfile; uint8_t inbuf[AUDIO_INBUF_SIZE + AV_INPUT_BUFFER_PADDING_SIZE]; + uint8_t *data; + size_t data_size; AVPacket avpkt; AVFrame *decoded_frame = NULL; @@ -69,6 +101,12 @@ int main(int argc, char **argv) exit(1); } + parser = av_parser_init(codec->id); + if (!parser) { + fprintf(stderr, "Parser not found\n"); + exit(1); + } + c = avcodec_alloc_context3(codec); if (!c) { fprintf(stderr, "Could not allocate audio codec context\n"); @@ -93,12 +131,10 @@ int main(int argc, char **argv) } /* decode until eof */ - avpkt.data = inbuf; - avpkt.size = fread(inbuf, 1, AUDIO_INBUF_SIZE, f); - - while (avpkt.size > 0) { - int got_frame = 0; + data = inbuf; + data_size = fread(inbuf, 1, AUDIO_INBUF_SIZE, f); + while (data_size > 0) { if (!decoded_frame) { if (!(decoded_frame = av_frame_alloc())) { fprintf(stderr, "Could not allocate audio frame\n"); @@ -106,39 +142,26 @@ int main(int argc, char **argv) } } - len = avcodec_decode_audio4(c, decoded_frame, &got_frame, &avpkt); - if (len < 0) { - fprintf(stderr, "Error while decoding\n"); + ret = av_parser_parse2(parser, c, &avpkt.data, &avpkt.size, + data, data_size, + AV_NOPTS_VALUE, AV_NOPTS_VALUE, 0); + if (ret < 0) { + fprintf(stderr, "Error while parsing\n"); exit(1); } - if (got_frame) { - int i, ch; - /* if a frame has been decoded, output it */ - int data_size = av_get_bytes_per_sample(c->sample_fmt); - if (data_size < 0) { - /* This should not occur, checking just for paranoia */ - fprintf(stderr, "Failed to calculate data size\n"); - exit(1); - } - for (i=0; inb_samples; i++) - for (ch=0; chchannels; ch++) - fwrite(decoded_frame->data[ch] + data_size*i, 1, data_size, outfile); - } - avpkt.size -= len; - avpkt.data += len; - avpkt.dts = - avpkt.pts = AV_NOPTS_VALUE; - if (avpkt.size < AUDIO_REFILL_THRESH) { - /* Refill the input buffer, to avoid trying to decode - * incomplete frames. Instead of this, one could also use - * a parser, or use a proper container format through - * libavformat. */ - memmove(inbuf, avpkt.data, avpkt.size); - avpkt.data = inbuf; - len = fread(avpkt.data + avpkt.size, 1, - AUDIO_INBUF_SIZE - avpkt.size, f); + data += ret; + data_size -= ret; + + if (avpkt.size) + decode(c, &avpkt, decoded_frame, outfile); + + if (data_size < AUDIO_REFILL_THRESH) { + memmove(inbuf, data, data_size); + data = inbuf; + len = fread(data + data_size, 1, + AUDIO_INBUF_SIZE - data_size, f); if (len > 0) - avpkt.size += len; + data_size += len; } } @@ -146,6 +169,7 @@ int main(int argc, char **argv) fclose(f); avcodec_free_context(&c); + av_parser_close(parser); av_frame_free(&decoded_frame); return 0;