diff --git a/bazaar/Media/Media.upp b/bazaar/Media/Media.upp index 6df4c0b92..21037c972 100644 --- a/bazaar/Media/Media.upp +++ b/bazaar/Media/Media.upp @@ -1,3 +1,5 @@ +description "Audio and video managing\377"; + uses CtrlLib, SDL; @@ -6,7 +8,7 @@ library(MSC) "avcodec.lib avformat.lib avutil.lib swscale.lib avdevice.lib avcor library(GCC WIN32) "avcodec avformat avutil swscale avdevice avcore"; -library(GCC !WIN32) "avutil avcodec avformat avdevice swscale avcore"; +library(GCC !WIN32) "avutil avcodec avformat avdevice swscale"; link(MSC) /FORCE:MULTIPLE; @@ -22,9 +24,13 @@ file MediaPlayer.iml, MediaFile readonly separator, MediaFile.cpp, + MediaFile.h, PacketQueue.cpp, clock.cpp, - MediaFile.h, + VolumeCtrl readonly separator, + VolumeCtrl.cpp, + VolumeCtrl.h, + VolumeCtrl.usc, "Utility functions" readonly separator, utility_file.cpp, utility_stream.cpp, @@ -32,6 +38,8 @@ file utility.cpp, utility.h, ffmpeg_base.h, + audioSystem.cpp, + audioSystem.h, mt.h, ubuntu.cpp, srcdoc.tpp; diff --git a/bazaar/Media/MediaFile.cpp b/bazaar/Media/MediaFile.cpp index 01e2ccb95..18640a3ff 100644 --- a/bazaar/Media/MediaFile.cpp +++ b/bazaar/Media/MediaFile.cpp @@ -9,6 +9,7 @@ using namespace Upp; MediaFile::MediaFile() { avcodec_register_all(); // Register all codecs, demux and protocols avdevice_register_all(); + //avfilter_register_all(); av_register_all(); av_log_set_callback(AvLogCallback); @@ -26,6 +27,7 @@ MediaFile::MediaFile() { showAudioFps = 25; rgb = false; forceAspect = true; + audioFactor = 1000; imgRect.Clear(); } @@ -34,10 +36,10 @@ MediaFile::~MediaFile() { av_close_input_file(fileData); fileData = NULL; /* safety */ } - SDL_DestroyMutex(pictq_mutex); - SDL_DestroyCond(pictq_cond); - SDL_DestroyMutex(subpq_mutex); - SDL_DestroyCond(subpq_cond); + //SDL_DestroyMutex(pictq_mutex); + //SDL_DestroyCond(pictq_cond); + //SDL_DestroyMutex(subpq_mutex); + //SDL_DestroyCond(subpq_cond); } void MediaFile::Reset() { @@ -59,13 +61,13 @@ void MediaFile::Reset() { av_init_packet(&flush_pkt); flush_pkt.data = (uint8_t *)"FLUSH"; - pictq_mutex = SDL_CreateMutex(); - pictq_cond = SDL_CreateCond(); + //pictq_mutex = SDL_CreateMutex(); + //pictq_cond = SDL_CreateCond(); memset(&pictq, 0, sizeof(pictq)); pictq_size = pictq_rindex = pictq_windex = 0; - subpq_mutex = SDL_CreateMutex(); - subpq_cond = SDL_CreateCond(); + //subpq_mutex = SDL_CreateMutex(); + //subpq_cond = SDL_CreateCond(); memset(&subpq, 0, sizeof(subpq)); subpq_size = subpq_rindex = subpq_windex = 0; @@ -74,7 +76,7 @@ void MediaFile::Reset() { reformat_ctx = 0; - decoderThreadId = video_tid = refresh_tid = subtitle_tid = 0; + //decoderThreadId = video_tid = refresh_tid = subtitle_tid = 0; subtitle_stream_changed = false; debug = debug_mv = 0; @@ -262,7 +264,8 @@ bool MediaFile::StreamOpen(int stream_index) video_current_pts_time = GetUSec(); videoq.Init(flush_pkt, &flush_pkt); - video_tid = SDL_CreateThread(VideoThread, this); + video_tid.Run(THISBACK(VideoThread)); + //video_tid = SDL_CreateThread(VideoThread, this); break; case AVMEDIA_TYPE_SUBTITLE: @@ -270,7 +273,8 @@ bool MediaFile::StreamOpen(int stream_index) subtitleStream = fileData->streams[stream_index]; subtitleq.Init(flush_pkt, &flush_pkt); - subtitle_tid = SDL_CreateThread(SubtitleThread, this); + subtitle_tid.Run(THISBACK(SubtitleThread)); + //subtitle_tid = SDL_CreateThread(SubtitleThread, this); break; default: @@ -301,11 +305,11 @@ void MediaFile::StreamClose(int stream_index) videoq.Abort(); // note: we also signal this mutex to make sure we deblock the video thread in all cases - SDL_LockMutex(pictq_mutex); - SDL_CondSignal(pictq_cond); - SDL_UnlockMutex(pictq_mutex); + INTERLOCKED_(pictq_mutex) { + pictq_cond.Signal(); + } - SDL_WaitThread(video_tid, NULL); + video_tid.Wait(); videoq.End(); break; @@ -313,13 +317,12 @@ void MediaFile::StreamClose(int stream_index) subtitleq.Abort(); // note: we also signal this mutex to make sure we deblock the video thread in all cases - SDL_LockMutex(subpq_mutex); - subtitle_stream_changed = true; + INTERLOCKED_(subpq_mutex) { + subtitle_stream_changed = true; + subpq_cond.Signal(); + } - SDL_CondSignal(subpq_cond); - SDL_UnlockMutex(subpq_mutex); - - SDL_WaitThread(subtitle_tid, NULL); + subtitle_tid.Wait(); subtitleq.End(); break; @@ -361,7 +364,13 @@ int MediaFile::audio_decode_frame(double *pts_ptr) // The audio packet can contain several frames while (pkt_temp->size > 0) { data_size = sizeof(audio_buf1); +#if (((LIBAVCODEC_VERSION_MAJOR <= 52) && (LIBAVCODEC_VERSION_MINOR <= 20)) || UBUNTU_TRICK) + len1 = avcodec_decode_audio2(dec, (int16_t *)audio_buf1, &data_size, pkt_temp->data, + pkt_temp->size); +#else len1 = avcodec_decode_audio3(dec, (int16_t *)audio_buf1, &data_size, pkt_temp); +#endif + if (len1 < 0) { pkt_temp->size = 0; // if error, we skip the frame break; @@ -433,16 +442,12 @@ int MediaFile::audio_decode_frame(double *pts_ptr) } } -/* copy samples for viewing in editor window */ -void MediaFile::update_sample_display(short *samples, int samples_size) -{ - int size, len, channels; - - channels = audioStream->codec->channels; - - size = samples_size / sizeof(short); +// Copy samples for viewing in editor window +void MediaFile::update_sample_display(short *samples, int samples_size) { + int channels = audioStream->codec->channels; + int size = samples_size / sizeof(short); while (size > 0) { - len = SAMPLE_ARRAY_SIZE - sample_array_index; + int len = SAMPLE_ARRAY_SIZE - sample_array_index; if (len > size) len = size; memcpy(sample_array + sample_array_index, samples, len * sizeof(short)); @@ -454,8 +459,8 @@ void MediaFile::update_sample_display(short *samples, int samples_size) } } -/* return the new audio buffer size (samples can be added or deleted - to get better sync if video or external master clock) */ +// Return the new audio buffer size (samples can be added or deleted +// to get better sync if video or external master clock) int MediaFile::synchronize_audio(short *samples, int samples_size1, double pts) { int n, samples_size; @@ -514,8 +519,7 @@ int MediaFile::synchronize_audio(short *samples, int samples_size1, double pts) } } } else { - /* too big difference : may be initial PTS errors, so - reset A-V filter */ + // Too big difference : may be initial PTS errors, so reset A-V filter audio_diff_avg_count = 0; audio_diff_cum = 0; } @@ -526,11 +530,10 @@ int MediaFile::synchronize_audio(short *samples, int samples_size1, double pts) // Called by VideoThread to store the just decoded frame bool MediaFile::queue_picture(AVFrame *frame, double pts) { // wait until we have space to put a new picture - SDL_LockMutex(pictq_mutex); - while (pictq_size >= VIDEO_PICTURE_QUEUE_SIZE && !videoq.IsAbort()) - SDL_CondWait(pictq_cond, pictq_mutex); - - SDL_UnlockMutex(pictq_mutex); + INTERLOCKED_(pictq_mutex) { + while (pictq_size >= VIDEO_PICTURE_QUEUE_SIZE && !videoq.IsAbort()) + pictq_cond.Wait(pictq_mutex); + } if (videoq.IsAbort()) return false; @@ -550,11 +553,10 @@ bool MediaFile::queue_picture(AVFrame *frame, double pts) { SDL_PushEvent(&event); // wait until the picture is allocated - SDL_LockMutex(pictq_mutex); - while (!vp.allocated && !videoq.IsAbort()) - SDL_CondWait(pictq_cond, pictq_mutex); - - SDL_UnlockMutex(pictq_mutex); + INTERLOCKED_(pictq_mutex) { + while (!vp.allocated && !videoq.IsAbort()) + pictq_cond.Wait(pictq_mutex); + } if (videoq.IsAbort()) return false; @@ -568,7 +570,7 @@ bool MediaFile::queue_picture(AVFrame *frame, double pts) { SwsContext *context = 0; // if the frame is not skipped, then display it - if (vp.overlay) { // Convertion to YUV420P + if (vp.overlay) { // Conversion to YUV420P context = SWSGetContext(videoStream->codec->width, videoStream->codec->height, videoStream->codec->pix_fmt, videoStream->codec->width, videoStream->codec->height, @@ -626,9 +628,9 @@ bool MediaFile::queue_picture(AVFrame *frame, double pts) { // now we can update the picture count if (++pictq_windex == VIDEO_PICTURE_QUEUE_SIZE) pictq_windex = 0; - SDL_LockMutex(pictq_mutex); - pictq_size++; - SDL_UnlockMutex(pictq_mutex); + INTERLOCKED_(pictq_mutex) { + pictq_size++; + } } return true; } @@ -649,6 +651,8 @@ void MediaFile::SetError(String str) { } bool MediaFile::BeginDecoder() { - decoderThreadId = SDL_CreateThread(DecoderThread, this); - return !!decoderThreadId; + return decoderThreadId.Run(THISBACK(DecoderThread)); + //decoderThreadId = SDL_CreateThread(DecoderThread, this); + //return !!decoderThreadId; } + diff --git a/bazaar/Media/MediaFile.h b/bazaar/Media/MediaFile.h index d54068aa9..076fadbb3 100644 --- a/bazaar/Media/MediaFile.h +++ b/bazaar/Media/MediaFile.h @@ -76,13 +76,14 @@ private: int size; int maxSize; bool abort_request; - SDL_mutex *mutex; - SDL_cond *cond; + Mutex mutex; + ConditionVariable cond; }; void sdl_audio_callback(void *data, Uint8 *stream, int len); class MediaFile { +typedef MediaFile CLASSNAME; public: friend int decoderInterrupt_cb(); friend void sdl_audio_callback(void *data, Uint8 *stream, int len); @@ -90,10 +91,12 @@ public: MediaFile(); ~MediaFile(); - inline String GetFileName() {return fileData->filename;}; - inline double GetDuration() {return double(fileData->duration) / AV_TIME_BASE;}; - inline int64 GetDurationTimeBase() {return fileData->duration;}; - inline int GetNumStreams() {return fileData->nb_streams;}; + inline bool IsOpened() {return fileData;}; + + inline String GetFileName() {return !fileData ? "" : fileData->filename;}; + inline double GetDuration() {return !fileData ? -1 : double(fileData->duration) / AV_TIME_BASE;}; + inline int64 GetDurationTimeBase() {return !fileData ? -1 : fileData->duration;}; + inline int GetNumStreams() {return !fileData ? -1 : fileData->nb_streams;}; int GetNumVideo() {return numVideoStreams;}; int GetNumAudio() {return numAudioStreams;}; @@ -114,6 +117,8 @@ public: inline MediaFile& ShowAudio(bool show = true) {showAudio = show; return *this;}; inline MediaFile& SetShowAudioFPS(double fps) {showAudioFps = fps; return *this;}; + inline MediaFile& SetAudioFactor(double f) {audioFactor = int(f*1000); return *this;}; + struct StreamData { int id; String codec; @@ -158,9 +163,9 @@ protected: double get_external_clock(); bool queue_picture(AVFrame *src_frame, double pts); void stream_pause(); - static int DecoderThread(void *arg); - static int VideoThread(void *arg); - static int SubtitleThread(void *arg); + void DecoderThread();//void *arg); + void VideoThread();//(void *arg); + void SubtitleThread();//(void *arg); bool BeginDecoder(); AVFormatContext *fileData; @@ -185,19 +190,19 @@ protected: VideoPicture pictq[VIDEO_PICTURE_QUEUE_SIZE]; int pictq_size, pictq_rindex, pictq_windex; - SDL_mutex *pictq_mutex; - SDL_cond *pictq_cond; + Mutex pictq_mutex; + ConditionVariable pictq_cond; SubPicture subpq[SUBPICTURE_QUEUE_SIZE]; int subpq_size, subpq_rindex, subpq_windex; - SDL_mutex *subpq_mutex; - SDL_cond *subpq_cond; + Mutex subpq_mutex; + ConditionVariable subpq_cond; AVStream *audioStream, *videoStream, *subtitleStream; AVAudioConvert *reformat_ctx; - SDL_Thread *video_tid, *decoderThreadId, *refresh_tid, *subtitle_tid; + Thread video_tid, decoderThreadId, /*refresh_tid,*/ subtitle_tid; int subtitle_stream_changed; int debug, debug_mv, workaround_bugs; @@ -255,6 +260,8 @@ protected: bool forceAspect; // Force aspect ratio Rect imgRect; // Image size Mutex mtx; + + AtomicVar audioFactor; }; diff --git a/bazaar/Media/MediaPlayer.cpp b/bazaar/Media/MediaPlayer.cpp index eb1cbcfd6..d5f24b6ab 100644 --- a/bazaar/Media/MediaPlayer.cpp +++ b/bazaar/Media/MediaPlayer.cpp @@ -331,16 +331,16 @@ bool MediaPlayer::alloc_picture() return false; } - SDL_LockMutex(pictq_mutex); - vp.allocated = true; - SDL_CondSignal(pictq_cond); - SDL_UnlockMutex(pictq_mutex); + INTERLOCKED_(pictq_mutex) { + vp.allocated = true; + pictq_cond.Signal(); + } return true; } void MediaPlayer::video_audioWaveform() { - int i, i_start, x, y1, y, ys, delay, n, nb_display_channels; + int i_start, x, y1, y, ys, delay, n, nb_display_channels; int ch, channels, h, h2, bgcolor, fgcolor; int16_t time_diff; int rdft_bits, nb_freq; @@ -371,15 +371,15 @@ void MediaPlayer::video_audioWaveform() i_start = x = compute_mod(sample_array_index - delay * channels, SAMPLE_ARRAY_SIZE); h= INT_MIN; - for(i=0; i<1000; i+=channels){ + for(int i = 0; i < 1000; i += channels) { int idx= (SAMPLE_ARRAY_SIZE + x - i) % SAMPLE_ARRAY_SIZE; int a= sample_array[idx]; int b= sample_array[(idx + 4*channels)%SAMPLE_ARRAY_SIZE]; int c= sample_array[(idx + 5*channels)%SAMPLE_ARRAY_SIZE]; int d= sample_array[(idx + 9*channels)%SAMPLE_ARRAY_SIZE]; int score= a-d; - if(hformat, 0x00, 0xff, 0x00); - /* total height for one channel */ + // total height for one channel h = screen->h / nb_display_channels; - /* graph height / 2 */ + // graph height / 2 h2 = (h * 9) / 20; for(ch = 0; ch < nb_display_channels; ch++) { - i = i_start + ch; + int i = i_start + ch; y1 = ch * h + (h / 2); /* position of center line */ for(x = 0; x < screen->w; x++) { y = (sample_array[i] * h2) >> 15; @@ -447,30 +447,29 @@ void MediaPlayer::video_refresh() { if (++pictq_rindex == VIDEO_PICTURE_QUEUE_SIZE) pictq_rindex = 0; - SDL_LockMutex(pictq_mutex); - pictq_size--; - SDL_CondSignal(pictq_cond); - SDL_UnlockMutex(pictq_mutex); + INTERLOCKED_(pictq_mutex) { + pictq_size--; + pictq_cond.Signal(); + } return; } if(subtitleStream) { if (subtitle_stream_changed) { - SDL_LockMutex(subpq_mutex); - - while (subpq_size) { - free_subpicture(&subpq[subpq_rindex]); - - // update queue size for next picture - if (++subpq_rindex == SUBPICTURE_QUEUE_SIZE) - subpq_rindex = 0; - - subpq_size--; + INTERLOCKED_(subpq_mutex) { + while (subpq_size) { + free_subpicture(&subpq[subpq_rindex]); + + // update queue size for next picture + if (++subpq_rindex == SUBPICTURE_QUEUE_SIZE) + subpq_rindex = 0; + + subpq_size--; + } + subtitle_stream_changed = false; + + subpq_cond.Signal(); } - subtitle_stream_changed = false; - - SDL_CondSignal(subpq_cond); - SDL_UnlockMutex(subpq_mutex); } else { if (subpq_size > 0) { SubPicture *sp, *sp2; @@ -489,10 +488,10 @@ void MediaPlayer::video_refresh() { if (++subpq_rindex == SUBPICTURE_QUEUE_SIZE) subpq_rindex = 0; - SDL_LockMutex(subpq_mutex); - subpq_size--; - SDL_CondSignal(subpq_cond); - SDL_UnlockMutex(subpq_mutex); + INTERLOCKED_(subpq_mutex) { + subpq_size--; + subpq_cond.Signal(); + } } } } @@ -503,10 +502,10 @@ void MediaPlayer::video_refresh() { if (++pictq_rindex == VIDEO_PICTURE_QUEUE_SIZE) pictq_rindex = 0; - SDL_LockMutex(pictq_mutex); - pictq_size--; - SDL_CondSignal(pictq_cond); - SDL_UnlockMutex(pictq_mutex); + INTERLOCKED_(pictq_mutex) { + pictq_size--; + pictq_cond.Signal(); + } } } else if (audioStream && showAudio) { if (get_external_clock() > lastAudioShow + 1./showAudioFps) { diff --git a/bazaar/Media/PacketQueue.cpp b/bazaar/Media/PacketQueue.cpp index c759fa3fb..ca64bd1c2 100644 --- a/bazaar/Media/PacketQueue.cpp +++ b/bazaar/Media/PacketQueue.cpp @@ -1,124 +1,121 @@ -#include - -using namespace Upp; - -#include "MediaPlayer.h" -#include "utility.h" -#include "mediaplayer_in.h" - - -PacketQueue::PacketQueue() -{ - Init(); -} - -void PacketQueue::Init() -{ - first_pkt = last_pkt = 0; - nb_packets = size = 0; - abort_request = false; - mutex = 0; - cond = 0; -} - -void PacketQueue::Init(AVPacket &pkt, AVPacket *flush_pkt) -{ - Init(); - mutex = SDL_CreateMutex(); - cond = SDL_CreateCond(); - Put(&pkt, flush_pkt); -} - -void PacketQueue::Flush() -{ - AVPacketList *pkt, *pkt1; - - SDL_LockMutex(mutex); - for(pkt = first_pkt; pkt != NULL; pkt = pkt1) { - pkt1 = pkt->next; - av_free_packet(&pkt->pkt); - av_freep(&pkt); - } - first_pkt = last_pkt = 0; - nb_packets = size = 0; - SDL_UnlockMutex(mutex); -} - -void PacketQueue::End() -{ - Flush(); - SDL_DestroyMutex(mutex); - SDL_DestroyCond(cond); -} - -int PacketQueue::Put(AVPacket *pkt, AVPacket *flush_pkt) -{ - AVPacketList *pkt1; - - // Duplicate the packet - if (pkt != flush_pkt && av_dup_packet(pkt) < 0) - return -1; - - pkt1 = (AVPacketList*)av_malloc(sizeof(AVPacketList)); - if (!pkt1) - return -1; - pkt1->pkt = *pkt; - pkt1->next = NULL; - - SDL_LockMutex(mutex); - - if (!last_pkt) - first_pkt = pkt1; - else - last_pkt->next = pkt1; - last_pkt = pkt1; - nb_packets++; - size += pkt1->pkt.size + sizeof(*pkt1); - // Should duplicate packet data in DV case - SDL_CondSignal(cond); - - SDL_UnlockMutex(mutex); - return 0; -} - -void PacketQueue::Abort() -{ - SDL_LockMutex(mutex); - abort_request = true; - SDL_CondSignal(cond); - SDL_UnlockMutex(mutex); -} - -// return < 0 if aborted, 0 if no packet and > 0 if packet. -int PacketQueue::Get(AVPacket *pkt, bool decodeEnd) -{ - AVPacketList *pkt1; - int ret; - - SDL_LockMutex(mutex); - - for(;;) { - if (abort_request) { - ret = -1; - break; - } - pkt1 = first_pkt; - if (pkt1) { - first_pkt = pkt1->next; - if (!first_pkt) - last_pkt = NULL; - nb_packets--; - size -= pkt1->pkt.size + sizeof(*pkt1); - *pkt = pkt1->pkt; - av_free(pkt1); - ret = 1; - break; - } else if (decodeEnd) { - ret = 0; - break; - } else - SDL_CondWait(cond, mutex); - } - SDL_UnlockMutex(mutex); - return ret; +#include + +using namespace Upp; + +#include "MediaPlayer.h" +#include "utility.h" +#include "mediaplayer_in.h" + + +PacketQueue::PacketQueue() +{ + Init(); +} + +void PacketQueue::Init() +{ + first_pkt = last_pkt = 0; + nb_packets = size = 0; + abort_request = false; + //mutex = 0; + //cond = 0; +} + +void PacketQueue::Init(AVPacket &pkt, AVPacket *flush_pkt) +{ + Init(); + //mutex = SDL_CreateMutex(); + //cond = SDL_CreateCond(); + Put(&pkt, flush_pkt); +} + +void PacketQueue::Flush() +{ + AVPacketList *pkt, *pkt1; + + INTERLOCKED_(mutex) { + for(pkt = first_pkt; pkt != NULL; pkt = pkt1) { + pkt1 = pkt->next; + av_free_packet(&pkt->pkt); + av_freep(&pkt); + } + first_pkt = last_pkt = 0; + nb_packets = size = 0; + } +} + +void PacketQueue::End() +{ + Flush(); + //SDL_DestroyMutex(mutex); + //SDL_DestroyCond(cond); +} + +int PacketQueue::Put(AVPacket *pkt, AVPacket *flush_pkt) +{ + AVPacketList *pkt1; + + // Duplicate the packet + if (pkt != flush_pkt && av_dup_packet(pkt) < 0) + return -1; + + pkt1 = (AVPacketList*)av_malloc(sizeof(AVPacketList)); + if (!pkt1) + return -1; + pkt1->pkt = *pkt; + pkt1->next = NULL; + + INTERLOCKED_(mutex) { + if (!last_pkt) + first_pkt = pkt1; + else + last_pkt->next = pkt1; + last_pkt = pkt1; + nb_packets++; + size += pkt1->pkt.size + sizeof(*pkt1); + // Should duplicate packet data in DV case + cond.Signal(); + } + return 0; +} + +void PacketQueue::Abort() +{ + INTERLOCKED_(mutex) { + abort_request = true; + cond.Signal(); + } +} + +// return < 0 if aborted, 0 if no packet and > 0 if packet. +int PacketQueue::Get(AVPacket *pkt, bool decodeEnd) +{ + AVPacketList *pkt1; + int ret; + + INTERLOCKED_(mutex) { + for(;;) { + if (abort_request) { + ret = -1; + break; + } + pkt1 = first_pkt; + if (pkt1) { + first_pkt = pkt1->next; + if (!first_pkt) + last_pkt = NULL; + nb_packets--; + size -= pkt1->pkt.size + sizeof(*pkt1); + *pkt = pkt1->pkt; + av_free(pkt1); + ret = 1; + break; + } else if (decodeEnd) { + ret = 0; + break; + } else + cond.Wait(mutex); + } + } + return ret; } \ No newline at end of file diff --git a/bazaar/Media/VolumeCtrl.cpp b/bazaar/Media/VolumeCtrl.cpp new file mode 100644 index 000000000..eaf0b1766 --- /dev/null +++ b/bazaar/Media/VolumeCtrl.cpp @@ -0,0 +1,124 @@ +#include "VolumeCtrl.h" + + +SliderVolume::SliderVolume() { + moving = false; + Jump(); +} + +void SliderVolume::LeftDown(Point pos, dword keyflags) { + SliderCtrl::LeftDown(pos, keyflags); + moving = true; +} + +void SliderVolume::LeftUp(Point pos, dword keyflags) { + SliderCtrl::LeftUp(pos, keyflags); + moving = false; +} + +void SliderVolume::SetData(const Value& v) { + Size sz = GetSize(); + bool horiz = sz.cx > sz.cy; + + if (horiz) + SliderCtrl::SetData(v); + else + SliderCtrl::SetData(GetMax() - int(v)); +} + +Value SliderVolume::GetData() const { + Size sz = GetSize(); + bool horiz = sz.cx > sz.cy; + + Value val = SliderCtrl::GetData(); + if (horiz) + return val; + else + return GetMax() - int(val); +} + +VolumeCtrl::VolumeCtrl() { + Add(sliderL); + Add(sliderR); + sliderL.MinMax(0, MAX_MAINVOLUME); + sliderR.MinMax(0, MAX_MAINVOLUME); + sliderL.WhenAction = THISBACK(Action); + sliderR.WhenAction = THISBACK(Action); + Add(labelL); + Add(labelR); + labelL.SetLabel("L"); + labelR.SetLabel("R"); + SetTimeCallback(-100, THISBACK(TimerAction)); + stereo = false; + showLR = true; + TimerAction(); +} + +void VolumeCtrl::Action() { + if (stereo) { + int left, right; + if (!GetMainVolume(left, right)) + return; + int valL = sliderL.GetData(); + int valR = sliderR.GetData(); + if (valL != left || valR != right) + SetMainVolume(valL, valR); + } else { + int val = sliderL.GetData(); + if (val != GetMainVolume()) + SetMainVolume(val); + } +} + +void VolumeCtrl::TimerAction() { + if(sliderL.IsMoving() && (sliderR.IsMoving() || !stereo)) + return; + if (stereo) { + int left, right; + if (!GetMainVolume(left, right)) + return; + if (left != sliderL.GetData()) + sliderL.SetData(left); + if (right != sliderR.GetData()) + sliderR.SetData(right); + } else { + int val = GetMainVolume(); + if ((val != -1) && (val != sliderL.GetData())) + sliderL.SetData(val); + } +} + +void VolumeCtrl::Layout() { + Rect r = GetRect(); + Size sz = GetSize(); + + if (stereo) { + sliderR.Show(); + labelL.Show(showLR); + labelR.Show(showLR); + if (sz.cx < sz.cy) { + Font f = Arial(sz.cx/4); + Size fontSize = GetTextSize("X", f); + if (showLR) + labelL.SetFont(f).BottomPosZ(0, fontSize.cy).LeftPosZ(int(0.15*sz.cx), 2*fontSize.cx); + sliderL.VSizePosZ(0, (showLR ? fontSize.cy : 0)).LeftPosZ(0, sz.cx/2); + if (showLR) + labelR.SetFont(f).BottomPosZ(0, fontSize.cy).LeftPosZ(int(0.65*sz.cx), 2*fontSize.cx); + sliderR.VSizePosZ(0, (showLR ? fontSize.cy : 0)).LeftPosZ(sz.cx/2, sz.cx/2); + } else { + Font f = Arial(sz.cy/4); + Size fontSize = GetTextSize("X", f); + if (showLR) + labelL.SetFont(f).HSizePosZ(0, 0).TopPosZ(int(0.1*sz.cy), fontSize.cy); + sliderL.HSizePosZ((showLR ? int(1.5*fontSize.cx) : 0), 0).TopPosZ(0, sz.cy/2); + if (showLR) + labelR.SetFont(f).HSizePosZ(0, 0).TopPosZ(int(0.6*sz.cy), fontSize.cy); + sliderR.HSizePosZ((showLR ? int(1.5*fontSize.cx) : 0), 0).TopPosZ(sz.cy/2, sz.cy/2); + } + } else { + sliderL.SizePos(); + sliderR.Hide(); + labelL.Hide(); + labelR.Hide(); + } +} diff --git a/bazaar/Media/VolumeCtrl.h b/bazaar/Media/VolumeCtrl.h new file mode 100644 index 000000000..4c8be0532 --- /dev/null +++ b/bazaar/Media/VolumeCtrl.h @@ -0,0 +1,46 @@ +#ifndef _Media_VolumeCtrl_h_ +#define _Media_VolumeCtrl_h_ + +#include + +using namespace Upp; + +#include "audioSystem.h" + + +class SliderVolume : public SliderCtrl { +typedef SliderVolume CLASSNAME; +public: + SliderVolume(); + bool IsMoving() {return moving;}; + virtual void SetData(const Value& v); + virtual Value GetData() const; + +private: + bool moving; + + void LeftDown(Point pos, dword keyflags); + void LeftUp(Point pos, dword keyflags); +}; + +class VolumeCtrl : public StaticRect { +typedef VolumeCtrl CLASSNAME; +public: + VolumeCtrl(); + VolumeCtrl &SetStereo(bool _stereo = false) {stereo = _stereo; return *this;}; + VolumeCtrl &ShowLR(bool _showLR = true) {showLR = _showLR; return *this;}; + +private: + bool stereo; + bool showLR; + + SliderVolume sliderL, sliderR; + Label labelL, labelR; + + void Action(); + void TimerAction(); + + virtual void Layout(); +}; + +#endif diff --git a/bazaar/Media/VolumeCtrl.usc b/bazaar/Media/VolumeCtrl.usc new file mode 100644 index 000000000..0345dfa76 --- /dev/null +++ b/bazaar/Media/VolumeCtrl.usc @@ -0,0 +1,53 @@ +ctrl VolumeCtrl { + group "Media"; + + GetMinSize() { return Size(0, 0); } + GetStdSize() { return Size(64, 24); } + + Frame SetFrame @1; + bool SetStereo = false; + bool ShowLR = true; + + PaintSlider(w, r) { + sz = Size(r.right - r.left, r.bottom - r.top); + + halfX = int(r.left + r.right) >> 1; + halfY = int(r.top + r.bottom) >> 1; + + if (sz.cx < sz.cy) { + DrawInsetFrame(w, Rect(halfX - 2, r.top + 2, halfX + 2, r.bottom - 2)); + imgSz = GetImageSize("CtrlImg::vthumb"); + w.DrawImage(halfX - (imgSz.cx >> 1), halfY - (imgSz.cy >> 1), "CtrlImg::vthumb"); + } else { + DrawInsetFrame(w, Rect(r.left + 2, halfY - 2, r.right - 2, halfY + 2)); + imgSz = GetImageSize("CtrlImg::hthumb"); + w.DrawImage(halfX - (imgSz.cx >> 1), halfY - (imgSz.cy >> 1), "CtrlImg::hthumb"); + } + } + Paint(w) { + r = GetRect(); + DrawCtrlFrame(w, r, .SetFrame); + + if (.SetStereo) { + sz = Size(r.right - r.left, r.bottom - r.top); + if (sz.cx < sz.cy) { + fontSize = GetTextSize("X", Arial(sz.cx/4)); + if (.ShowLR) + w.DrawText(r.left + 0.15*sz.cx, r.top + sz.cy - fontSize.cy, "L", Arial(sz.cx/4), :SBlack); + PaintSlider(w, Rect(r.left, r.top, r.left + sz.cx/2, r.bottom - (.ShowLR ? fontSize.cy : 0))); + if (.ShowLR) + w.DrawText(r.left + 0.65*sz.cx, r.top + sz.cy - fontSize.cy, "R", Arial(sz.cx/4), :SBlack); + PaintSlider(w, Rect(r.left + sz.cx/2, r.top, r.right, r.bottom - (.ShowLR ? fontSize.cy : 0))); + } else { + fontSize = GetTextSize("X", Arial(sz.cy/4)); + if (.ShowLR) + w.DrawText(r.left, r.top + 0.1*sz.cy, "L", Arial(sz.cy/4), :SBlack); + PaintSlider(w, Rect(r.left + (.ShowLR ? 1.5*fontSize.cx : 0), r.top, r.right, r.bottom/2)); + if (.ShowLR) + w.DrawText(r.left, r.top + 0.6*sz.cy, "R", Arial(sz.cy/4), :SBlack); + PaintSlider(w, Rect(r.left + (.ShowLR ? 1.5*fontSize.cx : 0), r.top + sz.cy/2, r.right, r.bottom)); + } + } else + PaintSlider(w, r); + } +} \ No newline at end of file diff --git a/bazaar/Media/audioSystem.cpp b/bazaar/Media/audioSystem.cpp new file mode 100644 index 000000000..c4e953909 --- /dev/null +++ b/bazaar/Media/audioSystem.cpp @@ -0,0 +1,178 @@ +#include + +using namespace Upp; + +#include +#include "audioSystem.h" + +int GetMainVolume() { + int left, right; + + if(!GetMainVolume(left, right)) + return -1; + return Average(left, right); +} + +bool SetMainVolume(int vol) { + return SetMainVolume(vol, vol); +} + +#ifdef PLATFORM_POSIX +//#include +#include +//#include +//#include +#include + +// See more details here + +bool GetMainVolume(int &left, int &right) { + int fAudio = open("/dev/mixer", O_RDWR, 0); + if (fAudio == -1) + return false; + int vol; + bool ret; + if(ioctl(fAudio, MIXER_READ(SOUND_MIXER_VOLUME), &vol) == -1) + ret = false; + else + ret = true; + close(fAudio); + + // Linux levels are in percentage + if (ret) { + left = (MAX_MAINVOLUME/100)*(vol & 0x7f); + right = (MAX_MAINVOLUME/100)*((vol >> 8) & 0x7f); + } else + left = right = -1; + return ret; +} + +bool SetMainVolume(int left, int right) { + int vol = ((right/(MAX_MAINVOLUME/100)) << 8) | (left/(MAX_MAINVOLUME/100)); + int fAudio = open("/dev/mixer", O_RDWR, 0); + if (fAudio == -1) + return -1; + bool ret; + if(ioctl(fAudio, MIXER_WRITE(SOUND_MIXER_VOLUME), &vol) == -1) + ret = false; + else + ret = true; + close(fAudio); + return ret; +} + +#else + +#include + +// See more details here http://echochamber.me/viewtopic.php?f=11&t=15858 + +bool GetVolumeCtrl(HMIXER &hMixer, MIXERCONTROL &mc) { + MMRESULT result; + + if (MMSYSERR_NOERROR != (result = mixerOpen(&hMixer, MIXER_OBJECTF_MIXER, 0, 0, 0))) + return false; + + // Get the speaker line of the mixer device. + MIXERLINE ml = {0}; + ml.cbStruct = sizeof(MIXERLINE); + ml.dwComponentType = MIXERLINE_COMPONENTTYPE_DST_SPEAKERS; + result = mixerGetLineInfo((HMIXEROBJ) hMixer, &ml, MIXER_GETLINEINFOF_COMPONENTTYPE); + if (result != MMSYSERR_NOERROR) { + mixerClose(hMixer); + return false; + } + + // Get the volume control of the speaker line. + MIXERLINECONTROLS mlc = {0}; + mlc.cbStruct = sizeof(MIXERLINECONTROLS); + mlc.dwLineID = ml.dwLineID; + mlc.dwControlType = MIXERCONTROL_CONTROLTYPE_VOLUME; + mlc.cControls = 1; + mlc.pamxctrl = &mc; + mlc.cbmxctrl = sizeof(MIXERCONTROL); + result = mixerGetLineControls((HMIXEROBJ) hMixer, &mlc, MIXER_GETLINECONTROLSF_ONEBYTYPE); + if (result != MMSYSERR_NOERROR) { + mixerClose(hMixer); + return false; + } + return true; +} + +bool SetMainVolume(int left, int right) { + HMIXER hMixer; + MIXERCONTROL mc = {0}; + + GetVolumeCtrl(hMixer, mc); + + MIXERCONTROLDETAILS mcd = {0}; + MIXERCONTROLDETAILS_UNSIGNED mcdVol[2] = {0}; + double range = mc.Bounds.dwMaximum - mc.Bounds.dwMinimum; + DWORD dwLeft = DWORD(left *range/MAX_MAINVOLUME); + DWORD dwRight = DWORD(right*range/MAX_MAINVOLUME); + + memcpy(&mcdVol[0], &dwLeft, sizeof(MIXERCONTROLDETAILS_UNSIGNED)); + memcpy(&mcdVol[1], &dwRight, sizeof(MIXERCONTROLDETAILS_UNSIGNED)); + + mcd.cbStruct = sizeof(MIXERCONTROLDETAILS); + mcd.hwndOwner = 0; + mcd.dwControlID = mc.dwControlID; + mcd.paDetails = &mcdVol; + mcd.cbDetails = sizeof(MIXERCONTROLDETAILS_UNSIGNED); + mcd.cChannels = 2; + MMRESULT result = mixerSetControlDetails((HMIXEROBJ) hMixer, &mcd, + MIXER_OBJECTF_HMIXER | MIXER_SETCONTROLDETAILSF_VALUE); + mixerClose(hMixer); + + return result == MMSYSERR_NOERROR; +} + +bool GetMainVolume(int &left, int &right) { + HMIXER hMixer; + MIXERCONTROL mc = {0}; + + GetVolumeCtrl(hMixer, mc); + + MIXERCONTROLDETAILS mcd = {0}; + MIXERCONTROLDETAILS_UNSIGNED mcdVol[2] = {0}; + + mcd.cbStruct = sizeof(MIXERCONTROLDETAILS); + mcd.hwndOwner = 0; + mcd.dwControlID = mc.dwControlID; + mcd.paDetails = &mcdVol; + mcd.cbDetails = sizeof(MIXERCONTROLDETAILS_UNSIGNED); + mcd.cChannels = 2; + MMRESULT result = mixerGetControlDetails((HMIXEROBJ) hMixer, &mcd, + MIXER_OBJECTF_HMIXER | MIXER_GETCONTROLDETAILSF_VALUE); + + if (result == MMSYSERR_NOERROR) { + double range = mc.Bounds.dwMaximum - mc.Bounds.dwMinimum; + left = int((mcdVol[0].dwValue - mc.Bounds.dwMinimum)*MAX_MAINVOLUME/range); + right = int((mcdVol[1].dwValue - mc.Bounds.dwMinimum)*MAX_MAINVOLUME/range); + } else + left = right = -1; + + mixerClose(hMixer); + + return result == MMSYSERR_NOERROR; +} + +const char* GetAudioErrorDescription(MMRESULT code) { + switch(code) { + case MMSYSERR_ERROR: return "Unspecified Error"; + case MMSYSERR_BADDEVICEID: return "Device ID out of range"; + case MMSYSERR_NOTENABLED: return "Driver failed enable"; + case MMSYSERR_ALLOCATED: return "Device already allocated"; + case MMSYSERR_INVALHANDLE: return "Device handle is invalid"; + case MMSYSERR_NODRIVER: return "No device driver present"; + case MMSYSERR_NOMEM: return "Memory allocation error"; + case MMSYSERR_NOTSUPPORTED: return "Function isn't supported"; + case MMSYSERR_BADERRNUM: return "Error value out of range"; + case MMSYSERR_INVALFLAG: return "Invalid flag passed"; + case MMSYSERR_INVALPARAM: return "Invalid parameter passed"; + case MMSYSERR_LASTERROR: return "Last error in range"; + default: return "Unknown error"; + } +} + +#endif \ No newline at end of file diff --git a/bazaar/Media/audioSystem.h b/bazaar/Media/audioSystem.h new file mode 100644 index 000000000..1fc709a7a --- /dev/null +++ b/bazaar/Media/audioSystem.h @@ -0,0 +1,11 @@ +#ifndef _Media_audioSystem_h_ +#define _Media_audioSystem_h_ + +#define MAX_MAINVOLUME 10000 + +bool GetMainVolume(int &left, int &right); +int GetMainVolume(); +bool SetMainVolume(int left, int right); +bool SetMainVolume(int vol); + +#endif diff --git a/bazaar/Media/ffmpeg_base.h b/bazaar/Media/ffmpeg_base.h index dddf7c939..3a003229c 100644 --- a/bazaar/Media/ffmpeg_base.h +++ b/bazaar/Media/ffmpeg_base.h @@ -1,37 +1,37 @@ -#ifndef _Ffmpeg_Ffmpeg_h_ -#define _Ffmpeg_Ffmpeg_h_ - -#include - -extern "C" { - #include - #include - #include - #include - #include - #include - #include - #include - - #include - #include - - #include - - #include - - #include - - #include - #include -} - -#if defined(_MSC_VER) - extern AVRational myAVTIMEBASEQ; - #undef AV_TIME_BASE_Q - #define AV_TIME_BASE_Q myAVTIMEBASEQ - #define snprintf( buf, count, format, ... ) _snprintf_s( buf, 512, count, format, __VA_ARGS__ ) -#endif - -#endif - +#ifndef _Ffmpeg_Ffmpeg_h_ +#define _Ffmpeg_Ffmpeg_h_ + +#include + +extern "C" { + #include + #include + #include + #include + #include + #include + #include + #include + + #include + #include + + #include + + #include + + #include + + #include + #include +} + +#if defined(_MSC_VER) + extern AVRational myAVTIMEBASEQ; + #undef AV_TIME_BASE_Q + #define AV_TIME_BASE_Q myAVTIMEBASEQ + #define snprintf( buf, count, format, ... ) _snprintf_s( buf, 512, count, format, __VA_ARGS__ ) +#endif + +#endif + diff --git a/bazaar/Media/mediaplayer_in.h b/bazaar/Media/mediaplayer_in.h index 579a6a86e..a7c8af2bd 100644 --- a/bazaar/Media/mediaplayer_in.h +++ b/bazaar/Media/mediaplayer_in.h @@ -3,7 +3,7 @@ int video_thread(void *arg); int subtitle_thread(void *arg); -void sdl_audio_callback(void *opaque, Uint8 *stream, int len); +void sdl_audio_callback(void *opaque, uint16 *stream, int len); #define ALPHA_BLEND(a, oldp, newp, s)\ ((((oldp << s) * (255 - (a))) + (newp * (a))) / (255 << s)) diff --git a/bazaar/Media/mt.h b/bazaar/Media/mt.h index 2c81e8021..9f87c540f 100644 --- a/bazaar/Media/mt.h +++ b/bazaar/Media/mt.h @@ -3,46 +3,6 @@ // Classes thanks to U++ Forum supporters -// Safe mutex -template -class ScopedLock { -private: - MUTEX& mutex; - -private: - // The following constructor/operators are expilictly FORBIDDEN because they have no meaning - ScopedLock(void) {}; - ScopedLock(const ScopedLock&) {}; - ScopedLock& operator=(ScopedLock&) {return *this;}; - -public: - inline ScopedLock(MUTEX& mut) : mutex(mut) {mutex.lock();} - inline ~ScopedLock(void) {mutex.unLock();} -}; - -/* -class MyMutex { -private: - Mutex &mutex; - -private: - // The following constructor/operators are expilictly FORBIDDEN because they have no meaning - //MyMutex(void) {}; - MyMutex(const MyMutex&) {}; - MyMutex& operator=(MyMutex&) {return *this;}; - -public: - MyMutex(void) { - int kk = 33; - }; - inline MyMutex(Mutex& mut) : mutex(mut) { - mutex.Enter(); - } - inline ~MyMutex() { - mutex.Leave(); - } -}; -*/ // Safe atomic class AtomicVar { private: diff --git a/bazaar/Media/srcdoc.tpp/FfmpegInstall$en-us.tpp b/bazaar/Media/srcdoc.tpp/FfmpegInstall$en-us.tpp index da48ba82e..3d6881c82 100644 --- a/bazaar/Media/srcdoc.tpp/FfmpegInstall$en-us.tpp +++ b/bazaar/Media/srcdoc.tpp/FfmpegInstall$en-us.tpp @@ -9,14 +9,22 @@ installing instructions. Here are some useful links.]&] [s0;2 &] [s0; [* In Linux]&] [s0;2 &] -[s0; [2 Install ffmpeg `"`-dev`" packages:]&] +[s0; [2 Install ffmpeg packages:]&] +[s0;i150;O0; [2 libavcodec52 or libavcodec`-extra`-52]&] [s0;i150;O0; [2 libavcodec`-dev]&] -[s0;i150;O0; [2 libavutil`-dev]&] +[s0;i150;O0; [2 libavformat52 or libavformat`-extra`-52]&] [s0;i150;O0; [2 libavformat`-dev]&] +[s0;i150;O0; [2 libavdevice52 or libavdevice`-extra`-52]&] [s0;i150;O0; [2 libavdevice`-dev]&] +[s0;i150;O0; [2 libavfilter0 or libavfilter`-extra`-0]&] +[s0;i150;O0; [2 libavfilter`-dev]&] +[s0;i150;O0; [2 libavutil49 or libavutil`-extra`-49]&] +[s0;i150;O0; [2 libavutil`-dev]&] +[s0;i150;O0; [2 libpostproc51 or libpostproc`-extra`-51]&] +[s0;i150;O0; [2 libpostproc`-dev]&] +[s0;i150;O0; [2 libswscale0 or libswscale`-extra`-0]&] [s0;i150;O0; [2 libswscale`-dev]&] [s0;2 &] -[s0;2 &] [s0; [2 Other possible packages are:]&] [s0;i150;O0; [2 libdc1394`-22`-dev]&] [s0;i150;O0; [2 libfaad`-dev]&] @@ -41,15 +49,15 @@ safe (recommended!!), medium and hard ways.]&] [s0;2 &] [s0; [*2 Safe way]&] [s0;2 &] -[s0; [2 Download ][^https`:`/`/sourceforge`.net`/projects`/upp`/files`/GPL`-sources`/Ffmpeg`%20plugin`_LGPL`.7z`/download^2 f +[s0;# [2 Download ][^https`:`/`/sourceforge`.net`/projects`/upp`/files`/GPL`-sources`/Ffmpeg`%20plugin`_LGPL`.7z`/download^2 f fmpeg][2 and ][^https`:`/`/sourceforge`.net`/projects`/upp`/files`/GPL`-sources`/SDL`%20plugin`_LGPL`.7z`/download^2 S DL][2 from U`+`+ Sourceforge following the links. They include .dll, .lib, .a, .h and source code for recent versions.]&] -[s0;2 &] -[s0; [2 Copy the downloaded folders in upp folder. You will get a folder -structure like this:]&] -[s0; [2 drive:`\upp`\plugin`_LGPL`\ffmpeg]&] -[s0; [2 drive:`\upp`\plugin`_LGPL`\SDL]&] +[s0;#2 &] +[s0;# [2 Copy the downloaded folders in upp folder. You will get a +folder structure like this:]&] +[s0; [2 drive:`\upp`\uppsrc`\plugin`\ffmpeg]&] +[s0; [2 drive:`\upp`\uppsrc`\plugin`\SDL]&] [s0;2 &] [s0; [2 In Setup/Build Methods menu include the next folders:]&] [s0;%- &] @@ -57,17 +65,17 @@ structure like this:]&] :: [s0;= [2 INCLUDE directories]] :: [s0;= [2 LIB directories]] :: [s0; [2 drive:`\upp]] -:: [s0; [2 drive:`\upp`\plugin`_LGPL`\SDL`\include]&] -[s0; [2 drive:`\upp`\plugin`_LGPL`\ffmpeg`\include]] -:: [s0; [2 drive:`\upp`\plugin`_LGPL`\SDL`\lib]&] -[s0; [2 drive:`\upp`\plugin`_LGPL`\ffmpeg`\lib]]}}&] +:: [s0; [2 drive:`\upp`\uppsrc`\plugin`\SDL`\include]&] +[s0; [2 drive:`\upp`\uppsrc`\plugin`\ffmpeg`\include]] +:: [s0; [2 drive:`\upp`\uppsrc`\plugin`\SDL`\lib]&] +[s0; [2 drive:`\upp`\uppsrc`\plugin`\ffmpeg`\lib]]}}&] [s0;2 &] [s0; [2 In addition, MSC9 and MSC10 require an additional include folder]&] [s0;2 &] [ {{3211:6789 [s0;= [2 Compiler]] :: [s0;= [2 INCLUDE directories]] :: [s0; [2 MSC9]] -::|1 [s0; [2 drive:`\upp`\plugin`_LGPL`\ffmpeg`\include`_msc]] +::|1 [s0; [2 drive:`\upp`\uppsrc`\plugin`\ffmpeg`\include`_msc]] :: [s0; [2 MSC10]] :: [s0;%- ]}}&] [s0;2 &] diff --git a/bazaar/Media/srcdoc.tpp/Media$en-us.tpp b/bazaar/Media/srcdoc.tpp/Media$en-us.tpp index 0e7008228..00f8a3aa1 100644 --- a/bazaar/Media/srcdoc.tpp/Media$en-us.tpp +++ b/bazaar/Media/srcdoc.tpp/Media$en-us.tpp @@ -14,10 +14,10 @@ to install them are ][^topic`:`/`/Media`/srcdoc`/FfmpegInstall`$en`-us^2 here][2 [s0;i150;O0; [2 ffmpeg gives audio and video decoding and encoding.]&] [s0;2 &] [s0;2 &] -[s0; [^topic`:`/`/MediaPlayer`/srcdoc`/MediaPlayer`$en`-us^2 MediaPlayer -package][2 is a demo of MediaPlayer class capabilities.]&] +[s0; [^topic`:`/`/MediaPlayer`/srcdoc`/MediaPlayer`$en`-us^2 Media`_Demo +package][2 is a demo of Media classes capabilities.]&] [s0;2 &] -[s0; [2 So in summary for playing:]&] +[s0; [2 In summary for playing:]&] [s0;2 &] [s0;i150;O0; [2 ffmpeg opens the file (.avi, .mp3, ...)]&] [s0;i150;O0; [2 ffmpeg reads the codified data and converts it in uncompressed diff --git a/bazaar/Media/threads.cpp b/bazaar/Media/threads.cpp index c9f8baa8e..dac4d3bad 100644 --- a/bazaar/Media/threads.cpp +++ b/bazaar/Media/threads.cpp @@ -13,195 +13,204 @@ int decoderInterrupt_cb() { } // MediaFile streams retrieval and storage in packets -int MediaFile::DecoderThread(void *data) +void MediaFile::DecoderThread()//void *data) { - MediaFile &mf = *(MediaFile*)data; - mf.requestAbort = false; - mf.decodeThEnd = mf.decodeThEnded = false; - globalMediaFile = &mf; + //MediaFile &mf = *this;// *(MediaFile*)data; + requestAbort = false; + decodeThEnd = decodeThEnded = false; + globalMediaFile = this; url_set_interrupt_cb(decoderInterrupt_cb); int ret; for(;;) { - if (mf.requestAbort) // Abort request + if (requestAbort) // Abort request break; - if (mf.paused != mf.last_paused) { // Pausing - mf.last_paused = mf.paused; - if (mf.paused) - av_read_pause(mf.fileData); // Pauses a network based stream + if (paused != last_paused) { // Pausing + last_paused = paused; + if (paused) + av_read_pause(fileData);// Pauses a network based stream else - av_read_play(mf.fileData); + av_read_play(fileData); } - if (mf.seek_req) { // Somebody asked a seek - mf.decodeThEnd = false; - int64_t seek_target= mf.seek_pos; - int64_t seek_min = mf.seek_rel > 0 ? seek_target - mf.seek_rel + 2: INT64_MIN; - int64_t seek_max = mf.seek_rel < 0 ? seek_target - mf.seek_rel - 2: INT64_MAX; + if (seek_req) { // Somebody asked a seek + decodeThEnd = false; + int64_t seek_target= seek_pos; + int64_t seek_min = seek_rel > 0 ? seek_target - seek_rel + 2: INT64_MIN; + int64_t seek_max = seek_rel < 0 ? seek_target - seek_rel - 2: INT64_MAX; - if (0 > avformat_seek_file(mf.fileData, -1, seek_min, seek_target, seek_max, mf.seek_flags)) - mf.SetError(Format("%s: error while seeking", mf.GetFileName())); + if (0 > avformat_seek_file(fileData, -1, seek_min, seek_target, seek_max, seek_flags)) + SetError(Format("%s: error while seeking", GetFileName())); else { - if (mf.idAudio >= 0) { - mf.audioq.Flush(); - mf.audioq.Put(&mf.flush_pkt, &mf.flush_pkt); + if (idAudio >= 0) { + audioq.Flush(); + audioq.Put(&flush_pkt, &flush_pkt); } - if (mf.idSubtitle >= 0) { - mf.subtitleq.Flush(); - mf.subtitleq.Put(&mf.flush_pkt, &mf.flush_pkt); + if (idSubtitle >= 0) { + subtitleq.Flush(); + subtitleq.Put(&flush_pkt, &flush_pkt); } - if (mf.idVideo >= 0) { - mf.videoq.Flush(); - mf.videoq.Put(&mf.flush_pkt, &mf.flush_pkt); + if (idVideo >= 0) { + videoq.Flush(); + videoq.Put(&flush_pkt, &flush_pkt); } } - mf.seek_req = false; + seek_req = false; } // If any of the queues is full, it waits - if (mf.audioq.IsFull() || mf.videoq.IsFull() || mf.subtitleq.IsFull()) { + if (audioq.IsFull() || videoq.IsFull() || subtitleq.IsFull()) { Sleep(10); continue; } AVPacket pkt; - if(url_feof(mf.fileData->pb)) { + if(url_feof(fileData->pb)) { /*av_init_packet(&pkt); pkt.data = NULL; pkt.size = 0; - pkt.stream_index = mf.idVideo; - mf.videoq.Put(&pkt, &mf.flush_pkt); + pkt.stream_index = idVideo; + videoq.Put(&pkt, &flush_pkt); continue;*/ break; } - ret = av_read_frame(mf.fileData, &pkt); + ret = av_read_frame(fileData, &pkt); if (ret < 0) { - if (ret != AVERROR_EOF && url_ferror(mf.fileData->pb) == 0) { + if (ret != AVERROR_EOF && url_ferror(fileData->pb) == 0) { Sleep(100); // Wait for user event continue; } else break; } - if (pkt.stream_index == mf.idAudio) - mf.audioq.Put(&pkt, &mf.flush_pkt); - else if (pkt.stream_index == mf.idVideo) - mf.videoq.Put(&pkt, &mf.flush_pkt); - else if (pkt.stream_index == mf.idSubtitle) - mf.subtitleq.Put(&pkt, &mf.flush_pkt); + if (pkt.stream_index == idAudio) + audioq.Put(&pkt, &flush_pkt); + else if (pkt.stream_index == idVideo) + videoq.Put(&pkt, &flush_pkt); + else if (pkt.stream_index == idSubtitle) + subtitleq.Put(&pkt, &flush_pkt); else av_free_packet(&pkt); } - mf.decodeThEnd = true; // Ask PaquetQeue to stop, so all threads end + decodeThEnd = true; // Ask PaquetQeue to stop, so all threads end - while (!mf.requestAbort && !(mf.audioThEnd && mf.videoThEnd && mf.subtitleThEnd))// Wait until end + while (!requestAbort && !(audioThEnd && videoThEnd && subtitleThEnd))// Wait until end Sleep(100); // Close each stream - if (mf.idAudio >= 0) - mf.StreamClose(mf.idAudio); - if (mf.idVideo >= 0) - mf.StreamClose(mf.idVideo); - if (mf.idSubtitle >= 0) - mf.StreamClose(mf.idSubtitle); + if (idAudio >= 0) + StreamClose(idAudio); + if (idVideo >= 0) + StreamClose(idVideo); + if (idSubtitle >= 0) + StreamClose(idSubtitle); url_set_interrupt_cb(NULL); - mf.decodeThEnded = true; + decodeThEnded = true; - return 0; + //return 0; } -int MediaFile::VideoThread(void *data) +void MediaFile::VideoThread() //void *data) { - MediaFile &mf = *(MediaFile *)data; + //MediaFile &mf = *this; // *(MediaFile *)data; AVFrame *frame= avcodec_alloc_frame(); - mf.videoThEnd = false; + videoThEnd = false; for(;;) { - while (mf.paused && !mf.videoq.IsAbort()) + while (paused && !videoq.IsAbort()) Sleep(10); AVPacket pkt; - if (mf.videoq.Get(&pkt, mf.decodeThEnd) <= 0) // Gets a video packet + if (videoq.Get(&pkt, decodeThEnd) <= 0) // Gets a video packet break; - if(pkt.data == mf.flush_pkt.data) - avcodec_flush_buffers(mf.videoStream->codec); + if(pkt.data == flush_pkt.data) + avcodec_flush_buffers(videoStream->codec); else { - mf.videoStream->codec->reordered_opaque = pkt.pts; + videoStream->codec->reordered_opaque = pkt.pts; int got_picture; // It does not check for errors - int len1 = avcodec_decode_video2(mf.videoStream->codec, frame, &got_picture, &pkt); +#if (((LIBAVCODEC_VERSION_MAJOR <= 52) && (LIBAVCODEC_VERSION_MINOR <= 20)) || UBUNTU_TRICK) + int len1 = avcodec_decode_video(videoStream->codec, frame, &got_picture, pkt.data, pkt.size); +#else + int len1 = avcodec_decode_video2(videoStream->codec, frame, &got_picture, &pkt); +#endif + double pts; - if((mf.decoder_reorder_pts || pkt.dts == AV_NOPTS_VALUE) && + if((decoder_reorder_pts || pkt.dts == AV_NOPTS_VALUE) && (frame->reordered_opaque != AV_NOPTS_VALUE)) pts = double(frame->reordered_opaque); else if(pkt.dts != AV_NOPTS_VALUE) pts = double(pkt.dts); else pts = 0; - pts *= av_q2d(mf.videoStream->time_base); + pts *= av_q2d(videoStream->time_base); if (got_picture) { // Compute video clock double frame_delay; if (pts != 0) - mf.video_clock = pts; // Update video clock with pts, if present + video_clock = pts; // Update video clock with pts, if present // Update video clock for next frame - frame_delay = av_q2d(mf.videoStream->codec->time_base); + frame_delay = av_q2d(videoStream->codec->time_base); // For MPEG2, the frame can be repeated, so we update the clock accordingly frame_delay += frame->repeat_pict * (frame_delay * 0.5); - mf.video_clock += frame_delay; + video_clock += frame_delay; - if (!mf.queue_picture(frame, pts)) + if (!queue_picture(frame, pts)) break; } av_free_packet(&pkt); - if (mf.step) - mf.stream_pause(); + if (step) + stream_pause(); } } av_free(frame); - mf.videoThEnd = true; - return 0; + videoThEnd = true; + //return 0; } -int MediaFile::SubtitleThread(void *data) +void MediaFile::SubtitleThread() //void *data) { - MediaFile &mf = *(MediaFile *)data; - mf.subtitleThEnd = false; + //MediaFile &mf = *this; // *(MediaFile *)data; + subtitleThEnd = false; for(;;) { - while (mf.paused && !mf.subtitleq.IsAbort()) + while (paused && !subtitleq.IsAbort()) Sleep(10); AVPacket pkt; - if (mf.subtitleq.Get(&pkt, 1) < 0) + if (subtitleq.Get(&pkt, 1) < 0) break; - if(pkt.data == mf.flush_pkt.data){ - avcodec_flush_buffers(mf.subtitleStream->codec); + if(pkt.data == flush_pkt.data){ + avcodec_flush_buffers(subtitleStream->codec); continue; } - SDL_LockMutex(mf.subpq_mutex); - while (mf.subpq_size >= SUBPICTURE_QUEUE_SIZE && !mf.subtitleq.IsAbort()) - SDL_CondWait(mf.subpq_cond, mf.subpq_mutex); - - SDL_UnlockMutex(mf.subpq_mutex); + INTERLOCKED_(subpq_mutex) { + while (subpq_size >= SUBPICTURE_QUEUE_SIZE && !subtitleq.IsAbort()) + subpq_cond.Wait(subpq_mutex); + } - if (mf.subtitleq.IsAbort()) - return 0; + if (subtitleq.IsAbort()) + return ;//0; - SubPicture *sp = &mf.subpq[mf.subpq_windex]; + SubPicture *sp = &subpq[subpq_windex]; double pts = 0; if (pkt.pts != AV_NOPTS_VALUE) - pts = av_q2d(mf.subtitleStream->time_base)*pkt.pts; + pts = av_q2d(subtitleStream->time_base)*pkt.pts; int got_subtitle; // It does not check for errors - int len1 = avcodec_decode_subtitle2(mf.subtitleStream->codec, &sp->sub, &got_subtitle, +#if (((LIBAVCODEC_VERSION_MAJOR <= 52) && (LIBAVCODEC_VERSION_MINOR <= 20)) || UBUNTU_TRICK) + int len1 = avcodec_decode_subtitle(subtitleStream->codec, &sp->sub, &got_subtitle, + pkt.data, pkt.size); +#else + int len1 = avcodec_decode_subtitle2(subtitleStream->codec, &sp->sub, &got_subtitle, &pkt); +#endif if (got_subtitle && sp->sub.format == 0) { sp->pts = pts; @@ -215,16 +224,16 @@ int MediaFile::SubtitleThread(void *data) YUVA_OUT((uint32_t*)sp->sub.rects[i]->pict.data[1] + j, y, u, v, a); } } - if (++mf.subpq_windex == SUBPICTURE_QUEUE_SIZE) // New picture is added - mf.subpq_windex = 0; - SDL_LockMutex(mf.subpq_mutex); - mf.subpq_size++; - SDL_UnlockMutex(mf.subpq_mutex); + if (++subpq_windex == SUBPICTURE_QUEUE_SIZE) // New picture is added + subpq_windex = 0; + INTERLOCKED_(subpq_mutex) { + subpq_size++; + } } av_free_packet(&pkt); } - mf.subtitleThEnd = true; - return 0; + subtitleThEnd = true; + //return 0; } // Prepare a new audio buffer @@ -238,11 +247,11 @@ void sdl_audio_callback(void *data, Uint8 *stream, int len) if (unsigned(mf.audio_buf_index) >= mf.audio_buf_size) { double pts; int audio_size = mf.audio_decode_frame(&pts); - if (audio_size < 0) { + if (audio_size < 0) { // If error, it outputs silence mf.audio_buf = mf.audio_buf1; mf.audio_buf_size = 1024; - memset(mf.audio_buf, 0, mf.audio_buf_size); // If error, it outputs silence - } else if (audio_size == 0) + memset(mf.audio_buf, 0, mf.audio_buf_size); + } else if (audio_size == 0) // Audio is ended mf.audioThEnd = true; else { if (mf.showAudio) @@ -252,11 +261,19 @@ void sdl_audio_callback(void *data, Uint8 *stream, int len) } mf.audio_buf_index = 0; } - int len1 = mf.GetAudioOutputBufferSize(); - if (len1 > len) - len1 = len; - memcpy(stream, (uint8_t *)mf.audio_buf + mf.audio_buf_index, len1); - len -= len1; + int len1 = min(len, mf.GetAudioOutputBufferSize()); + //memcpy(stream, (uint8_t *)mf.audio_buf + mf.audio_buf_index, len1); + int16 *audioStr = (int16 *)(mf.audio_buf + mf.audio_buf_index); + int16 *destStream = (int16 *)stream; + for (int i = 0; i < len1/2; ++i) { + double val = audioStr[i]*mf.audioFactor/1000.; // Meter tambien un "WhenAudioFrame" + if (val < -32767+2) // To avoid audio saturation. A bit less than the limit + val = -32767+2; + else if (val > 32768-2) + val = 32768-2; + destStream[i] = int16(val); + } + len -= len1; stream += len1; mf.audio_buf_index += len1; } diff --git a/bazaar/Media/ubuntu.cpp b/bazaar/Media/ubuntu.cpp index b9ab8abe4..5f46c1210 100644 --- a/bazaar/Media/ubuntu.cpp +++ b/bazaar/Media/ubuntu.cpp @@ -1,146 +1,148 @@ -#include - -using namespace Upp; - -#include -#include "utility.h" - -int av_strerror(int errnum, char *errbuf, size_t errbuf_size) -{ - int ret = 0; - const char *errstr = NULL; - - switch (errnum) { - case AVERROR_EOF: errstr = "End of file"; break; - case AVERROR_INVALIDDATA: errstr = "Invalid data found when processing input"; break; - case AVERROR_NUMEXPECTED: errstr = "Number syntax expected in filename"; break; - case AVERROR_PATCHWELCOME: errstr = "Not yet implemented in FFmpeg, patches welcome"; break; - case AVERROR_DEMUXER_NOT_FOUND: errstr = "Demuxer not found"; break; - case AVERROR_MUXER_NOT_FOUND: errstr = "Muxer not found"; break; - case AVERROR_DECODER_NOT_FOUND: errstr = "Decoder not found"; break; - case AVERROR_ENCODER_NOT_FOUND: errstr = "Encoder not found"; break; - case AVERROR_PROTOCOL_NOT_FOUND:errstr = "Protocol not found"; break; - case AVERROR_FILTER_NOT_FOUND: errstr = "Filter not found"; break; - case AVERROR_BSF_NOT_FOUND: errstr = "Bitstream filter not found"; break; - case AVERROR_STREAM_NOT_FOUND: errstr = "Stream not found"; break; - } - - if (errstr) { - av_strlcpy(errbuf, errstr, errbuf_size); - } else { -#if HAVE_STRERROR_R - ret = strerror_r(AVUNERROR(errnum), errbuf, errbuf_size); -#else - ret = -1; -#endif - if (ret < 0) - snprintf(errbuf, errbuf_size, "Error number %d occurred", errnum); - } - - return ret; -} - -void av_free_packet(AVPacket *pkt) -{ - if (pkt) { - if (pkt->destruct) pkt->destruct(pkt); - pkt->data = NULL; pkt->size = 0; - } -} - -// XXX: suppress the packet queue -static void flush_packet_queue(AVFormatContext *s) -{ - AVPacketList *pktl; - - for(;;) { - pktl = s->packet_buffer; - if (!pktl) - break; - s->packet_buffer = pktl->next; - av_free_packet(&pktl->pkt); - av_free(pktl); - } - while(s->raw_packet_buffer){ - pktl = s->raw_packet_buffer; - s->raw_packet_buffer = pktl->next; - av_free_packet(&pktl->pkt); - av_free(pktl); - } - s->packet_buffer_end= - s->raw_packet_buffer_end= NULL; - s->raw_packet_buffer_remaining_size = RAW_PACKET_BUFFER_SIZE; -} - -// Flush the frame reader. -void ff_read_frame_flush(AVFormatContext *s) -{ - AVStream *st; - int j; - - flush_packet_queue(s); - - s->cur_st = NULL; - - // for each stream, reset read state - for(unsigned i = 0; i < s->nb_streams; i++) { - st = s->streams[i]; - - if (st->parser) { - av_parser_close(st->parser); - st->parser = NULL; - av_free_packet(&st->cur_pkt); - } - st->last_IP_pts = AV_NOPTS_VALUE; - st->cur_dts = AV_NOPTS_VALUE; // we set the current DTS to an unspecified origin - st->reference_dts = AV_NOPTS_VALUE; - // fail safe - st->cur_ptr = NULL; - st->cur_len = 0; - - st->probe_packets = MAX_PROBE_PACKETS; - - for(j=0; jpts_buffer[j]= AV_NOPTS_VALUE; - } -} - -int avformat_seek_file(AVFormatContext *s, int stream_index, int64_t min_ts, int64_t ts, int64_t max_ts, int flags) -{ - if(min_ts > ts || max_ts < ts) - return -1; - - ff_read_frame_flush(s); - - if (s->iformat->read_seek2) - return s->iformat->read_seek2(s, stream_index, min_ts, ts, max_ts, flags); - - if(s->iformat->read_timestamp){ - //try to seek via read_timestamp() - } - - //Fallback to old API if new is not implemented but old is - //Note the old has somewat different sematics - if(s->iformat->read_seek || 1) - return av_seek_frame(s, stream_index, ts, flags | (ts - min_ts > max_ts - ts ? AVSEEK_FLAG_BACKWARD : 0)); - - // try some generic seek like av_seek_frame_generic() but with new ts semantics -} - -void avsubtitle_free(AVSubtitle *sub) -{ - for (unsigned i = 0; i < sub->num_rects; i++) - { - av_freep(&sub->rects[i]->pict.data[0]); - av_freep(&sub->rects[i]->pict.data[1]); - av_freep(&sub->rects[i]->pict.data[2]); - av_freep(&sub->rects[i]->pict.data[3]); - av_freep(&sub->rects[i]->text); - av_freep(&sub->rects[i]->ass); - av_freep(&sub->rects[i]); - } - - av_freep(&sub->rects); - - memset(sub, 0, sizeof(AVSubtitle)); -} \ No newline at end of file +#include + +using namespace Upp; + +#include +#include "utility.h" + + +int av_strerror(int errnum, char *errbuf, size_t errbuf_size) +{ + int ret = 0; + const char *errstr = NULL; + + switch (errnum) { + case AVERROR_EOF: errstr = "End of file"; break; + case AVERROR_INVALIDDATA: errstr = "Invalid data found when processing input"; break; + case AVERROR_NUMEXPECTED: errstr = "Number syntax expected in filename"; break; + case AVERROR_PATCHWELCOME: errstr = "Not yet implemented in FFmpeg, patches welcome"; break; + case AVERROR_DEMUXER_NOT_FOUND: errstr = "Demuxer not found"; break; + case AVERROR_MUXER_NOT_FOUND: errstr = "Muxer not found"; break; + case AVERROR_DECODER_NOT_FOUND: errstr = "Decoder not found"; break; + case AVERROR_ENCODER_NOT_FOUND: errstr = "Encoder not found"; break; + case AVERROR_PROTOCOL_NOT_FOUND:errstr = "Protocol not found"; break; + case AVERROR_FILTER_NOT_FOUND: errstr = "Filter not found"; break; + case AVERROR_BSF_NOT_FOUND: errstr = "Bitstream filter not found"; break; + case AVERROR_STREAM_NOT_FOUND: errstr = "Stream not found"; break; + } + + if (errstr) { + av_strlcpy(errbuf, errstr, errbuf_size); + } else { +#if HAVE_STRERROR_R + ret = strerror_r(AVUNERROR(errnum), errbuf, errbuf_size); +#else + ret = -1; +#endif + if (ret < 0) + snprintf(errbuf, errbuf_size, "Error number %d occurred", errnum); + } + + return ret; +} + +void av_free_packet(AVPacket *pkt) +{ + if (pkt) { + if (pkt->destruct) pkt->destruct(pkt); + pkt->data = NULL; pkt->size = 0; + } +} + +// XXX: suppress the packet queue +static void flush_packet_queue(AVFormatContext *s) +{ + AVPacketList *pktl; + + for(;;) { + pktl = s->packet_buffer; + if (!pktl) + break; + s->packet_buffer = pktl->next; + av_free_packet(&pktl->pkt); + av_free(pktl); + } + while(s->raw_packet_buffer){ + pktl = s->raw_packet_buffer; + s->raw_packet_buffer = pktl->next; + av_free_packet(&pktl->pkt); + av_free(pktl); + } + s->packet_buffer_end= + s->raw_packet_buffer_end= NULL; + s->raw_packet_buffer_remaining_size = RAW_PACKET_BUFFER_SIZE; +} + +// Flush the frame reader. +void ff_read_frame_flush(AVFormatContext *s) +{ + AVStream *st; + int j; + + flush_packet_queue(s); + + s->cur_st = NULL; + + // for each stream, reset read state + for(unsigned i = 0; i < s->nb_streams; i++) { + st = s->streams[i]; + + if (st->parser) { + av_parser_close(st->parser); + st->parser = NULL; + av_free_packet(&st->cur_pkt); + } + st->last_IP_pts = AV_NOPTS_VALUE; + st->cur_dts = AV_NOPTS_VALUE; // we set the current DTS to an unspecified origin + st->reference_dts = AV_NOPTS_VALUE; + // fail safe + st->cur_ptr = NULL; + st->cur_len = 0; + + st->probe_packets = MAX_PROBE_PACKETS; + + for(j=0; jpts_buffer[j]= AV_NOPTS_VALUE; + } +} + +int avformat_seek_file(AVFormatContext *s, int stream_index, int64_t min_ts, int64_t ts, int64_t max_ts, int flags) +{ + if(min_ts > ts || max_ts < ts) + return -1; + + ff_read_frame_flush(s); + + if (s->iformat->read_seek2) + return s->iformat->read_seek2(s, stream_index, min_ts, ts, max_ts, flags); + + if(s->iformat->read_timestamp){ + //try to seek via read_timestamp() + } + + //Fallback to old API if new is not implemented but old is + //Note the old has somewat different sematics + if(s->iformat->read_seek || 1) + return av_seek_frame(s, stream_index, ts, flags | (ts - min_ts > max_ts - ts ? AVSEEK_FLAG_BACKWARD : 0)); + + // try some generic seek like av_seek_frame_generic() but with new ts semantics +} + +void avsubtitle_free(AVSubtitle *sub) +{ + for (unsigned i = 0; i < sub->num_rects; i++) + { + av_freep(&sub->rects[i]->pict.data[0]); + av_freep(&sub->rects[i]->pict.data[1]); + av_freep(&sub->rects[i]->pict.data[2]); + av_freep(&sub->rects[i]->pict.data[3]); + av_freep(&sub->rects[i]->text); + av_freep(&sub->rects[i]->ass); + av_freep(&sub->rects[i]); + } + + av_freep(&sub->rects); + + memset(sub, 0, sizeof(AVSubtitle)); +} + diff --git a/bazaar/Media/utility.cpp b/bazaar/Media/utility.cpp index c1adafacc..f3718580a 100644 --- a/bazaar/Media/utility.cpp +++ b/bazaar/Media/utility.cpp @@ -3,6 +3,7 @@ using namespace Upp; #include +//#include #include "utility.h" @@ -17,7 +18,9 @@ int64 GetUSec() { gettimeofday(&tv, &tz); return int64(tv.tv_sec)*1000000 + tv.tv_usec; } + #else + int64 GetUSec() { LARGE_INTEGER ticksPerSec; LARGE_INTEGER tick; @@ -26,4 +29,5 @@ int64 GetUSec() { QueryPerformanceCounter(&tick); return tick.QuadPart/(ticksPerSec.QuadPart/1000000); } + #endif \ No newline at end of file diff --git a/bazaar/Media/utility.h b/bazaar/Media/utility.h index 1aa892cea..4ceaece30 100644 --- a/bazaar/Media/utility.h +++ b/bazaar/Media/utility.h @@ -1,6 +1,7 @@ #ifndef _Media_utility_h_ #define _Media_utility_h_ +#include "audioSystem.h" String GetTags(AVFormatContext *fileData); String GetAvError(int err); @@ -25,5 +26,6 @@ inline int compute_mod(int a, int b) } int64 GetUSec(); - + + #endif