diff --git a/Output/x64/acinerella.dll b/Output/x64/acinerella.dll index e851fd01..eb6998e6 100644 Binary files a/Output/x64/acinerella.dll and b/Output/x64/acinerella.dll differ diff --git a/Output/x64/avcodec-54.dll b/Output/x64/avcodec-54.dll index ca074e7c..193d96cb 100644 Binary files a/Output/x64/avcodec-54.dll and b/Output/x64/avcodec-54.dll differ diff --git a/Output/x64/avformat-54.dll b/Output/x64/avformat-54.dll index 40521b17..67041399 100644 Binary files a/Output/x64/avformat-54.dll and b/Output/x64/avformat-54.dll differ diff --git a/Output/x64/avutil-51.dll b/Output/x64/avutil-51.dll deleted file mode 100644 index 5f8cdf7d..00000000 Binary files a/Output/x64/avutil-51.dll and /dev/null differ diff --git a/Output/x64/avutil-52.dll b/Output/x64/avutil-52.dll index d1985df4..c7ca9619 100644 Binary files a/Output/x64/avutil-52.dll and b/Output/x64/avutil-52.dll differ diff --git a/Output/x64/swresample-0.dll b/Output/x64/swresample-0.dll index f1150429..9b3af43d 100644 Binary files a/Output/x64/swresample-0.dll and b/Output/x64/swresample-0.dll differ diff --git a/Output/x64/swscale-2.dll b/Output/x64/swscale-2.dll index dcc41fd3..5d6588fe 100644 Binary files a/Output/x64/swscale-2.dll and b/Output/x64/swscale-2.dll differ diff --git a/Output/x86/acinerella.dll b/Output/x86/acinerella.dll index a39e3501..f651542d 100644 Binary files a/Output/x86/acinerella.dll and b/Output/x86/acinerella.dll differ diff --git a/Output/x86/avcodec-54.dll b/Output/x86/avcodec-54.dll index 97d7f850..7b08c266 100644 Binary files a/Output/x86/avcodec-54.dll and b/Output/x86/avcodec-54.dll differ diff --git a/Output/x86/avformat-54.dll b/Output/x86/avformat-54.dll index 7328c561..9dc249e0 100644 Binary files a/Output/x86/avformat-54.dll and b/Output/x86/avformat-54.dll differ diff --git a/Output/x86/avutil-51.dll b/Output/x86/avutil-51.dll deleted file mode 100644 index 5ab61687..00000000 Binary files a/Output/x86/avutil-51.dll and /dev/null differ diff --git a/Output/x86/avutil-52.dll b/Output/x86/avutil-52.dll index af2ce47e..100dc0f5 100644 Binary files a/Output/x86/avutil-52.dll and b/Output/x86/avutil-52.dll differ diff --git a/Output/x86/swresample-0.dll b/Output/x86/swresample-0.dll index 060469a0..6a77631b 100644 Binary files a/Output/x86/swresample-0.dll and b/Output/x86/swresample-0.dll differ diff --git a/Output/x86/swscale-2.dll b/Output/x86/swscale-2.dll index afa902a0..f3b957f8 100644 Binary files a/Output/x86/swscale-2.dll and b/Output/x86/swscale-2.dll differ diff --git a/Vocaluxe/Lib/Sound/Decoder/CAudioDecoderFFmpeg.cs b/Vocaluxe/Lib/Sound/Decoder/CAudioDecoderFFmpeg.cs index ba63ece0..0a41a7e7 100644 --- a/Vocaluxe/Lib/Sound/Decoder/CAudioDecoderFFmpeg.cs +++ b/Vocaluxe/Lib/Sound/Decoder/CAudioDecoderFFmpeg.cs @@ -8,10 +8,6 @@ namespace Vocaluxe.Lib.Sound.Decoder { class CAudioDecoderFFmpeg : CAudioDecoder, IDisposable { - private TAc_read_callback _rc; - private TAc_seek_callback _sc; - private FileStream _fs; - private IntPtr _instance = IntPtr.Zero; private IntPtr _audiodecoder = IntPtr.Zero; @@ -24,11 +20,7 @@ namespace Vocaluxe.Lib.Sound.Decoder public override void Init() { - _rc = read_proc; - _sc = seek_proc; - _FileOpened = false; - _Initialized = true; } @@ -38,12 +30,19 @@ namespace Vocaluxe.Lib.Sound.Decoder return; _FileName = FileName; - _fs = new FileStream(FileName, FileMode.Open, FileAccess.Read, FileShare.Read); - _instance = CAcinerella.ac_init(); - CAcinerella.ac_open(_instance, IntPtr.Zero, null, _rc, _sc, null, IntPtr.Zero); - - _Instance = (TAc_instance)Marshal.PtrToStructure(_instance, typeof(TAc_instance)); + try + { + _instance = CAcinerella.ac_init(); + CAcinerella.ac_open2(_instance, _FileName); + _Instance = (TAc_instance)Marshal.PtrToStructure(_instance, typeof(TAc_instance)); + } + catch (Exception) + { + CLog.LogError("Error opening audio file: " + _FileName); + return; + } + if (!_Instance.opened) { @@ -52,26 +51,17 @@ namespace Vocaluxe.Lib.Sound.Decoder } int AudioStreamIndex = -1; - - TAc_stream_info Info = new TAc_stream_info(); - for (int i = 0; i < _Instance.stream_count; i++) + TAc_decoder Audiodecoder; + try { - CAcinerella.ac_get_stream_info(_instance, i, out Info); - - if (Info.stream_type == TAc_stream_type.AC_STREAM_TYPE_AUDIO) - { - try - { - _audiodecoder = CAcinerella.ac_create_decoder(_instance, i); - } - catch (Exception) - { - return; - } - - AudioStreamIndex = i; - break; - } + _audiodecoder = CAcinerella.ac_create_audio_decoder(_instance); + Audiodecoder = (TAc_decoder)Marshal.PtrToStructure(_audiodecoder, typeof(TAc_decoder)); + AudioStreamIndex = Audiodecoder.stream_index; + } + catch (Exception) + { + CLog.LogError("Error opening audio file (can't find decoder): " + _FileName); + return; } if (AudioStreamIndex < 0) @@ -80,8 +70,6 @@ namespace Vocaluxe.Lib.Sound.Decoder return; } - TAc_decoder Audiodecoder = (TAc_decoder)Marshal.PtrToStructure(_audiodecoder, typeof(TAc_decoder)); - _FormatInfo = new FormatInfo(); _FormatInfo.SamplesPerSecond = Audiodecoder.stream_info.audio_info.samples_per_second; @@ -198,28 +186,8 @@ namespace Vocaluxe.Lib.Sound.Decoder TimeStamp = 0f; } - #region Callbacks - private Int32 read_proc(IntPtr sender, IntPtr buf, Int32 size) - { - Int32 r = 0; - - byte[] bb = new byte[size]; - r = _fs.Read(bb, 0, size); - Marshal.Copy(bb, 0, buf, size); - - return r; - } - - private Int64 seek_proc(IntPtr sender, Int64 pos, Int32 whence) - { - return _fs.Seek(pos, (SeekOrigin)whence); - } - #endregion Callbacks - public void Dispose() { - _fs.Dispose(); - _fs = null; } } } \ No newline at end of file diff --git a/Vocaluxe/Lib/Video/Acinerella/CAcinerella.cs b/Vocaluxe/Lib/Video/Acinerella/CAcinerella.cs index 0080e70a..47576c64 100644 --- a/Vocaluxe/Lib/Video/Acinerella/CAcinerella.cs +++ b/Vocaluxe/Lib/Video/Acinerella/CAcinerella.cs @@ -220,6 +220,7 @@ namespace Vocaluxe.Lib.Video.Acinerella close_proc: TAc_openclose_callback; proberesult: PAc_proberesult): integer; cdecl; external ac_dll; */ + /* [DllImport(AcDll, EntryPoint = "ac_open", ExactSpelling = false, CallingConvention = CallingConvention.Cdecl, CharSet = CharSet.Auto)] private static extern Int32 _ac_open( IntPtr PAc_instance, @@ -245,6 +246,23 @@ namespace Vocaluxe.Lib.Video.Acinerella { return _ac_open(PAc_instance, sender, open_proc, read_proc, seek_proc, close_proc, proberesult); } + }*/ + + [DllImport(AcDll, EntryPoint = "ac_open", ExactSpelling = false, CallingConvention = CallingConvention.Cdecl, CharSet = CharSet.Ansi)] + private static extern Int32 _ac_open2( + IntPtr PAc_instance, + string filename + ); + + public static Int32 ac_open2( + IntPtr PAc_instance, + string filename + ) + { + lock (_lock) + { + return _ac_open2(PAc_instance, filename); + } } // Closes an opened media file. @@ -296,17 +314,26 @@ namespace Vocaluxe.Lib.Video.Acinerella [DllImport(AcDll, EntryPoint = "ac_free_package", ExactSpelling = false, CallingConvention = CallingConvention.Cdecl, CharSet = CharSet.Auto)] public static extern void ac_free_package(IntPtr PAc_package); - // Creates an decoder for the specified stream number. Returns NIL if no decoder - // could be found. - //function ac_create_decoder(pacInstance: PAc_instance; nb: integer): PAc_decoder; cdecl; external ac_dll; - [DllImport(AcDll, EntryPoint = "ac_create_decoder", ExactSpelling = false, CallingConvention = CallingConvention.Cdecl, CharSet = CharSet.Auto)] - private static extern IntPtr _ac_create_decoder(IntPtr PAc_instance, Int32 nb); - public static IntPtr ac_create_decoder(IntPtr PAc_instance, Int32 nb) + [DllImport(AcDll, EntryPoint = "ac_create_video_decoder", ExactSpelling = false, CallingConvention = CallingConvention.Cdecl, CharSet = CharSet.Auto)] + private static extern IntPtr _ac_create_video_decoder(IntPtr PAc_instance); + + public static IntPtr ac_create_video_decoder(IntPtr PAc_instance) { lock (_lock) { - return _ac_create_decoder(PAc_instance, nb); + return _ac_create_video_decoder(PAc_instance); + } + } + + [DllImport(AcDll, EntryPoint = "ac_create_audio_decoder", ExactSpelling = false, CallingConvention = CallingConvention.Cdecl, CharSet = CharSet.Auto)] + private static extern IntPtr _ac_create_audio_decoder(IntPtr PAc_instance); + + public static IntPtr ac_create_audio_decoder(IntPtr PAc_instance) + { + lock (_lock) + { + return _ac_create_audio_decoder(PAc_instance); } } diff --git a/Vocaluxe/Lib/Video/Acinerella/acinerella.c b/Vocaluxe/Lib/Video/Acinerella/acinerella.c index 3550bc07..ba9a9a6e 100644 --- a/Vocaluxe/Lib/Video/Acinerella/acinerella.c +++ b/Vocaluxe/Lib/Video/Acinerella/acinerella.c @@ -23,6 +23,7 @@ #include #include #include +#include #include #define AUDIO_BUFFER_BASE_SIZE AVCODEC_MAX_AUDIO_FRAME_SIZE @@ -38,15 +39,7 @@ struct _ac_data { ac_instance instance; - AVFormatContext *pFormatCtx; - - void *sender; - ac_openclose_callback open_proc; - ac_read_callback read_proc; - ac_seek_callback seek_proc; - ac_openclose_callback close_proc; - void* buffer; }; @@ -55,8 +48,6 @@ typedef ac_data* lp_ac_data; struct _ac_decoder_data { ac_decoder decoder; - int sought; - double last_timecode; }; typedef struct _ac_decoder_data ac_decoder_data; @@ -64,8 +55,6 @@ typedef ac_decoder_data* lp_ac_decoder_data; struct _ac_video_decoder { ac_decoder decoder; - int sought; - double last_timecode; AVCodec *pCodec; AVCodecContext *pCodecCtx; AVFrame *pFrame; @@ -78,10 +67,6 @@ typedef ac_video_decoder* lp_ac_video_decoder; struct _ac_audio_decoder { ac_decoder decoder; - int sought; - double last_timecode; - uint8_t *tmp_data; - int tmp_data_length; int max_buffer_size; AVCodec *pCodec; AVCodecContext *pCodecCtx; @@ -145,225 +130,41 @@ void CALL_CONVT ac_free(lp_ac_instance pacInstance) { } } -static int io_read(void *opaque, uint8_t *buf, int buf_size) -{ - if (((lp_ac_data)(opaque))->read_proc != NULL) { - return ((lp_ac_data)(opaque))->read_proc( - ((lp_ac_data)(opaque))->sender, buf, buf_size); - } - - return -1; -} - -static int64_t io_seek(void *opaque, int64_t pos, int whence) -{ - if (((lp_ac_data)(opaque))->seek_proc != NULL) { - if ((whence >= 0) && (whence <= 2)) { - return ((lp_ac_data)(opaque))->seek_proc( - ((lp_ac_data)(opaque))->sender, pos, whence); - } - } - - return -1; -} - -lp_ac_proberesult CALL_CONVT ac_probe_input_buffer( - void* buf, - int bufsize, - char* filename, - int* score_max) -{ - AVProbeData pd; - AVInputFormat *fmt = NULL; - - //Initialize FFMpeg libraries - ac_init_ffmpeg(); - - //Set the filename - pd.filename = ""; - if (filename) { - pd.filename = filename; - } - - //The given buffer has to be copied to a new one, which is aligned and padded - void* aligned_buf = av_malloc(bufsize + AVPROBE_PADDING_SIZE); - - memset(aligned_buf, 0, bufsize + AVPROBE_PADDING_SIZE); - memcpy(aligned_buf, buf, bufsize); - - //Set the probe data buffer - pd.buf = aligned_buf; - pd.buf_size = bufsize; - - //Test it - fmt = (AVInputFormat*)av_probe_input_format2(&pd, 1, score_max); - - //Free the temporary buffer - av_free(aligned_buf); - - return (lp_ac_proberesult)fmt; -} - -#define PROBE_BUF_MIN 2048 -#define PROBE_BUF_MAX (1<<20) - - -AVInputFormat* ac_probe_input_stream( - void* sender, - ac_read_callback read_proc, - char* filename, - void* *buf, - int* buf_read) -{ - //Initialize the result variables - AVInputFormat* fmt = NULL; - *buf_read = 0; - *buf = NULL; - int last_iteration = 0; - int probe_size = 0; - - for (probe_size = PROBE_BUF_MIN; - (probe_size <= PROBE_BUF_MAX) && !fmt && !last_iteration; - probe_size<<=1) { - int score = AVPROBE_SCORE_MAX / 4; - - //Allocate some memory for the current probe buffer - void* tmp_buf = av_malloc(probe_size); //Unaligned memory would also be ok here - memset(tmp_buf, 0, probe_size); - - //Copy the old data to the new buffer - if (*buf) { - memcpy(tmp_buf, *buf, *buf_read); - //Free the old data memory - av_free(*buf); - } - - //Read the new data - void* write_ptr = tmp_buf + *buf_read; - int read_size = probe_size - *buf_read; - int size; - if (size = read_proc(sender, write_ptr, read_size) < read_size) { - last_iteration = 1; - probe_size = *buf_read + size; - } - - //Probe it - fmt = (AVInputFormat*)ac_probe_input_buffer(tmp_buf, probe_size, filename, &score); - - //Set the new buffer - *buf = tmp_buf; - *buf_read = probe_size; - } - - //Return the result - return fmt; -} - -int CALL_CONVT ac_open( - lp_ac_instance pacInstance, - void *sender, - ac_openclose_callback open_proc, - ac_read_callback read_proc, - ac_seek_callback seek_proc, - ac_openclose_callback close_proc, - lp_ac_proberesult proberesult) +int CALL_CONVT ac_open(lp_ac_instance pacInstance, const char* filename) { - pacInstance->opened = 0; - - //Store the given parameters in the ac Instance - ((lp_ac_data)pacInstance)->sender = sender; - ((lp_ac_data)pacInstance)->open_proc = open_proc; - ((lp_ac_data)pacInstance)->read_proc = read_proc; - ((lp_ac_data)pacInstance)->seek_proc = seek_proc; - ((lp_ac_data)pacInstance)->close_proc = close_proc; + pacInstance->opened = 0; - //Call the file open proc - if (open_proc != NULL) { - open_proc(sender); - } - - AVInputFormat* fmt = NULL; - int probe_size = 0; - - //Probe the input format, if no probe result is specified - if(proberesult == NULL) - { - fmt = ac_probe_input_stream(sender, read_proc, "", - (void*)&((lp_ac_data)pacInstance)->buffer, &probe_size); - } - else - { - fmt = (AVInputFormat*)proberesult; - } - if (!fmt) return -1; + /* open input file, and allocate format context */ + int ret = 0; + if ((ret = avformat_open_input(&((lp_ac_data)pacInstance)->pFormatCtx, filename, NULL, NULL)) < 0) + { + return ret; + } - ((lp_ac_data)pacInstance)->pFormatCtx = avformat_alloc_context(); - - if (!seek_proc) { - ((lp_ac_data)pacInstance)->pFormatCtx->pb = avio_alloc_context( - ((lp_ac_data)pacInstance)->buffer, - probe_size, 0, pacInstance, io_read, 0, NULL); - - //Feed the probed bytes into the IO-Context - ((lp_ac_data)pacInstance)->pFormatCtx->pb->buf_end = - ((lp_ac_data)pacInstance)->buffer + probe_size; - ((lp_ac_data)pacInstance)->pFormatCtx->pb->pos = probe_size; - } else { - //If the stream is seekable, seek back to the beginning of the stream and - //let FFMpeg start from the beginning - if (((lp_ac_data)pacInstance)->buffer) - av_free(((lp_ac_data)pacInstance)->buffer); - - int64_t pos = seek_proc(sender, 0, SEEK_SET); - - //Reserve AC_BUFSIZE Bytes of memory - ((lp_ac_data)pacInstance)->buffer = av_malloc(AC_BUFSIZE); - - ((lp_ac_data)pacInstance)->pFormatCtx->pb = avio_alloc_context( - ((lp_ac_data)pacInstance)->buffer, - AC_BUFSIZE, 0, pacInstance, io_read, 0, io_seek); - } - - //Open the given input stream (the io structure) with the given format of the stream - //(fmt) and write the pointer to the new format context to the pFormatCtx variable - if (avformat_open_input( - &(((lp_ac_data)pacInstance)->pFormatCtx), - "", - fmt, - NULL) < 0) - { - return -1; - } + /* retrieve stream information */ + if ((ret = avformat_find_stream_info(((lp_ac_data)pacInstance)->pFormatCtx, NULL)) < 0) + { + return ret; + } + else + pacInstance->info.duration = ((lp_ac_data)pacInstance)->pFormatCtx->duration * 1000 / AV_TIME_BASE; - //Retrieve stream information - AVFormatContext *ctx = ((lp_ac_data)pacInstance)->pFormatCtx; - if(avformat_find_stream_info(ctx, NULL) >= 0) { - pacInstance->info.duration = ctx->duration * 1000 / AV_TIME_BASE; - } else { - return -1; - } + //Set some information in the instance variable + pacInstance->stream_count = ((lp_ac_data)pacInstance)->pFormatCtx->nb_streams; + pacInstance->opened = pacInstance->stream_count > 0; - //Set some information in the instance variable - pacInstance->stream_count = ((lp_ac_data)pacInstance)->pFormatCtx->nb_streams; - pacInstance->opened = pacInstance->stream_count > 0; - - return 0; + return 0; } void CALL_CONVT ac_close(lp_ac_instance pacInstance) { if (pacInstance->opened) { - //Close the opened file - if (((lp_ac_data)(pacInstance))->close_proc != NULL) { - ((lp_ac_data)(pacInstance))->close_proc(((lp_ac_data)(pacInstance))->sender); - } - + //Close the opened file avformat_close_input(&(((lp_ac_data)(pacInstance))->pFormatCtx)); pacInstance->opened = 0; //If the seek proc has not been specified, the input buffer is not automatically //freed, as ffmpeg didn't get the original pointer to the buffer - if (!((lp_ac_data)(pacInstance))->seek_proc && - ((lp_ac_data)(pacInstance))->buffer) { + if (((lp_ac_data)(pacInstance))->buffer) { av_free(((lp_ac_data)(pacInstance))->buffer); } @@ -404,42 +205,13 @@ void CALL_CONVT ac_get_stream_info(lp_ac_instance pacInstance, int nb, lp_ac_str info->stream_type = AC_STREAM_TYPE_AUDIO; //Store more information about the video stream - info->audio_info.samples_per_second = + info->audio_info.samples_per_second = ((lp_ac_data)pacInstance)->pFormatCtx->streams[nb]->codec->sample_rate; - info->audio_info.channel_count = - ((lp_ac_data)pacInstance)->pFormatCtx->streams[nb]->codec->channels; - - // Set bit depth - switch (((lp_ac_data)pacInstance)->pFormatCtx->streams[nb]->codec->sample_fmt) { - //8-Bit - case AV_SAMPLE_FMT_U8: - info->audio_info.bit_depth = - 8; - break; - - //16-Bit - case AV_SAMPLE_FMT_S16: - info->audio_info.bit_depth = - 16; - break; - -/* //24-Bit (removed in the newest ffmpeg version) - case SAMPLE_FMT_S24: - info->additional_info.audio_info.bit_depth = - 24; - break; */ - - //32-Bit - case AV_SAMPLE_FMT_S32: case AV_SAMPLE_FMT_FLT: - info->audio_info.bit_depth = - 32; - break; - - //Unknown format, return zero - default: - info->audio_info.bit_depth = - 0; - } + info->audio_info.channel_count = 2; + //((lp_ac_data)pacInstance)->pFormatCtx->streams[nb]->codec->channels; + + // Set bit depth (its always 16Bit because of the conversion! + info->audio_info.bit_depth = 16; break; default: @@ -474,7 +246,8 @@ lp_ac_package CALL_CONVT ac_read_package(lp_ac_instance pacInstance) { } //Frees the currently loaded package -void CALL_CONVT ac_free_package(lp_ac_package pPackage) { +void CALL_CONVT ac_free_package(lp_ac_package pPackage) +{ //Free the packet if (pPackage != NULL) { AVPacket* pkt = &((lp_ac_package_data)pPackage)->ffpackage; @@ -500,112 +273,98 @@ enum PixelFormat convert_pix_format(ac_output_format fmt) { return PIX_FMT_RGB32; } -//Init a video decoder -void* ac_create_video_decoder(lp_ac_instance pacInstance, lp_ac_stream_info info, int nb) { - //Allocate memory for a new decoder instance - lp_ac_video_decoder pDecoder; - pDecoder = (lp_ac_video_decoder)(av_malloc(sizeof(ac_video_decoder))); - memset(pDecoder, 0, sizeof(ac_video_decoder)); - - //Set a few properties - pDecoder->decoder.pacInstance = pacInstance; - pDecoder->decoder.type = AC_DECODER_TYPE_VIDEO; - pDecoder->decoder.stream_index = nb; - pDecoder->pCodecCtx = ((lp_ac_data)(pacInstance))->pFormatCtx->streams[nb]->codec; - pDecoder->decoder.stream_info = *info; - - //Find correspondenting codec - if (!(pDecoder->pCodec = avcodec_find_decoder(pDecoder->pCodecCtx->codec_id))) { - return NULL; //Codec could not have been found - } +lp_ac_decoder CALL_CONVT ac_create_video_decoder(lp_ac_instance pacInstance) { + //Allocate memory for a new decoder instance + lp_ac_video_decoder pDecoder; + pDecoder = (lp_ac_video_decoder)(av_malloc(sizeof(ac_video_decoder))); + memset(pDecoder, 0, sizeof(ac_video_decoder)); - pDecoder->pCodecCtx->thread_count = 1; //this is for HT CPUs, it should be - // tested if there is a better solution + int nb = av_find_best_stream(((lp_ac_data)pacInstance)->pFormatCtx, AVMEDIA_TYPE_VIDEO, -1, -1, NULL, 0); + if (nb < 0) + return NULL; + + ac_stream_info info; + ac_get_stream_info(pacInstance, nb, &info); + + //Set a few properties + pDecoder->decoder.pacInstance = pacInstance; + pDecoder->decoder.type = AC_DECODER_TYPE_VIDEO; + pDecoder->decoder.stream_index = nb; + pDecoder->decoder.video_clock = 0; + pDecoder->pCodecCtx = ((lp_ac_data)pacInstance)->pFormatCtx->streams[nb]->codec; + pDecoder->decoder.stream_info = info; + pDecoder->pCodecCtx->thread_count = 1; //this is for HT CPUs, it should be + // tested if there is a better solution + + //Find correspondenting codec + if (!(pDecoder->pCodec = avcodec_find_decoder(pDecoder->pCodecCtx->codec_id))) + return NULL; //Codec could not have been found - //Open codec - if (avcodec_open2(pDecoder->pCodecCtx, pDecoder->pCodec, NULL) < 0) { - return NULL; //Codec could not have been opened - } - - //Reserve frame variables - pDecoder->pFrame = avcodec_alloc_frame(); - pDecoder->pFrameRGB = avcodec_alloc_frame(); - - pDecoder->pSwsCtx = NULL; - - //Reserve buffer memory - pDecoder->decoder.buffer_size = avpicture_get_size(convert_pix_format(pacInstance->output_format), - pDecoder->pCodecCtx->width, pDecoder->pCodecCtx->height); - pDecoder->decoder.pBuffer = (uint8_t*)av_malloc(pDecoder->decoder.buffer_size); + //Open codec + if (avcodec_open2(pDecoder->pCodecCtx, pDecoder->pCodec, NULL) < 0) + return NULL; //Codec could not have been opened - //Link decoder to buffer - avpicture_fill( - (AVPicture*)(pDecoder->pFrameRGB), - pDecoder->decoder.pBuffer, convert_pix_format(pacInstance->output_format), - pDecoder->pCodecCtx->width, pDecoder->pCodecCtx->height); - - return (void*)pDecoder; + //Reserve frame variables + pDecoder->pFrame = avcodec_alloc_frame(); + pDecoder->pFrameRGB = avcodec_alloc_frame(); + + pDecoder->pSwsCtx = NULL; + + //Reserve buffer memory + pDecoder->decoder.buffer_size = avpicture_get_size(convert_pix_format(pacInstance->output_format), + pDecoder->pCodecCtx->width, pDecoder->pCodecCtx->height); + pDecoder->decoder.pBuffer = (uint8_t*)av_malloc(pDecoder->decoder.buffer_size); + + //Link decoder to buffer + avpicture_fill( + (AVPicture*)(pDecoder->pFrameRGB), + pDecoder->decoder.pBuffer, convert_pix_format(pacInstance->output_format), + pDecoder->pCodecCtx->width, pDecoder->pCodecCtx->height); + + return (void*)pDecoder; } -//Init a audio decoder -void* ac_create_audio_decoder(lp_ac_instance pacInstance, lp_ac_stream_info info, int nb) { - //Allocate memory for a new decoder instance - lp_ac_audio_decoder pDecoder; - pDecoder = (lp_ac_audio_decoder)(av_malloc(sizeof(ac_audio_decoder))); - memset(pDecoder, 0, sizeof(ac_audio_decoder)); - - //Set a few properties - pDecoder->decoder.pacInstance = pacInstance; - pDecoder->decoder.type = AC_DECODER_TYPE_AUDIO; - pDecoder->decoder.stream_index = nb; - pDecoder->decoder.stream_info = *info; - pDecoder->decoder.video_clock = 0; - - //Temporary store codec context pointer - AVCodecContext *pCodecCtx = ((lp_ac_data)(pacInstance))->pFormatCtx->streams[nb]->codec; - pDecoder->pCodecCtx = pCodecCtx; - - //Find correspondenting codec - if (!(pDecoder->pCodec = avcodec_find_decoder(pCodecCtx->codec_id))) { - return NULL; - } - - //Open codec - if (avcodec_open2(pCodecCtx, pDecoder->pCodec, NULL) < 0) { - return NULL; - } +lp_ac_decoder CALL_CONVT ac_create_audio_decoder(lp_ac_instance pacInstance) +{ + //Allocate memory for a new decoder instance + lp_ac_audio_decoder pDecoder; + pDecoder = (lp_ac_audio_decoder)(av_malloc(sizeof(ac_audio_decoder))); + memset(pDecoder, 0, sizeof(ac_audio_decoder)); - //Initialize the buffers - pDecoder->decoder.pBuffer = NULL; //av_malloc(AUDIO_BUFFER_BASE_SIZE); - pDecoder->decoder.buffer_size = 0; - pDecoder->max_buffer_size = 0; + int nb = av_find_best_stream(((lp_ac_data)pacInstance)->pFormatCtx, AVMEDIA_TYPE_AUDIO, -1, -1, NULL, 0); + if (nb < 0) + return NULL; + + ac_stream_info info; + ac_get_stream_info(pacInstance, nb, &info); - pDecoder->tmp_data = NULL; - pDecoder->tmp_data_length = 0; - - return (void*)pDecoder; -} + //Set a few properties + pDecoder->decoder.pacInstance = pacInstance; + pDecoder->decoder.type = AC_DECODER_TYPE_AUDIO; + pDecoder->decoder.stream_index = nb; + pDecoder->decoder.stream_info = info; + pDecoder->decoder.video_clock = 0; + + //Temporary store codec context pointer + AVCodecContext *pCodecCtx = ((lp_ac_data)pacInstance)->pFormatCtx->streams[nb]->codec; + pDecoder->pCodecCtx = pCodecCtx; + //pDecoder->pCodecCtx->thread_count = 1; //this is for HT CPUs, it should be + // tested if there is a better solution + + //Find correspondenting codec + if (!(pDecoder->pCodec = avcodec_find_decoder(pCodecCtx->codec_id))) + return NULL; -lp_ac_decoder CALL_CONVT ac_create_decoder(lp_ac_instance pacInstance, int nb) { - //Get information about the chosen data stream and create an decoder that can - //handle this kind of stream. - ac_stream_info info; - ac_get_stream_info(pacInstance, nb, &info); - - lp_ac_decoder result; - - if (info.stream_type == AC_STREAM_TYPE_VIDEO) { - result = ac_create_video_decoder(pacInstance, &info, nb); - } - else if (info.stream_type == AC_STREAM_TYPE_AUDIO) { - result = ac_create_audio_decoder(pacInstance, &info, nb); - } - - ((lp_ac_decoder_data)result)->last_timecode = 0; - ((lp_ac_decoder_data)result)->sought = 1; - result->video_clock = 0; - - return result; + //Open codec + if (avcodec_open2(pCodecCtx, pDecoder->pCodec, NULL) < 0) + return NULL; + + //Initialize the buffers + pDecoder->decoder.pBuffer = av_malloc(AUDIO_BUFFER_BASE_SIZE); + pDecoder->decoder.buffer_size = 0; + pDecoder->max_buffer_size = AUDIO_BUFFER_BASE_SIZE; + + return (void*)pDecoder; } double ac_sync_video(lp_ac_package pPackage, lp_ac_decoder pDec, AVFrame *src_frame, double pts){ @@ -643,13 +402,7 @@ int ac_decode_video_package(lp_ac_package pPackage, lp_ac_video_decoder pDecoder pkt_tmp.size -= len; pkt_tmp.data += len; } - - /* - avcodec_decode_video2( - pDecoder->pCodecCtx, pDecoder->pFrame, &finished, - &(((lp_ac_package_data)pPackage)->ffpackage)); - */ - + if (finished != 0) { pDecoder->pSwsCtx = sws_getCachedContext(pDecoder->pSwsCtx, pDecoder->pCodecCtx->width, pDecoder->pCodecCtx->height, pDecoder->pCodecCtx->pix_fmt, @@ -687,6 +440,17 @@ int ac_decode_video_package(lp_ac_package pPackage, lp_ac_video_decoder pDecoder return 0; } +int alloc_samples_array_and_data(uint8_t ***data, int *linesize, int nb_channels, int nb_samples, enum AVSampleFormat sample_fmt, int align) +{ + int nb_planes = av_sample_fmt_is_planar(sample_fmt) ? nb_channels : 1; + + *data = av_malloc(sizeof(*data) * nb_planes); + if (!*data) + return AVERROR(ENOMEM); + return av_samples_alloc(*data, linesize, nb_channels, + nb_samples, sample_fmt, align); +} + int ac_decode_audio_package(lp_ac_package pPackage, lp_ac_audio_decoder pDecoder, lp_ac_decoder pDec) { double pts; //Variables describing the destination buffer @@ -694,17 +458,8 @@ int ac_decode_audio_package(lp_ac_package pPackage, lp_ac_audio_decoder pDecoder //Make a copy of the package read by avformat, so that we can move the data pointers around AVPacket pkt_tmp = ((lp_ac_package_data)pPackage)->ffpackage; - AVFrame *decoded_frame = NULL; - - if (pDecoder->tmp_data_length > 0) - { - pkt_tmp.data = av_realloc(pkt_tmp.data, pkt_tmp.size + pDecoder->tmp_data_length); - pkt_tmp.size = pkt_tmp.size + pDecoder->tmp_data_length; - memcpy(pkt_tmp.data + pDecoder->tmp_data_length, &pkt_tmp.data, pkt_tmp.size); - memcpy(&pkt_tmp.data, pDecoder->tmp_data, pDecoder->tmp_data_length); - } - + while (pkt_tmp.size > 0) { if (!decoded_frame) { @@ -718,7 +473,6 @@ int ac_decode_audio_package(lp_ac_package pPackage, lp_ac_audio_decoder pDecoder int len1 = avcodec_decode_audio4(pDecoder->pCodecCtx, decoded_frame, &got_frame, &pkt_tmp); - //If an error occured, skip the frame if (len1 < 0){ return 0; @@ -729,67 +483,105 @@ int ac_decode_audio_package(lp_ac_package pPackage, lp_ac_audio_decoder pDecoder pkt_tmp.data += len1; if (got_frame){ - - int data_size = av_samples_get_buffer_size(NULL, (pDecoder->pCodecCtx)->channels, - decoded_frame->nb_samples, - (pDecoder->pCodecCtx)->sample_fmt, 1); - - //Reserve enough memory for coping the result data - if (dest_buffer_pos + data_size > pDecoder->max_buffer_size) { - pDecoder->decoder.pBuffer = av_realloc(pDecoder->decoder.pBuffer, dest_buffer_pos + data_size); - pDecoder->max_buffer_size = dest_buffer_pos + data_size; - } - memcpy(pDecoder->decoder.pBuffer + dest_buffer_pos, decoded_frame->data[0], data_size); - - //Increment the destination buffer pointers, copy the result to the output buffer - dest_buffer_pos += data_size; - pDecoder->decoder.buffer_size += data_size; - - - pts=0; - - if(((lp_ac_package_data)pPackage)->ffpackage.dts != AV_NOPTS_VALUE){ - pts = ((lp_ac_package_data)pPackage)->ffpackage.dts * av_q2d(((lp_ac_data)pDec->pacInstance)->pFormatCtx->streams[pPackage->stream_index]->time_base); - - pDec->video_clock = pts; - } else { - pts = pDec->video_clock; - } - - double bytes_per_second = 2 * pDec->stream_info.audio_info.samples_per_second * pDec->stream_info.audio_info.channel_count; - if (bytes_per_second > 0) - pDec->video_clock += data_size / bytes_per_second; + struct SwrContext *swr_ctx; + int dst_nb_samples = 0, max_dst_nb_samples = 0, dst_linesize = 0; + uint8_t **dst_data = NULL; + int ret = 0; + int dst_sample_rate = (pDecoder->pCodecCtx)->sample_rate; - pDec->timecode = pts; + swr_ctx = swr_alloc(); - if (pkt_tmp.size > 0) - { - pDecoder->tmp_data = av_malloc(pkt_tmp.size); - memcpy(pDecoder->tmp_data, &pkt_tmp.data, pkt_tmp.size); - } else { - av_free(pDecoder->tmp_data); - pDecoder->tmp_data_length = 0; - } + /* set options */ + av_opt_set_int(swr_ctx, "in_channel_layout", (pDecoder->pCodecCtx)->channel_layout, 0); + av_opt_set_int(swr_ctx, "in_sample_rate", (pDecoder->pCodecCtx)->sample_rate, 0); + av_opt_set_sample_fmt(swr_ctx, "in_sample_fmt", (pDecoder->pCodecCtx)->sample_fmt, 0); + + av_opt_set_int(swr_ctx, "out_channel_layout", AV_CH_LAYOUT_STEREO, 0); + av_opt_set_int(swr_ctx, "out_sample_rate", dst_sample_rate, 0); + av_opt_set_sample_fmt(swr_ctx, "out_sample_fmt", AV_SAMPLE_FMT_S16, 0); + + if (swr_init(swr_ctx) < 0) + return 0; + + /* compute the number of converted samples: buffering is avoided + * ensuring that the output buffer will contain at least all the + * converted input samples */ + max_dst_nb_samples = dst_nb_samples = av_rescale_rnd( + decoded_frame->nb_samples, dst_sample_rate, (pDecoder->pCodecCtx)->sample_rate, AV_ROUND_UP); + + if (alloc_samples_array_and_data(&dst_data, &dst_linesize, 2, dst_nb_samples, AV_SAMPLE_FMT_S16, 0) < 0) + return 0; + + /* compute destination number of samples */ + dst_nb_samples = av_rescale_rnd(swr_get_delay(swr_ctx, (pDecoder->pCodecCtx)->sample_rate) + + decoded_frame->nb_samples, dst_sample_rate, (pDecoder->pCodecCtx)->sample_rate, AV_ROUND_UP); + + if (dst_nb_samples > max_dst_nb_samples) { + av_free(dst_data[0]); + ret = av_samples_alloc(dst_data, &dst_linesize, 2, + dst_nb_samples, AV_SAMPLE_FMT_S16, 1); + if (ret < 0) + return 0; + max_dst_nb_samples = dst_nb_samples; + } + + if ((ret = swr_convert(swr_ctx, dst_data, dst_nb_samples, (const uint8_t **)decoded_frame->data, decoded_frame->nb_samples)) < 0) + return 0; + + int data_size = av_samples_get_buffer_size(&dst_linesize, 2, ret, AV_SAMPLE_FMT_S16, 1); + + //Reserve enough memory for coping the result data + if (dest_buffer_pos + data_size > pDecoder->max_buffer_size) { + pDecoder->decoder.pBuffer = av_realloc(pDecoder->decoder.pBuffer, dest_buffer_pos + data_size); + pDecoder->max_buffer_size = dest_buffer_pos + data_size; + } + + memcpy(pDecoder->decoder.pBuffer + dest_buffer_pos, dst_data[0], data_size); + + //Increment the destination buffer pointers, copy the result to the output buffer + dest_buffer_pos += data_size; + pDecoder->decoder.buffer_size += data_size; + + pts=0; + + if(((lp_ac_package_data)pPackage)->ffpackage.dts != AV_NOPTS_VALUE){ + pts = ((lp_ac_package_data)pPackage)->ffpackage.dts * av_q2d(((lp_ac_data)pDec->pacInstance)->pFormatCtx->streams[pPackage->stream_index]->time_base); - return 1; + pDec->video_clock = pts; + } else { + pts = pDec->video_clock; + } + + double bytes_per_second = 4 * pDec->stream_info.audio_info.samples_per_second; + if (bytes_per_second > 0) + pDec->video_clock += data_size / bytes_per_second; + + pDec->timecode = pts; + + if (dst_data) + av_freep(&dst_data[0]); + av_freep(&dst_data); + + swr_free(&swr_ctx); + return 1; } } - av_free(pDecoder->tmp_data); - pDecoder->tmp_data_length; return 0; } -int CALL_CONVT ac_decode_package(lp_ac_package pPackage, lp_ac_decoder pDecoder) { - if (pDecoder->type == AC_DECODER_TYPE_AUDIO) { - return ac_decode_audio_package(pPackage, (lp_ac_audio_decoder)pDecoder, pDecoder); - } else if (pDecoder->type == AC_DECODER_TYPE_VIDEO) { - return ac_decode_video_package(pPackage, (lp_ac_video_decoder)pDecoder, pDecoder); - } - return 0; +int CALL_CONVT ac_decode_package(lp_ac_package pPackage, lp_ac_decoder pDecoder) +{ + if (pDecoder->type == AC_DECODER_TYPE_AUDIO) + return ac_decode_audio_package(pPackage, (lp_ac_audio_decoder)pDecoder, pDecoder); + else if (pDecoder->type == AC_DECODER_TYPE_VIDEO) + return ac_decode_video_package(pPackage, (lp_ac_video_decoder)pDecoder, pDecoder); + + return 0; } -int CALL_CONVT ac_drop_decode_package(lp_ac_package pPackage, lp_ac_decoder pDecoder) { +int CALL_CONVT ac_drop_decode_package(lp_ac_package pPackage, lp_ac_decoder pDecoder) +{ if (pDecoder->type == AC_DECODER_TYPE_VIDEO) { return ac_drop_decode_video_package(pPackage, (lp_ac_video_decoder)pDecoder, pDecoder); } @@ -818,7 +610,6 @@ int ac_drop_decode_video_package(lp_ac_package pPackage, lp_ac_video_decoder pDe if (finished) { pts=0; - //global_video_pkt_pts = ((lp_ac_package_data)pPackage)->ffpackage.pts; if(((lp_ac_package_data)pPackage)->ffpackage.dts == AV_NOPTS_VALUE && *(uint64_t*)pDecoder->pFrame->opaque != AV_NOPTS_VALUE ){ @@ -843,20 +634,17 @@ int ac_drop_decode_video_package(lp_ac_package pPackage, lp_ac_video_decoder pDe return 0; } -int CALL_CONVT ac_get_audio_frame(lp_ac_instance pacInstance, lp_ac_decoder pDecoder) { - +int CALL_CONVT ac_get_audio_frame(lp_ac_instance pacInstance, lp_ac_decoder pDecoder) +{ lp_ac_package pPackage = ac_read_package(pacInstance); ((lp_ac_audio_decoder)pDecoder)->decoder.buffer_size = 0; int done = 0; while(done == 0 && pPackage != NULL){ - if (((lp_ac_package_data)pPackage)->package.stream_index == pDecoder->stream_index){ + if (((lp_ac_package_data)pPackage)->package.stream_index == pDecoder->stream_index) + { done = ac_decode_package(pPackage, pDecoder); - ac_free_package(pPackage); - - if (((lp_ac_audio_decoder)pDecoder)->decoder.buffer_size < 4096) - done = 0; if (done == 0) pPackage = ac_read_package(pacInstance); @@ -872,19 +660,21 @@ int CALL_CONVT ac_get_audio_frame(lp_ac_instance pacInstance, lp_ac_decoder pDec return 1; } -int CALL_CONVT ac_get_frame(lp_ac_instance pacInstance, lp_ac_decoder pDecoder) { - +int CALL_CONVT ac_get_frame(lp_ac_instance pacInstance, lp_ac_decoder pDecoder) +{ lp_ac_package pPackage = ac_read_package(pacInstance); int done = 0; int pcount = 0; while(done == 0 && pPackage != NULL){ - if (((lp_ac_package_data)pPackage)->package.stream_index == pDecoder->stream_index){ + if (((lp_ac_package_data)pPackage)->package.stream_index == pDecoder->stream_index) + { done = ac_decode_package(pPackage, pDecoder); ac_free_package(pPackage); pcount++; if (done == 0) pPackage = ac_read_package(pacInstance); - } else { + } else + { ac_free_package(pPackage); pPackage = ac_read_package(pacInstance); } @@ -896,25 +686,28 @@ int CALL_CONVT ac_get_frame(lp_ac_instance pacInstance, lp_ac_decoder pDecoder) return pcount; } -int CALL_CONVT ac_skip_frames(lp_ac_instance pacInstance, lp_ac_decoder pDecoder, int num) { - +int CALL_CONVT ac_skip_frames(lp_ac_instance pacInstance, lp_ac_decoder pDecoder, int num) +{ lp_ac_package pPackage = ac_read_package(pacInstance); int done = 0; int i; - for(i=0; i0) pPackage = ac_read_package(pacInstance); done = 0; while(done == 0 && pPackage != NULL){ - if (((lp_ac_package_data)pPackage)->package.stream_index == pDecoder->stream_index){ + if (((lp_ac_package_data)pPackage)->package.stream_index == pDecoder->stream_index) + { done = ac_drop_decode_package(pPackage, pDecoder); ac_free_package(pPackage); if (done == 0) pPackage = ac_read_package(pacInstance); - } else { + } else + { ac_free_package(pPackage); pPackage = ac_read_package(pacInstance); } @@ -930,73 +723,69 @@ int CALL_CONVT ac_skip_frames(lp_ac_instance pacInstance, lp_ac_decoder pDecoder return 1; } - - //Seek function -int CALL_CONVT ac_seek(lp_ac_decoder pDecoder, int dir, int64_t target_pos) { - AVRational timebase = - ((lp_ac_data)pDecoder->pacInstance)->pFormatCtx->streams[pDecoder->stream_index]->time_base; +int CALL_CONVT ac_seek(lp_ac_decoder pDecoder, int dir, int64_t target_pos) +{ + AVRational timebase = ((lp_ac_data)pDecoder->pacInstance)->pFormatCtx->streams[pDecoder->stream_index]->time_base; + int flags = dir < 0 ? AVSEEK_FLAG_BACKWARD : 0; + int64_t pos = av_rescale(target_pos, AV_TIME_BASE, 1000); + pDecoder->timecode = target_pos / 1000.0; + pDecoder->video_clock = target_pos / 1000.0; - int flags = dir < 0 ? AVSEEK_FLAG_BACKWARD : 0; - - int64_t pos = av_rescale(target_pos, AV_TIME_BASE, 1000); - - ((lp_ac_decoder_data)pDecoder)->sought = 100; - pDecoder->timecode = target_pos / 1000; - - if (av_seek_frame(((lp_ac_data)pDecoder->pacInstance)->pFormatCtx, pDecoder->stream_index, - av_rescale_q(pos, AV_TIME_BASE_Q, timebase), flags) >= 0) { - - if (pDecoder->type == AC_DECODER_TYPE_AUDIO) + if (av_seek_frame(((lp_ac_data)pDecoder->pacInstance)->pFormatCtx, pDecoder->stream_index, + av_rescale_q(pos, AV_TIME_BASE_Q, timebase), flags) >= 0) { - if (((lp_ac_audio_decoder)pDecoder)->pCodecCtx->codec->flush != NULL) - avcodec_flush_buffers(((lp_ac_audio_decoder)pDecoder)->pCodecCtx); - av_free(((lp_ac_audio_decoder)pDecoder)->tmp_data); - ((lp_ac_audio_decoder)pDecoder)->tmp_data_length = 0; + if (pDecoder->type == AC_DECODER_TYPE_AUDIO) + { + if (((lp_ac_audio_decoder)pDecoder)->pCodecCtx->codec->flush != NULL) + avcodec_flush_buffers(((lp_ac_audio_decoder)pDecoder)->pCodecCtx); + } + + if (pDecoder->type == AC_DECODER_TYPE_VIDEO) + { + if (((lp_ac_video_decoder)pDecoder)->pCodecCtx->codec->flush != NULL) + avcodec_flush_buffers(((lp_ac_video_decoder)pDecoder)->pCodecCtx); + } + return 1; } - return 1; - } - - return 0; + return 0; } //Free video decoder -void ac_free_video_decoder(lp_ac_video_decoder pDecoder) { - av_free(pDecoder->pFrame); - av_free(pDecoder->pFrameRGB); - if (pDecoder->pSwsCtx != NULL) { - sws_freeContext(pDecoder->pSwsCtx); - } - avcodec_close(pDecoder->pCodecCtx); - - //Free reserved memory for the buffer - av_free(pDecoder->decoder.pBuffer); - - //Free reserved memory for decoder record - av_free(pDecoder); +void ac_free_video_decoder(lp_ac_video_decoder pDecoder) +{ + av_free(pDecoder->pFrame); + av_free(pDecoder->pFrameRGB); + + if (pDecoder->pSwsCtx != NULL) + sws_freeContext(pDecoder->pSwsCtx); + + avcodec_close(pDecoder->pCodecCtx); + + //Free reserved memory for the buffer + av_free(pDecoder->decoder.pBuffer); + + //Free reserved memory for decoder record + av_free(pDecoder); } //Free video decoder -void ac_free_audio_decoder(lp_ac_audio_decoder pDecoder) { -// av_free(pDecoder->decoder.pBuffer); - avcodec_close(pDecoder->pCodecCtx); - - //Free reserved memory for the buffer - av_free(pDecoder->decoder.pBuffer); - - //Free the memory reserved for the temporary audio buffer - av_free(pDecoder->tmp_data); +void ac_free_audio_decoder(lp_ac_audio_decoder pDecoder) +{ + avcodec_close(pDecoder->pCodecCtx); - //Free reserved memory for decoder record - av_free(pDecoder); + //Free reserved memory for the buffer + av_free(pDecoder->decoder.pBuffer); + + //Free reserved memory for decoder record + av_free(pDecoder); } -void CALL_CONVT ac_free_decoder(lp_ac_decoder pDecoder) { - if (pDecoder->type == AC_DECODER_TYPE_VIDEO) { - ac_free_video_decoder((lp_ac_video_decoder)pDecoder); - } - else if (pDecoder->type == AC_DECODER_TYPE_AUDIO) { - ac_free_audio_decoder((lp_ac_audio_decoder)pDecoder); - } +void CALL_CONVT ac_free_decoder(lp_ac_decoder pDecoder) +{ + if (pDecoder->type == AC_DECODER_TYPE_VIDEO) + ac_free_video_decoder((lp_ac_video_decoder)pDecoder); + else if (pDecoder->type == AC_DECODER_TYPE_AUDIO) + ac_free_audio_decoder((lp_ac_audio_decoder)pDecoder); } diff --git a/Vocaluxe/Lib/Video/Acinerella/acinerella.h b/Vocaluxe/Lib/Video/Acinerella/acinerella.h index 203d8750..bdae2056 100644 --- a/Vocaluxe/Lib/Video/Acinerella/acinerella.h +++ b/Vocaluxe/Lib/Video/Acinerella/acinerella.h @@ -113,7 +113,7 @@ struct _ac_audio_stream_info { /*Bits per sample. Can be 8 or 16 Bit.*/ int bit_depth; /*Count of channels in the audio stream.*/ - int channel_count; + int channel_count; }; typedef struct _ac_audio_stream_info ac_audio_stream_info; @@ -167,44 +167,17 @@ typedef struct _ac_package ac_package; /*Pointer on TAc_package*/ typedef ac_package* lp_ac_package; -typedef void* lp_ac_proberesult; - -/*Callback function used to ask the application to read data. Should return - the number of bytes read or an value smaller than zero if an error occured.*/ -typedef int CALL_CONVT (*ac_read_callback)(void *sender, char *buf, int size); -/*Callback function used to ask the application to seek. return 0 if succeed , -1 on failure.*/ -typedef int64_t CALL_CONVT (*ac_seek_callback)(void *sender, int64_t pos, int whence); -/*Callback function that is used to notify the application when the data stream - is opened or closed. For example the file pointer should be resetted to zero - when the "open" function is called.*/ -typedef int CALL_CONVT (*ac_openclose_callback)(void *sender); - -typedef void* CALL_CONVT (*ac_malloc_callback)(size_t size); -typedef void* CALL_CONVT (*ac_realloc_callback)(void *ptr, size_t size); -typedef void CALL_CONVT (*ac_free_callback)(void *ptr); - /*Initializes an Acinerella instance.*/ extern lp_ac_instance CALL_CONVT ac_init(void); extern void CALL_CONVT ac_free(lp_ac_instance pacInstance); -/*Opens a media file. - @param(inst specifies the Acinerella Instance the stream should be opened for) - @param(sender specifies a pointer that is sent to all callback functions to - allow you to do object orientated programming. May be NULL.) - @param(open_proc specifies the callback function that is called, when the - media file is opened. May be NULL.) - @param(seek_proc specifies the callback function that is called, when the ffmpeg decoder - wants to seek in the file. May be NULL) - @param(close_proc specifies the callback function that is called when the media - file is closed. May be NULL.)*/ -extern int CALL_CONVT ac_open( +/*Opens a media file.*/ + +extern int CALL_CONVT ac_open2( lp_ac_instance pacInstance, - void *sender, - ac_openclose_callback open_proc, - ac_read_callback read_proc, - ac_seek_callback seek_proc, - ac_openclose_callback close_proc, - lp_ac_proberesult proberesult); + const char* filename +); + /*Closes an opened media file.*/ extern void CALL_CONVT ac_close(lp_ac_instance pacInstance); @@ -216,9 +189,8 @@ extern lp_ac_package CALL_CONVT ac_read_package(lp_ac_instance pacInstance); /*Frees a package that has been read.*/ extern void CALL_CONVT ac_free_package(lp_ac_package pPackage); -/*Creates an decoder for the specified stream number. Returns NIL if no decoder - could be found.*/ -extern lp_ac_decoder CALL_CONVT ac_create_decoder(lp_ac_instance pacInstance, int nb); +extern lp_ac_decoder CALL_CONVT ac_create_audio_decoder(lp_ac_instance pacInstance); +extern lp_ac_decoder CALL_CONVT ac_create_video_decoder(lp_ac_instance pacInstance); /*Frees an created decoder.*/ extern void CALL_CONVT ac_free_decoder(lp_ac_decoder pDecoder); /*Decodes a package using the specified decoder. The decodec data is stored in the @@ -235,7 +207,4 @@ but seeks the whole file forward. The stream number paremter (nb) is only used f The parameter "dir" specifies the seek direction: 0 for forward, -1 for backward. The target_pos paremeter is in milliseconds. Returns 1 if the functions succeded.*/ extern int CALL_CONVT ac_seek(lp_ac_decoder pDecoder, int dir, int64_t target_pos); - -extern lp_ac_proberesult CALL_CONVT ac_probe_input_buffer(void* buf, int bufsize, char* filename, int* score_max); - #endif /*VIDEOPLAY_H*/ diff --git a/Vocaluxe/Lib/Video/CVideoDecoderFFmpeg.cs b/Vocaluxe/Lib/Video/CVideoDecoderFFmpeg.cs index a6f9728d..d553001e 100644 --- a/Vocaluxe/Lib/Video/CVideoDecoderFFmpeg.cs +++ b/Vocaluxe/Lib/Video/CVideoDecoderFFmpeg.cs @@ -194,10 +194,6 @@ namespace Vocaluxe.Lib.Video private int _StreamID; // stream ID for stream closing private string _FileName; // current video file name - private FileStream _fs; // video file stream - private readonly TAc_read_callback _rc; // read callback for acinerella - private readonly TAc_seek_callback _sc; // seek callback for acinerella - private bool _FileOpened; private float _VideoTimeBase; // frame time @@ -237,8 +233,6 @@ namespace Vocaluxe.Lib.Video public Decoder() { - _rc = read_proc; - _sc = seek_proc; _thread = new Thread(Execute); } @@ -359,6 +353,9 @@ namespace Vocaluxe.Lib.Video #region Threading private void DoSkip() { + if (!_FileOpened) + return; + _VideoSkipTime = _Gap; _SkipTime = _Start + _Gap; _BeforeLoop = false; @@ -449,14 +446,11 @@ namespace Vocaluxe.Lib.Video TAc_instance Instance = new TAc_instance(); try { - _fs = new FileStream(_FileName, FileMode.Open, FileAccess.Read, FileShare.Read); - - _instance = CAcinerella.ac_init(); - CAcinerella.ac_open(_instance, IntPtr.Zero, null, _rc, _sc, null, IntPtr.Zero); + CAcinerella.ac_open2(_instance, _FileName); Instance = (TAc_instance)Marshal.PtrToStructure(_instance, typeof(TAc_instance)); - ok = true; + ok = Instance.opened; } catch (Exception) { @@ -474,20 +468,19 @@ namespace Vocaluxe.Lib.Video _Duration = Instance.info.duration / 1000f; int VideoStreamIndex = -1; - - TAc_stream_info Info = new TAc_stream_info(); - for (int i = 0; i < Instance.stream_count; i++) + TAc_decoder Videodecoder; + try { - CAcinerella.ac_get_stream_info(_instance, i, out Info); - - if (Info.stream_type == TAc_stream_type.AC_STREAM_TYPE_VIDEO) - { - _videodecoder = CAcinerella.ac_create_decoder(_instance, i); - - VideoStreamIndex = i; - break; - } + _videodecoder = CAcinerella.ac_create_video_decoder(_instance); + Videodecoder = (TAc_decoder)Marshal.PtrToStructure(_videodecoder, typeof(TAc_decoder)); + VideoStreamIndex = Videodecoder.stream_index; } + catch (Exception) + { + CLog.LogError("Error opening video file (can't find decoder): " + _FileName); + return; + } + if (VideoStreamIndex < 0) { @@ -495,8 +488,6 @@ namespace Vocaluxe.Lib.Video return; } - TAc_decoder Videodecoder = (TAc_decoder)Marshal.PtrToStructure(_videodecoder, typeof(TAc_decoder)); - _Width = Videodecoder.stream_info.video_info.frame_width; _Height = Videodecoder.stream_info.video_info.frame_height; @@ -656,9 +647,6 @@ namespace Vocaluxe.Lib.Video _NewFrame = false; } } - - //if (!_BufferFull) - // EventDecode.Set(); } private void UploadNewFrame(ref STexture frame) @@ -685,7 +673,6 @@ namespace Vocaluxe.Lib.Video _CurrentVideoTime = _FrameBuffer[num].time; } _Finished = false; - //EventDecode.Set(); } else { @@ -738,28 +725,8 @@ namespace Vocaluxe.Lib.Video } #endregion Threading - #region Callbacks - private Int32 read_proc(IntPtr sender, IntPtr buf, Int32 size) - { - Int32 r = 0; - - byte[] bb = new byte[size]; - r = _fs.Read(bb, 0, size); - Marshal.Copy(bb, 0, buf, size); - - return r; - } - - private Int64 seek_proc(IntPtr sender, Int64 pos, Int32 whence) - { - return _fs.Seek(pos, (SeekOrigin)whence); - } - #endregion Callbacks - public void Dispose() { - _fs.Dispose(); - _fs = null; } } } \ No newline at end of file