Analysis
Overview
The ability for playing audio streams from media files in Sophie2 is significant because is one of the main features of the product. Till now, it was realized with JMF, which is pretty much outdated and does not support many of the today's audio codecs and formats. So, in order to provide ability to decode/encode most of the popular codecs used today, we can use http://ffmpeg.org/ - A C++ library which is an ongoing, live project. It support most of the known codecs. The wrapper from the second revision of this task should be updated.
Working branch for this task: http://www.sophie2.org/trac/browser/branches/private/nenko/experimental
Task requirements
- Playing back audio from a file ability should be provided.
- Protocol should be defined for communication between the native program (like FFmpeg) wrappers and Sophie2.
Task result
- Source code.
- Simple audio demo.
Implementation idea
- Update JavaBridge and NativeBridge defined in GROUP_WRAPPERS_R0
- Update and extend with classes needed in MEDIA_ENGINE_IMPL_MAIN_R2
Related
How to demo
- Start the Demo's executable.
Design
So, in order to make audio working, we'll make Decoder C++ class which will unite functionality of video decoding that are provided in MEDIA_ENGINE_IMPL_MAIN_R2 and audio decoding from this task. Prototype of Decoder.h :
#ifndef DECODER_H_ #define DECODER_H_ class Decoder { public: Decoder(); virtual ~Decoder(); Code open(); void close(); int seek(int time); bool readFrame(); int* decodeFrame(); int getWidth() const; int getHeight() const; int getLinesize() const; int getDuration() const; bool isOpen(); bool readAudioFrame(); int* decodeAudioFrame(int*); int* saveAudioBuffer(uint8_t*, int); private: bool is_open; bool is_closed; AVFormatContext *pFormatContext; AVCodecContext *pCodecCtx, *aCodecCtx; int videoStream, audiostream; uint8_t *buffer, *audio_buf; AVFrame *pFrame, *pFrameRGB; AVCodec *pCodec, *aCodec; PixelFormat pixFMT; int* saveFrame(AVFrame *pFrame, int width, int height); AVPacket packet; int buf_size; }; #endif /* DECODER_H_ */
Most of the methods come from Player class from the second revision of the ticket ( MEDIA_ENGINE_IMPL_MAIN_R2 ), but new fields and methods will be introduced ( info regarding AVFormatContext and all other data types and methods from the FFmpeg library could be found at http://www.dranger.com/ffmpeg/data.html ):
Fields:
- int audiostream - the index in the pFormatCtx->streams that is CODEC_TYPE_AUDIO.
- AVCodecContext *aCodecCtx - a pointer to a construct which contains information audio codecs to be opened.
- AVCodec *aCodec - a pointer to a construct which contains information regarding audio codec.
- uint8_t *audio_buf - a buffer which contain the raw data of the decoded audio stream.
Methods:
- bool readAudioFrame() - reads an audio frame in packets.
- int* decodeAudioFrame(int*) - decodes the packets read.
- int* saveAudioBuffer(uint8_t*, int) - save the decoded information.
A decode method for the audio stream in this class should be provided:
prototype:
int* AudioPlayer::decodeAudioFrame(int* size) { uint8_t* audio_pkt_data = NULL; int audio_pkt_size = 0; int len1; audio_pkt_data = packet.data; audio_pkt_size = packet.size; audio_buf =(uint8_t*) av_malloc(AVCODEC_MAX_AUDIO_FRAME_SIZE * sizeof(uint8_t)); buf_size = AVCODEC_MAX_AUDIO_FRAME_SIZE; packet.data =(uint8_t*) av_malloc((audio_pkt_size + FF_INPUT_BUFFER_PADDING_SIZE)*sizeof(uint8_t)); memcpy(packet.data, audio_pkt_data, audio_pkt_size); while (audio_pkt_size > 0) { int data_size = buf_size; //fprintf(stderr,"decodeAudioFrame: Trying to decode packet!\n"); //fprintf(stderr,"decodeAudioFrame: data_size before decode: %d.\n",data_size); len1 = avcodec_decode_audio3(aCodecCtx, (int16_t *) audio_buf, &data_size, &packet); //fprintf(stderr,"decodeAudioFrame: Number of bytes decoded: %d.\n",len1); //fprintf(stderr,"decodeAudioFrame: data_size after decode: %d.\n",data_size); if (len1 < 0) { //fprintf(stderr,"decodeAudioFrame: ERROR decoding!\n"); /* if error, skip frame */ audio_pkt_size = 0; break; } //fprintf(stderr,"decodeAudioFrame: Sound probably decoded...\n"); audio_pkt_data += len1; audio_pkt_size -= len1; if (data_size <= 0) { //fprintf(stderr,"decodeAudioFrame: SHOULDN'T GET HERE!\n"); continue; }/* We have data, return it and come back for more later */ size = &data_size; //fprintf(stderr,"decodeAudioFrame: Gets before saving buffer with size: %d\n", *size); return saveAudioBuffer(audio_buf, data_size); }
Working branch for this task is: http://www.sophie2.org/trac/browser/branches/private/nenko/experimental, but probably it will be changed to http://www.sophie2.org/trac/browser/branches/second_resource_refactoring/sophie2-natives or something similar.
Implementation
(Describe and link the implementation results here (from the wiki or the repository).)
Testing
(Place the testing results here.)
Comments
(Write comments for this or later revisions here.)