diff options
-rw-r--r-- | examples/alffmpeg.c | 83 | ||||
-rw-r--r-- | examples/alffmpeg.h | 2 |
2 files changed, 46 insertions, 39 deletions
diff --git a/examples/alffmpeg.c b/examples/alffmpeg.c index 786d78c3..16f73866 100644 --- a/examples/alffmpeg.c +++ b/examples/alffmpeg.c @@ -138,8 +138,10 @@ struct MyStream { struct PacketList *Packets; - char *DecodedData; - size_t DecodedDataSize; + AVFrame *Frame; + + const uint8_t *FrameData; + size_t FrameDataSize; FilePtr parent; }; @@ -251,6 +253,21 @@ FilePtr openAVCustom(const char *name, void *user_data, } +void clearAVAudioData(StreamPtr stream) +{ + while(stream->Packets) + { + struct PacketList *self; + + self = stream->Packets; + stream->Packets = self->next; + + av_free_packet(&self->pkt); + av_free(self); + } +} + + void closeAVFile(FilePtr file) { size_t i; @@ -273,7 +290,7 @@ void closeAVFile(FilePtr file) } avcodec_close(stream->CodecCtx); - av_free(stream->DecodedData); + av_free(stream->Frame); free(stream); } free(file->Streams); @@ -341,13 +358,15 @@ StreamPtr getAVAudioStream(FilePtr file, int streamnum) /* Allocate space for the decoded data to be stored in before it * gets passed to the app */ - stream->DecodedData = (char*)av_malloc(AVCODEC_MAX_AUDIO_FRAME_SIZE); - if(!stream->DecodedData) + stream->Frame = avcodec_alloc_frame(); + if(!stream->Frame) { avcodec_close(stream->CodecCtx); free(stream); return NULL; } + stream->FrameData = NULL; + stream->FrameDataSize = 0; /* Append the new stream object to the stream list. The original * pointer will remain valid if realloc fails, so we need to use @@ -357,7 +376,7 @@ StreamPtr getAVAudioStream(FilePtr file, int streamnum) if(!temp) { avcodec_close(stream->CodecCtx); - av_free(stream->DecodedData); + av_free(stream->Frame); free(stream); return NULL; } @@ -481,9 +500,9 @@ next_packet: return 0; } -void *getAVAudioData(StreamPtr stream, size_t *length) +uint8_t *getAVAudioData(StreamPtr stream, size_t *length) { - int size; + int got_frame; int len; if(length) *length = 0; @@ -491,25 +510,18 @@ void *getAVAudioData(StreamPtr stream, size_t *length) if(!stream || stream->CodecCtx->codec_type != AVMEDIA_TYPE_AUDIO) return NULL; - stream->DecodedDataSize = 0; - next_packet: if(!stream->Packets && !getNextPacket(stream->parent, stream->StreamIdx)) return NULL; /* Decode some data, and check for errors */ - size = AVCODEC_MAX_AUDIO_FRAME_SIZE; - while((len=avcodec_decode_audio3(stream->CodecCtx, - (int16_t*)stream->DecodedData, &size, - &stream->Packets->pkt)) == 0) + avcodec_get_frame_defaults(stream->Frame); + while((len=avcodec_decode_audio4(stream->CodecCtx, stream->Frame, + &got_frame, &stream->Packets->pkt)) < 0) { struct PacketList *self; - if(size > 0) - break; - - /* Packet went unread and no data was given? Drop it and try the next, - * I guess... */ + /* Error? Drop it and try the next, I guess... */ self = stream->Packets; stream->Packets = self->next; @@ -518,13 +530,8 @@ next_packet: if(!stream->Packets) goto next_packet; - - size = AVCODEC_MAX_AUDIO_FRAME_SIZE; } - if(len < 0) - return NULL; - if(len < stream->Packets->pkt.size) { /* Move the unread data to the front and clear the end bits */ @@ -546,14 +553,15 @@ next_packet: av_free(self); } - if(size == 0) + if(!got_frame || stream->Frame->nb_samples == 0) goto next_packet; /* Set the output buffer size */ - stream->DecodedDataSize = size; - if(length) *length = stream->DecodedDataSize; + *length = av_samples_get_buffer_size(NULL, stream->CodecCtx->channels, + stream->Frame->nb_samples, + stream->CodecCtx->sample_fmt, 1); - return stream->DecodedData; + return stream->Frame->data[0]; } size_t readAVAudioData(StreamPtr stream, void *data, size_t length) @@ -566,34 +574,33 @@ size_t readAVAudioData(StreamPtr stream, void *data, size_t length) while(dec < length) { /* If there's no decoded data, find some */ - if(stream->DecodedDataSize == 0) + if(stream->FrameDataSize == 0) { - if(getAVAudioData(stream, NULL) == NULL) + stream->FrameData = getAVAudioData(stream, &stream->FrameDataSize); + if(!stream->FrameData) break; } - if(stream->DecodedDataSize > 0) + if(stream->FrameDataSize > 0) { /* Get the amount of bytes remaining to be written, and clamp to * the amount of decoded data we have */ size_t rem = length-dec; - if(rem > stream->DecodedDataSize) - rem = stream->DecodedDataSize; + if(rem > stream->FrameDataSize) + rem = stream->FrameDataSize; /* Copy the data to the app's buffer and increment */ if(data != NULL) { - memcpy(data, stream->DecodedData, rem); + memcpy(data, stream->FrameData, rem); data = (char*)data + rem; } dec += rem; /* If there's any decoded data left, move it to the front of the * buffer for next time */ - if(rem < stream->DecodedDataSize) - memmove(stream->DecodedData, &stream->DecodedData[rem], - stream->DecodedDataSize - rem); - stream->DecodedDataSize -= rem; + stream->FrameData += rem; + stream->FrameDataSize -= rem; } } diff --git a/examples/alffmpeg.h b/examples/alffmpeg.h index 7fa88e65..27e49ab4 100644 --- a/examples/alffmpeg.h +++ b/examples/alffmpeg.h @@ -44,7 +44,7 @@ int getAVAudioInfo(StreamPtr stream, ALuint *rate, ALenum *channels, ALenum *typ * from a previously-decoded packet is dropped. The size (in bytes) of the * returned data buffer is stored in 'length', and the returned pointer is only * valid until the next call to getAVAudioData or readAVAudioData. */ -void *getAVAudioData(StreamPtr stream, size_t *length); +uint8_t *getAVAudioData(StreamPtr stream, size_t *length); /* The "meat" function. Decodes audio and writes, at most, length bytes into * the provided data buffer. Will only return less for end-of-stream or error |