25#include <scolPlugin.h>
28#include <boost/lexical_cast.hpp>
33#define QUEUE_BUFFER_SIZE 100
34#define QUEUE_BUFFERING_RATIO 10
39#if __STDC_VERSION__ < 199901L
41#define av_err2str(errnum) \
42 av_make_error_string( \
43 boost::array<char, AV_ERROR_MAX_STRING_SIZE>().c_array(), \
44 AV_ERROR_MAX_STRING_SIZE, \
55std::list<MediaPlayer*> MediaPlayer::players;
57bool MediaPlayer::globallyPaused =
false;
72 avformat_network_init();
73 MMechostr(MSKDEBUG, avformat_configuration());
78 avformat_network_deinit();
83 if (pause && !globallyPaused)
85 for (
auto it = players.begin(); it != players.end(); it++)
88 globallyPaused =
true;
90 else if (!pause && globallyPaused)
92 for (
auto it = players.begin(); it != players.end(); it++)
95 globallyPaused =
false;
101 for (
auto it = players.begin(); it != players.end(); it++)
121 mFinalW(0), mFinalH(0),
122 mSourceW(0), mSourceH(0),
129 mVideoPts(AV_NOPTS_VALUE),
130 mSeekPts(AV_NOPTS_VALUE),
131 mSeekRequested(false),
132 mSeekInProgressAudio(false),
133 mSeekInProgressVideo(false),
134 mSeekCompletedAudio(true),
143 mOutChannelLayout(0),
144 mOutSampleFormat(AV_SAMPLE_FMT_NONE),
148 mFrame = av_frame_alloc();
151 throw std::runtime_error(
"Couldn't allocate frame");
153 mVideoBuffer = av_frame_alloc();
154 if (mVideoBuffer == NULL)
155 throw std::runtime_error(
"Couldn't allocate frame");
158 players.push_back(
this);
163 if (mOpenThread.joinable())
168 av_frame_free(&mFrame);
170 if ((mVideoBuffer != 0) && (mVideoBuffer->data != 0))
171 avpicture_free((AVPicture*)mVideoBuffer);
173 av_frame_free(&mVideoBuffer);
176 mFrameBuffer.release();
177 mFrameRetrieveBuffer.release();
179 players.remove(
this);
182void MediaPlayer::OpenFileThread(
const std::string path)
188 mFilePtr = fopen(path.c_str(),
"rb");
189 if (mFilePtr == NULL)
192 MMechostr(MSKRUNTIME,
"Could not open file %s", path.c_str());
201 mIoContext = avio_alloc_context(NULL, 0, 0,
this, FileRead, FileWrite, FileSeek);
202 if (mIoContext == NULL)
205 MMechostr(MSKRUNTIME,
"Could not allocate AVIOContext for %s", path.c_str());
212 mContext = avformat_alloc_context();
213 if (mContext == NULL)
216 MMechostr(MSKRUNTIME,
"Could not allocate AVFormatContext for %s", path.c_str());
226 mContext->pb = mIoContext;
227 OpenUrlThread(path,
false);
241 if (mOpenThread.joinable())
244 mOpenThread = boost::thread(&MediaPlayer::OpenFileThread,
this, path);
247void MediaPlayer::OpenUrlThread(std::string url,
bool close)
254 AVDictionary *stream_opts = 0;
255 av_dict_set(&stream_opts,
"rw_timeout",
"8000000", 0);
257 if ((url.compare(0, 2,
"//") == 0) || (url.compare(0, 2,
"\\") == 0) || (url.compare(0, 4,
"rtp:") == 0) || (url.compare(0, 4,
"udp:") == 0) || (url.compare(0, 4,
"tcp:") == 0) || (url.compare(0, 5,
"http:") == 0) || (url.compare(0, 6,
"https:") == 0))
259 av_dict_set(&stream_opts,
"timeout",
"8000000", 0);
262 else if (url.compare(0, 5,
"rtsp:") == 0)
264 av_dict_set(&stream_opts,
"stimeout",
"8000000", 0);
270 int ret = avformat_open_input(&mContext, url.c_str(), NULL, &stream_opts);
271 av_dict_free(&stream_opts);
276 MMechostr(MSKRUNTIME,
"Open input error: %s",
av_err2str(ret));
283 if (avformat_find_stream_info(mContext, NULL) < 0)
286 MMechostr(MSKRUNTIME,
"Could not find stream info for %s",
av_err2str(ret));
302 MMechostr(MSKRUNTIME,
"File %s contains neither video or audio.", url.c_str());
323 if (mOpenThread.joinable())
326 mOpenThread = boost::thread(&MediaPlayer::OpenUrlThread,
this, url,
true);
333 avformat_close_input(&mContext);
337 if (mFilePtr != NULL)
373 return GetStreamDuration(mVideoStream);
375 return GetStreamDuration(mAudioStream);
382 if (mContext == NULL)
383 throw std::runtime_error(
"No open file or stream");
386 if (mContext->pb != NULL)
387 return mContext->pb->seekable != 0;
406 throw std::runtime_error(
"No open video stream");
417 throw std::runtime_error(
"No open video stream");
422 if ((width == mUserW) && (height == mUserH))
425 boost::mutex::scoped_lock l(mSizeMutex);
434 uint64_t channelLayout = 0;
435 AVSampleFormat ffmpegFormat = AV_SAMPLE_FMT_NONE;
440 channelLayout = AV_CH_LAYOUT_MONO;
441 ffmpegFormat = AV_SAMPLE_FMT_U8;
444 channelLayout = AV_CH_LAYOUT_STEREO;
445 ffmpegFormat = AV_SAMPLE_FMT_U8;
448 channelLayout = AV_CH_LAYOUT_MONO;
449 ffmpegFormat = AV_SAMPLE_FMT_S16;
452 channelLayout = AV_CH_LAYOUT_STEREO;
453 ffmpegFormat = AV_SAMPLE_FMT_S16;
456 throw std::runtime_error(std::string(
"Unsupported format: ") + boost::lexical_cast<std::string>(format));
464 boost::mutex::scoped_lock l(mAudioMutex);
466 if (av_sample_fmt_is_planar(format))
467 throw std::logic_error(
"Planar formats are not supported");
469 if ((mOutSampleFormat == format) && (mOutSampleRate == sampleRate) && (mOutChannelLayout == channelLayout))
475 AllocResampler(channelLayout, format, sampleRate, mAudioCtx);
482 mOutSampleFormat = format;
483 mOutSampleRate = sampleRate;
484 mOutChannelLayout = channelLayout;
490 throw std::logic_error(
"No open video stream");
501 mDecodingThread = boost::thread(&MediaPlayer::DecodingThread,
this);
502 mPauseCond.notify_all();
507 av_read_play(mContext);
510 mPauseCond.notify_all();
517 throw std::logic_error(
"No open video stream");
521 boost::mutex::scoped_lock l(mVideoMutex);
525 throw std::runtime_error(
"Stream doesn't have pause support");
527 mSystemClock.Pause();
537 if (mPaused || mSystemClock.IsPaused())
540 mPauseCond.notify_all();
543 if (mDecodingThread.joinable())
548 mDecodingThread.join();
564 throw std::logic_error(
"No open video stream");
572 time = std::max(0L, time);
574 if (streamDuration != -1)
575 time = std::min(streamDuration, time);
580 mSeekInProgressVideo =
true;
582 mSeekInProgressAudio =
true;
584 mSeekRequested =
true;
587 mSystemClock.Reset(time);
592 return (
long)mSystemClock.Get();
597 if (!
IsReady() || !mUpdated || mFrameBuffer.empty())
606 boost::mutex::scoped_lock l(mVideoMutex);
607 mFrameBuffer.copyTo(mFrameRetrieveBuffer);
612 cv::resize(mFrameRetrieveBuffer, imgdest, imgdest.size(), 0, 0, cv::INTER_LINEAR);
614 catch (cv::Exception& e)
616 MMechostr(MSKDEBUG,
"MediaPlayer::GetFrame error %s\n", e.what());
626 if (!
IsReady() || !mUpdated || imgdest.empty())
630 boost::mutex::scoped_lock l(mVideoMutex);
631 mFrameBuffer.copyTo(mFrameRetrieveBuffer);
636 cv::resize(mFrameRetrieveBuffer, imgdest, imgdest.size(), 0, 0, cv::INTER_LINEAR);
638 catch (cv::Exception& e)
640 MMechostr(MSKDEBUG,
"MediaPlayer::GetFrame error %s\n", e.what());
650 if (!
IsReady() || !mUpdated || mFrameBuffer.empty())
654 boost::mutex::scoped_lock l(mVideoMutex);
655 mFrameBuffer.copyTo(mFrameRetrieveBuffer);
659 return mFrameRetrieveBuffer;
664 if (mContext == NULL)
665 throw std::logic_error(
"No opened video file");
667 streamIndex = GetActualStreamIndex(streamIndex, AVMEDIA_TYPE_VIDEO);
669 int stream = SetStream(AVMEDIA_TYPE_VIDEO, streamIndex);
673 mVideoStream = stream;
674 mVideoCtx = mContext->streams[stream]->codec;
678 ComputeSize(mVideoCtx->width, mVideoCtx->height);
680 catch (std::exception&)
692 catch (std::exception& e)
694 MMechostr(MSKRUNTIME,
"No audio : %s\n", e.what());
705 if (mContext == NULL)
706 throw std::logic_error(
"No opened video file");
708 streamIndex = GetActualStreamIndex(streamIndex, AVMEDIA_TYPE_AUDIO);
710 int stream = SetStream(AVMEDIA_TYPE_AUDIO, streamIndex);
711 AVCodecContext* decContext = mContext->streams[stream]->codec;
713 if (!decContext->channel_layout)
714 decContext->channel_layout = av_get_default_channel_layout(decContext->channels);
717 if ((mOutChannelLayout == 0) || (mOutSampleFormat == AV_SAMPLE_FMT_NONE) || (mOutSampleRate == 0))
719 mOutChannelLayout = decContext->channel_layout;
720 mOutSampleFormat = decContext->sample_fmt;
721 mOutSampleRate = decContext->sample_rate;
732 AllocResampler(mOutChannelLayout, mOutSampleFormat, mOutSampleRate, decContext);
736 avcodec_close(decContext);
741 avcodec_close(mAudioCtx);
743 mAudioStream = stream;
744 mAudioCtx = decContext;
757int MediaPlayer::SetStream(AVMediaType type,
int index)
759 AVCodec* decoder = NULL;
760 AVCodecContext* decContext = NULL;
763 int relatedStream = -1;
764 if ((type == AVMEDIA_TYPE_AUDIO) || (type == AVMEDIA_TYPE_SUBTITLE))
765 relatedStream = mVideoStream;
767 int stream = av_find_best_stream(mContext, type, index, relatedStream, NULL, 0);
769 throw std::runtime_error(
"No stream of type " + std::string(av_get_media_type_string(type)));
772 if (stream == mAudioStream || stream == mVideoStream)
773 throw std::runtime_error(
"Stream already selected");
775 decContext = mContext->streams[stream]->codec;
777 decoder = avcodec_find_decoder(decContext->codec_id);
779 throw std::runtime_error(
"Codec not found : " + std::string(mContext->streams[stream]->codec->codec->name));
781 int ret = avcodec_open2(decContext, decoder, NULL);
783 throw std::runtime_error(
"FFmpeg couldn't open context for codec " + std::string(decoder->name));
790 std::vector<std::string> streamList;
793 if (mContext == NULL)
796 for (
unsigned int i = 0; i < mContext->nb_streams; i++)
798 AVStream* stream = mContext->streams[i];
799 if (stream->codec->codec_type != type)
802 std::string description(
"");
805 AVDictionaryEntry* title = av_dict_get(stream->metadata,
"title", NULL, 0);
807 description += std::string(title->value) +
" ";
810 if (type == AVMEDIA_TYPE_AUDIO)
812 AVDictionaryEntry* lang = av_dict_get(stream->metadata,
"language", NULL, 0);
814 description += std::string(
"Language: ") + lang->value;
817 if (description.empty())
818 description =
"(no info)";
820 std::stringstream desc;
821 desc << nbStreams <<
". " << description;
822 streamList.push_back(desc.str());
829int MediaPlayer::GetActualStreamIndex(
int streamIndex, AVMediaType streamType)
831 if (mContext == NULL)
832 throw std::logic_error(
"No open video file");
834 if (streamIndex < -1)
835 throw std::logic_error(
"Wrong stream index");
840 for (
unsigned int i = 0; i < mContext->nb_streams; i++)
842 if (mContext->streams[i]->codec->codec_type == streamType)
850 throw std::logic_error(
"Stream not found");
853long MediaPlayer::GetStreamDuration(
int index)
858 if (mContext->streams[index]->duration != AV_NOPTS_VALUE)
859 return (
long)av_rescale_q(mContext->streams[index]->duration, mContext->streams[index]->time_base,
MediaPlayer::TIME_BASE);
860 else if (mContext->duration != AV_NOPTS_VALUE)
866void MediaPlayer::DecodingThread()
869 mVideoThread = boost::thread(&MediaPlayer::VideoThread,
this);
871 mAudioThread = boost::thread(&MediaPlayer::AudioThread,
this);
873 bool eofReached =
false;
874 bool keepGoing =
true;
876 bool waitBuffer = !mIsLocal;
880 while (!mStopped && keepGoing)
884 if (length != -1 && !mLoop && !waitBuffer)
889 if (waitBuffer || mSystemClock.IsPaused())
891 if ((mSystemClock.IsPaused() && !mPaused && (!waitBuffer || eofReached))
896 mSystemClock.Resume();
897 mAudioClock.Resume();
899 mPauseCond.notify_all();
906 int seekFlag = AVSEEK_FLAG_BACKWARD;
909 int stream =
HasVideo() ? mVideoStream : mAudioStream;
913 int ret = av_seek_frame(mContext, stream, seekPts, seekFlag);
916 MMechostr(MSKRUNTIME,
">> MediaPlayer: Seek error: %s\n",
av_err2str(ret));
917 mSeekRequested =
false;
918 mSeekInProgressAudio = mSeekInProgressVideo =
false;
919 mSeekCompletedAudio =
true;
920 mSeekPts = AV_NOPTS_VALUE;
925 mSeekRequested =
false;
931 AVPacket* flushVideo =
new AVPacket;
932 flushVideo->data = PacketQueue::FLUSH_DATA;
933 flushVideo->pts = mSeekPts;
934 flushVideo->size = 0;
935 mVideoPktQ.Flush(flushVideo);
939 AVPacket* flushAudio =
new AVPacket;
940 flushAudio->data = PacketQueue::FLUSH_DATA;
941 flushAudio->pts = mSeekPts;
942 flushAudio->size = 0;
943 mAudioPktQ.Flush(flushAudio);
946 if (mPaused || mSystemClock.IsPaused())
947 mPauseCond.notify_all();
950 if (eofReached || (mAudioPktQ.Size() >= mAudioPktQ.MaxSize()) || (mVideoPktQ.Size() >= mVideoPktQ.MaxSize()))
952 boost::this_thread::sleep_for(boost::chrono::milliseconds(1));
956 AVPacket* packet =
new AVPacket;
959 int ret = av_read_frame(mContext, packet);
963 if (ret == AVERROR_EOF && mLoop &&
IsSeekable())
969 boost::this_thread::sleep_for(boost::chrono::microseconds(1));
975 if (ret != AVERROR_EOF)
978 MMechostr(MSKRUNTIME,
">> MediaPlayer: Read error: %s, %d tries left\n",
av_err2str(ret), readTries);
989 else if (!mIsLocal && keepGoing && !eofReached && !waitBuffer && ((
HasVideo() && (mVideoPktQ.Size() == 0))
993 mSystemClock.Pause();
1000 if (packet->stream_index == mAudioStream)
1001 mAudioPktQ.Push(packet);
1002 else if (packet->stream_index == mVideoStream)
1003 mVideoPktQ.Push(packet);
1006 av_packet_unref(packet);
1007 SAFE_DELETE(packet);
1012 boost::this_thread::sleep_for(boost::chrono::microseconds(1));
1015 catch (std::exception& e)
1017 MMechostr(MSKRUNTIME,
">> MediaPlayer : exception : %s\n", e.what());
1021 if (eofReached && !mStopped)
1032 if (
HasVideo() && mVideoThread.joinable())
1033 mVideoThread.join();
1035 if (
HasAudio() && mAudioThread.joinable())
1036 mAudioThread.join();
1042 MMechostr(MSKRUNTIME,
">> MediaPlayer : video ended\n");
1045int64_t MediaPlayer::SynchronizeVideo(AVFrame *srcFrame, int64_t pts)
1049 if (pts != AV_NOPTS_VALUE)
1054 if (srcFrame->repeat_pict != 0)
1056 AVRational fps = av_guess_frame_rate(mContext, mContext->streams[mVideoStream], srcFrame);
1059 double frame_delay = srcFrame->repeat_pict / (2 * av_q2d(fps));
1067void MediaPlayer::SendQuitPacket()
1072 AVPacket* quitPacketAudio =
new AVPacket;
1073 quitPacketAudio->data = PacketQueue::QUIT_DATA;
1074 quitPacketAudio->size = 0;
1075 mAudioPktQ.Flush(quitPacketAudio);
1081 AVPacket* quitPacketVideo =
new AVPacket;
1082 quitPacketVideo->data = PacketQueue::QUIT_DATA;
1083 quitPacketVideo->size = 0;
1084 mVideoPktQ.Flush(quitPacketVideo);
1088void MediaPlayer::ComputeSize(
int sourceW,
int sourceH)
1090 boost::mutex::scoped_lock lsize(mSizeMutex);
1091 boost::mutex::scoped_lock l(mVideoMutex);
1093 float ratio = (float)sourceW / (
float)sourceH;
1102 mFinalH = (int)((
float)mUserW / ratio);
1107 mFinalW = (int)((
float)mUserH * ratio);
1116 avpicture_free((AVPicture*)mVideoBuffer);
1118 mVideoBuffer->width = mFinalW;
1119 mVideoBuffer->height = mFinalH;
1122 throw std::runtime_error(
"Couldn't allocate RGB frame");
1124 sws_freeContext(mScalerCtx);
1125 mScalerCtx = sws_getContext(sourceW, sourceH, mVideoCtx->pix_fmt, mFinalW, mFinalH,
MediaPlayer::DEST_PIXEL_FORMAT, SWS_FAST_BILINEAR, NULL, NULL, NULL);
1127 mFrameBuffer = cv::Mat(mFinalH, mFinalW, CV_8UC3);
1128 mFrameRetrieveBuffer = cv::Mat(mFinalH, mFinalW, CV_8UC3);
1131 if (mScalerCtx == NULL)
1132 throw std::runtime_error(
"Couldn't create swscale context");
1138void MediaPlayer::AllocResampler(uint64_t outChannelLayout, AVSampleFormat outSampleFormat,
int outSampleRate, AVCodecContext* context)
1140 swr_free(&mResampleCtx);
1142 if (av_sample_fmt_is_planar(outSampleFormat))
1143 throw std::runtime_error(
"Planar formats are not supported");
1145 mResampleCtx = swr_alloc_set_opts(NULL, outChannelLayout, outSampleFormat, outSampleRate, context->channel_layout, context->sample_fmt, context->sample_rate, 0, NULL);
1146 if (mResampleCtx == NULL)
1147 throw std::runtime_error(
"Couldn't allocate resampler context");
1149 int ret = swr_init(mResampleCtx);
1151 throw std::runtime_error(std::string(
"Couldn't initialize resampler context: ") +
av_err2str(ret));
1154void MediaPlayer::Reset()
1159 avcodec_close(mVideoCtx);
1161 sws_freeContext(mScalerCtx);
1163 mFrameBuffer.release();
1167 avcodec_close(mAudioCtx);
1170 swr_free(&mResampleCtx);
1175void MediaPlayer::VideoThread()
1177 int64_t seekPts = AV_NOPTS_VALUE;
1179 int64_t presentationTime = 0;
1180 bool skipNext =
false;
1183 AVPacket* packet = mVideoPktQ.Pop();
1184 if (packet->data == PacketQueue::FLUSH_DATA)
1186 avcodec_flush_buffers(mVideoCtx);
1187 seekPts = packet->pts;
1188 SAFE_DELETE(packet);
1189 presentationTime = 0;
1190 mSeekInProgressVideo =
false;
1193 else if (packet->data == PacketQueue::QUIT_DATA)
1195 SAFE_DELETE(packet);
1208 int ret = avcodec_send_packet(mVideoCtx, packet);
1209 av_packet_unref(packet);
1210 SAFE_DELETE(packet);
1213 ret = avcodec_receive_frame(mVideoCtx, mFrame);
1214 if (ret == AVERROR(EAGAIN) || ret == AVERROR_EOF)
1220 MMechostr(MSKDEBUG,
">> MediaPlayer: Decoding error: %s\n",
av_err2str(ret));
1227 else if (mSizeChanged || mFrame->width != mSourceW || mFrame->height != mSourceH)
1229 ComputeSize(mFrame->width, mFrame->height);
1230 mSizeChanged =
false;
1234 int64_t pts = av_frame_get_best_effort_timestamp(mFrame);
1235 if (pts != AV_NOPTS_VALUE)
1238 pts = SynchronizeVideo(mFrame, pts);
1241 if (seekPts != AV_NOPTS_VALUE)
1246 seekPts = AV_NOPTS_VALUE;
1250 if (skipNext && (mFrame->pict_type == AV_PICTURE_TYPE_I))
1257 sws_scale(mScalerCtx, mFrame->data, mFrame->linesize, 0, mFrame->height, mVideoBuffer->data, mVideoBuffer->linesize);
1263 while (!mSeekInProgressVideo && !mSeekCompletedAudio && !mSystemClock.IsPaused() && !mPaused && !mStopped)
1264 boost::this_thread::yield();
1266 int64_t clock = mAudioClock.Get();
1269 if (mSeekInProgressVideo)
1275 if ((pts - clock) > 250)
1276 boost::this_thread::sleep_for(boost::chrono::milliseconds(250));
1278 boost::this_thread::sleep_for(boost::chrono::milliseconds(pts - clock));
1281 else if (presentationTime != 0 && !mSystemClock.IsPaused())
1283 int64_t elapsed = Clock::GetSysTime() - presentationTime;
1284 if (((pts - mVideoPts) - elapsed) > 250)
1285 boost::this_thread::sleep_for(boost::chrono::milliseconds(250));
1287 boost::this_thread::sleep_for(boost::chrono::milliseconds((pts - mVideoPts) - elapsed));
1291 boost::mutex::scoped_lock l(mVideoMutex);
1293 if (mVideoBuffer->linesize[0] != mFrameBuffer.step)
1294 mFrameBuffer = cv::Mat(mVideoBuffer->height, mVideoBuffer->width, CV_8UC3, mVideoBuffer->data[0], mVideoBuffer->linesize[0]);
1296 memcpy(mFrameBuffer.data, mVideoBuffer->data[0], mVideoBuffer->linesize[0] * mVideoBuffer->height);
1301 if ((mPaused || mSystemClock.IsPaused()) && !mStopped && !mSeekInProgressVideo)
1304 presentationTime = 0;
1307 presentationTime = Clock::GetSysTime();
1312 boost::this_thread::sleep_for(boost::chrono::microseconds(1));
1316MediaPlayer::AudioFrame::AudioFrame() :
1322MediaPlayer::AudioFrame::AudioFrame(
const AudioFrame& frame) :
1326 data.reset(
new char[size]);
1327 memcpy(data.get(), frame.data.get(), size);
1330MediaPlayer::AudioFrame::AudioFrame(AudioFrame&& frame) :
1331 data(std::move(frame.data)),
1336MediaPlayer::AudioFrame& MediaPlayer::AudioFrame::operator=(AudioFrame&& frame)
1340 data = std::move(frame.data);
1344void MediaPlayer::AudioThread()
1346 int64_t firstPts = AV_NOPTS_VALUE;
1348 AVFrame* frame = av_frame_alloc();
1350 throw std::runtime_error(
"Out of memory");
1352 int64_t seekPts = AV_NOPTS_VALUE;
1356 AVPacket* packet = mAudioPktQ.Pop();
1357 if (packet->data == PacketQueue::FLUSH_DATA)
1359 avcodec_flush_buffers(mAudioCtx);
1360 seekPts = packet->pts;
1361 SAFE_DELETE(packet);
1363 boost::mutex::scoped_lock l(mAudioMutex);
1364 mAudioFrameQ.clear();
1365 mSeekCompletedAudio =
false;
1368 else if (packet->data == PacketQueue::QUIT_DATA)
1370 SAFE_DELETE(packet);
1372 boost::mutex::scoped_lock l(mAudioMutex);
1373 mAudioFrameQ.clear();
1377 int ret = avcodec_send_packet(mAudioCtx, packet);
1378 av_packet_unref(packet);
1379 SAFE_DELETE(packet);
1381 while (ret >= 0 && !mStopped)
1383 ret = avcodec_receive_frame(mAudioCtx, frame);
1384 if (ret == AVERROR(EAGAIN) || ret == AVERROR_EOF)
1390 MMechostr(MSKDEBUG,
">> MediaPlayer: Decoding error: %s\n",
av_err2str(ret));
1396 int64_t pts = av_frame_get_best_effort_timestamp(frame);
1397 if (pts == AV_NOPTS_VALUE)
1402 if (firstPts == AV_NOPTS_VALUE)
1405 mAudioClock.Reset(firstPts);
1408 if (seekPts != AV_NOPTS_VALUE)
1414 seekPts = AV_NOPTS_VALUE;
1415 mSeekInProgressAudio =
false;
1419 AudioFrame destFrame;
1421 if (mResampleCtx != NULL)
1425 int outSamples = swr_get_out_samples(mResampleCtx, frame->nb_samples);
1429 int outSamplesLines = 0;
1430 int buffSize = av_samples_get_buffer_size(&outSamplesLines, av_get_channel_layout_nb_channels(mOutChannelLayout), outSamples, mOutSampleFormat, 1);
1432 destFrame.data.reset(
new char[buffSize]);
1433 char* convertedData = destFrame.data.get();
1436 int ilen = swr_convert(mResampleCtx, (uint8_t**)&convertedData, outSamples, (
const uint8_t**)frame->extended_data, frame->nb_samples);
1442 int outBytes = av_samples_get_buffer_size(&outSamplesLines, av_get_channel_layout_nb_channels(mOutChannelLayout), ilen, mOutSampleFormat, 1);
1444 if (outBytes < 0 || outBytes > buffSize)
1447 destFrame.size = outBytes;
1451 destFrame.size = frame->nb_samples * av_get_channel_layout_nb_channels(mOutChannelLayout) * av_get_bytes_per_sample(mOutSampleFormat);
1452 destFrame.data.reset(
new char[destFrame.size]);
1453 memcpy(destFrame.data.get(), frame->data[0], destFrame.size);
1455 destFrame.pts = pts;
1458 while (mAudioFrameQ.full() && !mStopped && !mPaused && !mSystemClock.IsPaused() && !mSeekInProgressAudio)
1459 boost::this_thread::yield();
1462 boost::mutex::scoped_lock l(mAudioMutex);
1463 if ((mPaused || mSystemClock.IsPaused()) && !mStopped && !mSeekInProgressAudio)
1466 if (!mSeekInProgressAudio)
1468 mAudioFrameQ.push_back(std::move(destFrame));
1475 boost::this_thread::sleep_for(boost::chrono::microseconds(1));
1478 av_frame_free(&frame);
1483 size_t retrieved = 0;
1484 int64_t firstPts = AV_NOPTS_VALUE;
1485 if (mSeekInProgressAudio || mAudioClock.IsPaused())
1488 boost::mutex::scoped_lock l(mAudioMutex);
1489 while (!mAudioFrameQ.empty() && (retrieved < length) && !mStopped)
1491 const AudioFrame frame = mAudioFrameQ.front();
1493 if (firstPts == AV_NOPTS_VALUE)
1494 firstPts = frame.pts;
1497 if (frame.size > length)
1499 mAudioFrameQ.pop_front();
1503 if (retrieved + frame.size > length)
1506 memcpy(destBuffer + retrieved, frame.data.get(), frame.size);
1507 retrieved += frame.size;
1508 mAudioFrameQ.pop_front();
1511 if (firstPts != AV_NOPTS_VALUE)
1512 SynchronizeAudio(firstPts);
1514 return (
int)retrieved;
1517void MediaPlayer::SynchronizeAudio(int64_t pts)
1524 if (!mSeekCompletedAudio)
1526 mAudioClock.Reset(pts);
1527 mSeekCompletedAudio =
true;
1531int MediaPlayer::FileRead(
void* player, uint8_t* buf,
int buf_size)
1533 return fread(buf, 1, buf_size, ((
MediaPlayer*)player)->mFilePtr);
1536int MediaPlayer::FileWrite(
void* player, uint8_t* buf,
int buf_size)
1538 return fwrite(buf, 1, buf_size, ((
MediaPlayer*)player)->mFilePtr);
1541int64_t MediaPlayer::FileSeek(
void* player, int64_t offset,
int whence)
1545 whence &= ~AVSEEK_FORCE;
1547 if (whence == AVSEEK_SIZE)
1549 int64_t prev = ftell(vp->mFilePtr);
1550 fseek(vp->mFilePtr, 0L, SEEK_END);
1551 int64_t sz = (int64_t)ftell(vp->mFilePtr);
1552 fseek(vp->mFilePtr, (
long)prev, SEEK_SET);
1556 if (fseek(vp->mFilePtr, (
long)offset, whence) != 0)
1559 return ftell(vp->mFilePtr);
1565int64_t MediaPlayer::Clock::GetSysTime()
1570MediaPlayer::Clock::Clock() :
1578int64_t MediaPlayer::Clock::Get()
1580 boost::mutex::scoped_lock l(mMutex);
1585 return GetSysTime() - mSystemTime + mInitialTime;
1588void MediaPlayer::Clock::Reset(int64_t initialTime)
1590 boost::mutex::scoped_lock l(mMutex);
1592 mInitialTime = initialTime;
1593 mSystemTime = GetSysTime();
1594 mPauseTime = initialTime;
1597void MediaPlayer::Clock::Pause()
1599 boost::mutex::scoped_lock l(mMutex);
1603 mPauseTime = GetSysTime() - mSystemTime + mInitialTime;
1608void MediaPlayer::Clock::Resume()
1610 boost::mutex::scoped_lock l(mMutex);
1614 mInitialTime = mPauseTime;
1615 mSystemTime = GetSysTime();
1620bool MediaPlayer::Clock::IsPaused()
1622 boost::mutex::scoped_lock l(mMutex);
1628uint8_t* MediaPlayer::PacketQueue::FLUSH_DATA = (uint8_t*)
"VP_FLUSH";
1629uint8_t* MediaPlayer::PacketQueue::QUIT_DATA = (uint8_t*)
"VP_QUIT";
1631MediaPlayer::PacketQueue::PacketQueue(
size_t capacity) :
1632 mCapacity(capacity),
1636MediaPlayer::PacketQueue::~PacketQueue()
1641bool MediaPlayer::PacketQueue::Empty()
1643 boost::mutex::scoped_lock l(mMutex);
1645 return mQueue.empty();
1648bool MediaPlayer::PacketQueue::Push(AVPacket* packet)
1650 boost::mutex::scoped_lock l(mMutex);
1652 if (mSize >= mCapacity)
1655 bool wasEmpty = mQueue.empty();
1656 mQueue.push(packet);
1657 mSize += packet->size;
1665AVPacket* MediaPlayer::PacketQueue::Pop()
1667 boost::mutex::scoped_lock l(mMutex);
1669 while (mQueue.empty())
1672 AVPacket* pkt = mQueue.front();
1679AVPacket* MediaPlayer::PacketQueue::TryPop()
1681 boost::mutex::scoped_lock l(mMutex);
1686 AVPacket* pkt = mQueue.front();
1693void MediaPlayer::PacketQueue::Flush(AVPacket* flushPacket)
1695 boost::mutex::scoped_lock l(mMutex);
1697 bool wasEmpty = mQueue.empty();
1701 mQueue.push(flushPacket);
1706void MediaPlayer::PacketQueue::Clear()
1708 while (!mQueue.empty())
1710 AVPacket* pkt = mQueue.front();
1713 if ((pkt->data != PacketQueue::FLUSH_DATA) && (pkt->data != PacketQueue::QUIT_DATA))
1714 av_packet_unref(pkt);
1721size_t MediaPlayer::PacketQueue::Size()
1726size_t MediaPlayer::PacketQueue::MaxSize()