Commit 3c604c4a authored by Ghislain MARY's avatar Ghislain MARY

Capture performed (need to output the samples now) + cleanup of display.

parent 2da506c1
......@@ -30,28 +30,12 @@ using namespace Windows::Storage;
using namespace libmswinrtvid;
static const float defaultFps = 15.0f;
static const int defaultBitrate = 384000;
bool MSWinRTCap::smInstantiated = false;
#define MS_H264_CONF(required_bitrate, bitrate_limit, resolution, fps, ncpus) \
{ required_bitrate, bitrate_limit, { MS_VIDEO_SIZE_ ## resolution ## _W, MS_VIDEO_SIZE_ ## resolution ## _H }, fps, ncpus, NULL }
static const MSVideoConfiguration h264_conf_list[] = {
MS_H264_CONF( 300000, 500000, VGA, 12, 1),
MS_H264_CONF( 170000, 300000, QVGA, 12, 1),
MS_H264_CONF( 120000, 170000, QVGA, 8, 1),
MS_H264_CONF( 0, 120000, QVGA, 5 ,1)
};
MSWinRTCap::MSWinRTCap()
: mIsInitialized(false), mIsActivated(false), mIsStarted(false),
mRfc3984Packer(NULL), mAllocator(NULL), mPackerMode(1), mStartTime(0), mSamplesCount(0), mBitrate(defaultBitrate),
mCameraSensorRotation(0), mDeviceOrientation(0), mPixFmt(MS_YUV420P)
: mIsInitialized(false), mIsActivated(false), mIsStarted(false), mFps(15),
mAllocator(NULL), mStartTime(0), mCameraSensorRotation(0), mDeviceOrientation(0)
{
if (smInstantiated) {
ms_error("[MSWinRTCap] An video capture filter is already instantiated. A second one can not be created.");
......@@ -62,7 +46,6 @@ MSWinRTCap::MSWinRTCap()
ms_queue_init(&mSampleToSendQueue);
ms_queue_init(&mSampleToFreeQueue);
mAllocator = ms_yuv_buf_allocator_new();
mVConf = ms_video_find_best_configuration_for_bitrate(h264_conf_list, mBitrate, ms_get_cpu_count());
mActivationCompleted = CreateEventEx(NULL, L"Local\\MSWinRTCapActivation", 0, EVENT_ALL_ACCESS);
if (!mActivationCompleted) {
......@@ -122,11 +105,6 @@ int MSWinRTCap::activate()
{
if (!mIsInitialized) return -1;
mRfc3984Packer = rfc3984_new();
rfc3984_set_mode(mRfc3984Packer, mPackerMode);
rfc3984_enable_stap_a(mRfc3984Packer, FALSE);
ms_video_starter_init(&mStarter);
mCapture = ref new MediaCapture();
MediaCaptureInitializationSettings^ initSettings = ref new MediaCaptureInitializationSettings();
initSettings->MediaCategory = MediaCategory::Communications;
......@@ -164,10 +142,6 @@ int MSWinRTCap::activate()
int MSWinRTCap::deactivate()
{
if (mRfc3984Packer != nullptr) {
rfc3984_destroy(mRfc3984Packer);
mRfc3984Packer = nullptr;
}
mCameraSensorRotation = 0;
mIsActivated = false;
return 0;
......@@ -200,20 +174,23 @@ void MSWinRTCap::start()
WaitForSingleObjectEx(mPreviewStartCompleted, INFINITE, FALSE);
MediaEncodingProfile^ mediaEncodingProfile = mEncodingProfile;
Concurrency::create_task(mMediaSink->InitializeAsync(mediaEncodingProfile->Video)).then([this, mediaEncodingProfile](Windows::Media::IMediaExtension^ mediaExtension)
{
return Concurrency::create_task(mCapture->StartRecordToCustomSinkAsync(mediaEncodingProfile, mediaExtension)).then([this](Concurrency::task<void>& asyncInfo)
{
try {
asyncInfo.get();
//_recordingStarted = true;
}
catch (Platform::Exception^) {
//CleanupSink();
throw;
}
});
IAsyncOperation<Windows::Media::IMediaExtension^>^ op = mMediaSink->InitializeAsync(mEncodingProfile->Video);
op->Completed = ref new AsyncOperationCompletedHandler<Windows::Media::IMediaExtension^>(
[this](IAsyncOperation<Windows::Media::IMediaExtension^>^ asyncOp, Windows::Foundation::AsyncStatus asyncStatus) {
if (asyncStatus == Windows::Foundation::AsyncStatus::Completed) {
Windows::Media::IMediaExtension^ mediaExtension = asyncOp->GetResults();
IAsyncAction^ action = mCapture->StartRecordToCustomSinkAsync(mEncodingProfile, mediaExtension);
action->Completed = ref new AsyncActionCompletedHandler([this](IAsyncAction^ asyncAction, Windows::Foundation::AsyncStatus asyncStatus) {
if (asyncStatus == Windows::Foundation::AsyncStatus::Completed)
mIsStarted = true;
SetEvent(mStartCompleted);
});
} else {
// TODO
SetEvent(mStartCompleted);
}
});
WaitForSingleObjectEx(mStartCompleted, INFINITE, FALSE);
}
}
......@@ -246,23 +223,7 @@ int MSWinRTCap::feed(MSFilter *f)
}
// Send queued samples
while ((im = ms_queue_get(&mSampleToSendQueue)) != NULL) {
if (mPixFmt == MS_H264) {
MSQueue nalus;
ms_queue_init(&nalus);
uint32_t timestamp = mblk_get_timestamp_info(im);
bitstreamToMsgb(im->b_rptr, im->b_wptr - im->b_rptr, &nalus);
rfc3984_pack(mRfc3984Packer, &nalus, f->outputs[0], timestamp);
ms_queue_put(&mSampleToFreeQueue, im);
} else {
ms_queue_put(f->outputs[0], im);
}
if (mSamplesCount == 0) {
ms_video_starter_first_frame(&mStarter, f->ticker->ticks);
} else if (ms_video_starter_need_i_frame(&mStarter, f->ticker->time)) {
requestIdrFrame();
}
mSamplesCount++;
ms_queue_put(f->outputs[0], im);
}
ms_mutex_unlock(&mMutex);
......@@ -275,94 +236,53 @@ static void freeSample(void *sample)
delete[] sample;
}
#if 0
void MSWinRTCap::OnSampleAvailable(ULONGLONG hnsPresentationTime, ULONGLONG hnsSampleDuration, DWORD cbSample, BYTE* pSample)
{
MS_UNUSED(hnsSampleDuration);
mblk_t *m;
uint32_t timestamp = (uint32_t)((hnsPresentationTime / 10000LL) * 90LL);
if (mPixFmt == MS_H264) {
BYTE* pMem = new BYTE[cbSample];
memcpy(pMem, pSample, cbSample);
m = esballoc(pMem, cbSample, 0, freeSample);
m->b_wptr += cbSample;
} else {
int w = mVConf.vsize.width;
int h = mVConf.vsize.height;
if ((mDeviceOrientation % 180) == 0) {
w = mVConf.vsize.height;
h = mVConf.vsize.width;
}
uint8_t *y = (uint8_t *)pSample;
uint8_t *cbcr = (uint8_t *)(pSample + w * h);
m = copy_ycbcrbiplanar_to_true_yuv_with_rotation(mAllocator, y, cbcr, 0, w, h, w, w, TRUE);
int w = mVConf.vsize.width;
int h = mVConf.vsize.height;
if ((mDeviceOrientation % 180) == 0) {
w = mVConf.vsize.height;
h = mVConf.vsize.width;
}
uint8_t *y = (uint8_t *)pSample;
uint8_t *cbcr = (uint8_t *)(pSample + w * h);
m = copy_ycbcrbiplanar_to_true_yuv_with_rotation(mAllocator, y, cbcr, 0, w, h, w, w, TRUE);
mblk_set_timestamp_info(m, timestamp);
ms_mutex_lock(&mMutex);
ms_queue_put(&mSampleToSendQueue, m);
ms_mutex_unlock(&mMutex);
}
#endif
void MSWinRTCap::setFps(float fps)
{
mVConf.fps = fps;
setConfiguration(&mVConf);
}
void MSWinRTCap::setBitrate(int bitrate)
{
if (mIsActivated) {
/* Encoding is already ongoing, do not change video size, only bitrate. */
mVConf.required_bitrate = bitrate;
setConfiguration(&mVConf);
} else {
MSVideoConfiguration best_vconf = ms_video_find_best_configuration_for_bitrate(h264_conf_list, bitrate, ms_get_cpu_count());
setConfiguration(&best_vconf);
}
mFps = fps;
applyFps();
}
MSVideoSize MSWinRTCap::getVideoSize()
{
MSVideoSize vs;
if ((mDeviceOrientation % 180) == 0) {
vs.width = mVConf.vsize.height;
vs.height = mVConf.vsize.width;
vs.width = mVideoSize.height;
vs.height = mVideoSize.width;
} else {
vs = mVConf.vsize;
vs = mVideoSize;
}
return vs;
}
void MSWinRTCap::setVideoSize(MSVideoSize vs)
{
MSVideoConfiguration best_vconf;
best_vconf = ms_video_find_best_configuration_for_size(h264_conf_list, vs, ms_get_cpu_count());
mVConf.vsize = vs;
mVConf.fps = best_vconf.fps;
mVConf.bitrate_limit = best_vconf.bitrate_limit;
selectBestVideoSize();
setConfiguration(&mVConf);
}
const MSVideoConfiguration * MSWinRTCap::getConfigurationList()
{
return h264_conf_list;
}
void MSWinRTCap::setConfiguration(const MSVideoConfiguration *vconf)
{
if (vconf != &mVConf) memcpy(&mVConf, vconf, sizeof(MSVideoConfiguration));
if (mVConf.required_bitrate > mVConf.bitrate_limit)
mVConf.required_bitrate = mVConf.bitrate_limit;
if (mIsActivated) {
applyVideoSize();
}
applyFps();
mVideoSize = vs;
applyVideoSize();
}
void MSWinRTCap::setDeviceOrientation(int degrees)
......@@ -370,20 +290,11 @@ void MSWinRTCap::setDeviceOrientation(int degrees)
mDeviceOrientation = degrees;
}
void MSWinRTCap::requestIdrFrame()
{
if (mIsStarted) {
if (mPixFmt == MS_H264) {
Platform::Boolean value = true;
}
}
}
void MSWinRTCap::applyFps()
{
if (mEncodingProfile != nullptr) {
mEncodingProfile->Video->FrameRate->Numerator = (unsigned int)mVConf.fps;
mEncodingProfile->Video->FrameRate->Numerator = (unsigned int)mFps;
mEncodingProfile->Video->FrameRate->Denominator = 1;
}
}
......@@ -391,79 +302,17 @@ void MSWinRTCap::applyFps()
void MSWinRTCap::applyVideoSize()
{
if (mEncodingProfile != nullptr) {
mEncodingProfile->Video->Width = mVConf.vsize.width;
mEncodingProfile->Video->Height = mVConf.vsize.height;
}
}
void MSWinRTCap::bitstreamToMsgb(uint8_t *encoded_buf, size_t size, MSQueue *nalus) {
size_t idx = 0;
size_t frame_start_idx;
mblk_t *m;
int nal_len;
if ((size < 5) || (encoded_buf[0] != 0) || (encoded_buf[1] != 0) || (encoded_buf[2] != 0) || (encoded_buf[3] != 1))
return;
frame_start_idx = idx = 4;
while (frame_start_idx < size) {
uint8_t *buf = encoded_buf + idx;
while ((buf = (uint8_t *)memchr(buf, 0, encoded_buf + size - buf)) != NULL) {
if (encoded_buf + size - buf < 4)
break;
if (*((int*)(buf)) == 0x01000000)
break;
++buf;
}
idx = buf ? buf - encoded_buf : size;
nal_len = idx - frame_start_idx;
if (nal_len > 0) {
m = esballoc(&encoded_buf[frame_start_idx], nal_len, 0, NULL);
m->b_wptr += nal_len;
ms_queue_put(nalus, m);
}
frame_start_idx = idx = idx + 4;
}
}
bool MSWinRTCap::selectBestVideoSize()
{
MSVideoSize requestedSize;
requestedSize.width = mVConf.vsize.width;
requestedSize.height = mVConf.vsize.height;
MediaCapture^ mediaCapture = ref new MediaCapture();
if (MediaCapture::IsVideoProfileSupported(mDeviceId)) {
Windows::Foundation::Collections::IVectorView<MediaCaptureVideoProfile^>^ profiles = mediaCapture->FindAllVideoProfiles(mDeviceId);
for (unsigned int i = 0; i < profiles->Size; i++) {
MediaCaptureVideoProfile^ profile = profiles->GetAt(i);
Windows::Foundation::Collections::IVectorView<MediaCaptureVideoProfileMediaDescription^>^ descriptions = profile->SupportedRecordMediaDescription;
for (unsigned int j = 0; j < descriptions->Size; j++) {
MediaCaptureVideoProfileMediaDescription^ description = descriptions->GetAt(j);
}
}
} else {
ms_warning("[MSWinRTCap] Video profile is not supported by the camera, default to requested video size");
mVConf.vsize.width = requestedSize.width;
mVConf.vsize.height = requestedSize.height;
return false;
mEncodingProfile->Video->Width = mVideoSize.width;
mEncodingProfile->Video->Height = mVideoSize.height;
}
return true;
}
void MSWinRTCap::configure()
{
if (mPixFmt == MS_H264) {
mEncodingProfile = MediaEncodingProfile::CreateMp4(VideoEncodingQuality::Auto);
mEncodingProfile->Container = nullptr;
mEncodingProfile->Video->ProfileId = H264ProfileIds::Baseline;
//mEncodingProfile->Video->Width = mVConf.vsize.width;
//mEncodingProfile->Video->Height = mVConf.vsize.height;
} else {
mEncodingProfile = ref new MediaEncodingProfile();
mEncodingProfile->Container = nullptr;
mEncodingProfile->Video = VideoEncodingProperties::CreateUncompressed(MediaEncodingSubtypes::Nv12, mVConf.vsize.width, mVConf.vsize.height);
}
mEncodingProfile = ref new MediaEncodingProfile();
mEncodingProfile->Audio = nullptr;
mEncodingProfile->Container = nullptr;
mEncodingProfile->Video = VideoEncodingProperties::CreateUncompressed(MediaEncodingSubtypes::Nv12, mVideoSize.width, mVideoSize.height);
}
void MSWinRTCap::addCamera(MSWebCamManager *manager, MSWebCamDesc *desc, Platform::String^ DeviceId, Platform::String^ DeviceName)
......@@ -523,7 +372,3 @@ void MSWinRTCap::detectCameras(MSWebCamManager *manager, MSWebCamDesc *desc)
});
WaitForSingleObjectEx(eventCompleted, INFINITE, FALSE);
}
void MSWinRTCap::printProperties()
{
}
......@@ -53,53 +53,41 @@ namespace libmswinrtvid
void stop();
int feed(MSFilter *f);
void OnSampleAvailable(ULONGLONG hnsPresentationTime, ULONGLONG hnsSampleDuration, DWORD cbSample, BYTE* pSample);
//void OnSampleAvailable(ULONGLONG hnsPresentationTime, ULONGLONG hnsSampleDuration, DWORD cbSample, BYTE* pSample);
void setCaptureElement(Windows::UI::Xaml::Controls::CaptureElement^ captureElement) { mCaptureElement = captureElement; };
void setDeviceId(Platform::String^ id) { mDeviceId = id; };
MSPixFmt getPixFmt() { return mPixFmt; }
void setPixFmt(MSPixFmt pixFmt) { mPixFmt = pixFmt; }
float getFps() { return mVConf.fps; }
MSPixFmt getPixFmt() { return MS_YUV420P; }
float getFps() { return mFps; }
void setFps(float fps);
int getBitrate() { return mBitrate; }
void setBitrate(int bitrate);
MSVideoSize getVideoSize();
void setVideoSize(MSVideoSize vs);
const MSVideoConfiguration * getConfigurationList();
void setConfiguration(const MSVideoConfiguration *vconf);
int getCameraSensorRotation() { return mCameraSensorRotation; }
void setDeviceOrientation(int degrees);
void requestIdrFrame();
static void detectCameras(MSWebCamManager *manager, MSWebCamDesc *desc);
private:
void applyFps();
void applyVideoSize();
void bitstreamToMsgb(uint8_t *encoded_buf, size_t size, MSQueue *nalus);
bool selectBestVideoSize();
void configure();
void printProperties();
static void addCamera(MSWebCamManager *manager, MSWebCamDesc *desc, Platform::String^ DeviceId, Platform::String^ DeviceName);
static bool smInstantiated;
bool mIsInitialized;
bool mIsActivated;
bool mIsStarted;
float mFps;
MSVideoSize mVideoSize;
MSQueue mSampleToSendQueue;
MSQueue mSampleToFreeQueue;
ms_mutex_t mMutex;
Rfc3984Context *mRfc3984Packer;
MSYuvBufAllocator *mAllocator;
int mPackerMode;
uint64_t mStartTime;
int mSamplesCount;
int mBitrate;
int mCameraSensorRotation;
int mDeviceOrientation;
MSVideoStarter mStarter;
MSVideoConfiguration mVConf;
MSPixFmt mPixFmt;
HANDLE mActivationCompleted;
HANDLE mStartCompleted;
HANDLE mStopCompleted;
......
......@@ -23,8 +23,6 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
#include "mswinrtdis.h"
#include "VideoBuffer.h"
#include <nserror.h>
#include <Mferror.h>
using namespace libmswinrtvid;
using namespace Microsoft::WRL;
......@@ -33,37 +31,6 @@ using namespace Windows::Media::Core;
using namespace Windows::Media::MediaProperties;
static uint8_t get_u8_at_bit_offset(uint8_t *data, uint32_t *bit_offset) {
uint8_t res = ((data[*bit_offset / 8] << (*bit_offset % 8)) | (data[(*bit_offset / 8) + 1] >> (8 - (*bit_offset % 8))));
*bit_offset += 8;
return res;
}
static uint8_t get_u1_at_bit_offset(uint8_t *data, uint32_t *bit_offset) {
uint8_t mod = *bit_offset % 8;
uint8_t res = (data[*bit_offset / 8] & ((1 << (8 - mod)) - 1)) >> (7 - mod);
*bit_offset += 1;
return res;
}
static uint8_t get_ue_at_bit_offset(uint8_t *data, uint32_t *bit_offset) {
uint8_t b;
uint8_t i;
uint8_t res = 0;
int leading_zero_bits = -1;
for (b = 0; !b; leading_zero_bits++) {
b = get_u1_at_bit_offset(data, bit_offset);
}
for (i = 0; i < leading_zero_bits; i++) {
b = get_u1_at_bit_offset(data, bit_offset);
res <<= 1;
res |= b;
}
res += (1 << leading_zero_bits) - 1;
return res;
}
static void _startMediaElement(Windows::UI::Xaml::Controls::MediaElement^ mediaElement, Windows::Media::Core::MediaStreamSource^ mediaStreamSource)
{
......@@ -97,13 +64,7 @@ void MSWinRTDisSampleHandler::StartMediaElement()
{
if (mMediaElement != nullptr) {
VideoEncodingProperties^ videoEncodingProperties;
if (this->PixFmt == MS_H264) {
videoEncodingProperties = VideoEncodingProperties::CreateH264();
videoEncodingProperties->Width = this->Width;
videoEncodingProperties->Height = this->Height;
}
else
videoEncodingProperties = VideoEncodingProperties::CreateUncompressed(MediaEncodingSubtypes::Nv12, this->Width, this->Height);
videoEncodingProperties = VideoEncodingProperties::CreateUncompressed(MediaEncodingSubtypes::Yv12, this->Width, this->Height);
VideoStreamDescriptor^ videoStreamDescriptor = ref new VideoStreamDescriptor(videoEncodingProperties);
MediaStreamSource^ mediaStreamSource = ref new MediaStreamSource(videoStreamDescriptor);
mediaStreamSource->SampleRequested += ref new Windows::Foundation::TypedEventHandler<Windows::Media::Core::MediaStreamSource ^, Windows::Media::Core::MediaStreamSourceSampleRequestedEventArgs ^>(this, &MSWinRTDisSampleHandler::OnSampleRequested);
......@@ -217,9 +178,7 @@ void MSWinRTDisSampleHandler::RequestMediaElementRestart()
MSWinRTDis::MSWinRTDis()
: mIsInitialized(false), mIsActivated(false), mIsStarted(false), mRfc3984Unpacker(nullptr),
mBitstreamSize(65536), mBitstream(nullptr), mSPS(nullptr), mPPS(nullptr), mAVPFEnabled(false),
mSampleHandler(nullptr), mFirstFrameReceived(false)
: mIsInitialized(false), mIsActivated(false), mIsStarted(false), mBuffer(NULL), mSampleHandler(nullptr)
{
if (smInstantiated) {
ms_error("[MSWinRTDis] A video display filter is already instantiated. A second one can not be created.");
......@@ -240,30 +199,12 @@ MSWinRTDis::~MSWinRTDis()
int MSWinRTDis::activate()
{
if (!mIsInitialized) return -1;
if (mSampleHandler->PixFmt == MS_H264) mRfc3984Unpacker = rfc3984_new();
mIsActivated = true;
return 0;
}
int MSWinRTDis::deactivate()
{
if (mRfc3984Unpacker != nullptr) {
rfc3984_destroy(mRfc3984Unpacker);
mRfc3984Unpacker = nullptr;
}
if (mSPS) {
freemsg(mSPS);
mSPS = nullptr;
}
if (mPPS) {
freemsg(mPPS);
mPPS = nullptr;
}
if (mBitstream) {
ms_free(mBitstream);
mBitstream = nullptr;
}
mIsActivated = false;
return 0;
}
......@@ -272,7 +213,6 @@ void MSWinRTDis::start()
{
if (!mIsStarted && mIsActivated) {
mIsStarted = true;
//startMediaElement();
mSampleHandler->StartMediaElement();
}
}
......@@ -281,118 +221,39 @@ void MSWinRTDis::stop()
{
if (mIsStarted) {
mIsStarted = false;
mFirstFrameReceived = false;
//stopMediaElement();
mSampleHandler->StopMediaElement();
}
}
#if 0
void MSWinRTDis::startMediaElement()
{
if (mMediaElement != nullptr) {
VideoEncodingProperties^ videoEncodingProperties;
if (mPixFmt == MS_H264) {
videoEncodingProperties = VideoEncodingProperties::CreateH264();
videoEncodingProperties->Width = mWidth;
videoEncodingProperties->Height = mHeight;
}
else
videoEncodingProperties = VideoEncodingProperties::CreateUncompressed(MediaEncodingSubtypes::Nv12, mWidth, mHeight);
VideoStreamDescriptor^ videoStreamDescriptor = ref new VideoStreamDescriptor(videoEncodingProperties);
MediaStreamSource^ mediaStreamSource = mMediaStreamSource = ref new MediaStreamSource(videoStreamDescriptor);
mMediaStreamSource->SampleRequested += ref new Windows::Foundation::TypedEventHandler<Windows::Media::Core::MediaStreamSource ^, Windows::Media::Core::MediaStreamSourceSampleRequestedEventArgs ^>(mSampleHandler, &MSWinRTDisSampleHandler::OnSampleRequested);
Windows::UI::Xaml::Controls::MediaElement^ mediaElement = mMediaElement;
bool inUIThread = mMediaElement->Dispatcher->HasThreadAccess;
if (mMediaElement->Dispatcher->HasThreadAccess) {
// We are in the UI thread
_startMediaElement(mediaElement, mediaStreamSource);
} else {
// Ask the dispatcher to run this code in the UI thread
mMediaElement->Dispatcher->RunAsync(Windows::UI::Core::CoreDispatcherPriority::Normal, ref new Windows::UI::Core::DispatchedHandler([mediaElement, mediaStreamSource]() {
_startMediaElement(mediaElement, mediaStreamSource);
}));
}
}
}
void MSWinRTDis::stopMediaElement()
{
if (mMediaElement != nullptr) {
Windows::UI::Xaml::Controls::MediaElement^ mediaElement = mMediaElement;
MSWinRTDisSampleHandler^ sampleHandler = mSampleHandler;
if (mMediaElement->Dispatcher->HasThreadAccess) {
// We are in the UI thread
_stopMediaElement(mediaElement, sampleHandler);
} else {
// Ask the dispatcher to run this code in the UI thread
mMediaElement->Dispatcher->RunAsync(Windows::UI::Core::CoreDispatcherPriority::Normal, ref new Windows::UI::Core::DispatchedHandler([mediaElement, sampleHandler]() {
_stopMediaElement(mediaElement, sampleHandler);
}));
}
}
}
#endif
int MSWinRTDis::feed(MSFilter *f)
{
if (mIsStarted) {
mblk_t *im;
bool_t requestPLI = false;
while ((im = ms_queue_get(f->inputs[0])) != NULL) {
int size = 0;
if (mSampleHandler->PixFmt == MS_H264) {
MSQueue nalus;
ms_queue_init(&nalus);
requestPLI |= (rfc3984_unpack(mRfc3984Unpacker, im, &nalus) < 0);
if (!ms_queue_empty(&nalus)) {
bool need_reinit = false;
size = nalusToFrame(&nalus, &need_reinit);
if (need_reinit) {
mSampleHandler->RequestMediaElementRestart();
mFirstFrameReceived = true;
}
}
MSPicture buf;
ms_yuv_buf_init_from_mblk(&buf, im);
if ((buf.w != mSampleHandler->Width) || (buf.h != mSampleHandler->Height)) {
mSampleHandler->Width = buf.w;
mSampleHandler->Height = buf.h;
mSampleHandler->RequestMediaElementRestart();
if (mBuffer) ms_free(mBuffer);
}
else {
MSPicture buf;
ms_yuv_buf_init_from_mblk(&buf, im);
size = (buf.w * buf.h * 3) / 2;
if (!mBitstream) mBitstream = (uint8_t *)ms_malloc(size);
int ysize = buf.w * buf.h;
int usize = ysize / 4;
memcpy(mBitstream, buf.planes[0], ysize);
memcpy(mBitstream + ysize, buf.planes[2], usize);
memcpy(mBitstream + ysize + usize, buf.planes[1], usize);
freemsg(im);
#ifdef MS2_WINDOWS_PHONE
if ((mRenderer != nullptr) && ((buf.w != mWidth) || (buf.h != mHeight))) {
mWidth = buf.w;
mHeight = buf.h;
if (mFirstFrameReceived) {
stop();
start();
}
else {
Platform::String^ format = ref new Platform::String(L"YV12");
mRenderer->ChangeFormat(format, mWidth, mHeight);
}
}
#endif
}
if (mFirstFrameReceived && (size > 0)) {
size = (buf.w * buf.h * 3) / 2;
if (!mBuffer) mBuffer = (uint8_t *)ms_malloc(size);
int ysize = buf.w * buf.h;
int usize = ysize / 4;
memcpy(mBuffer, buf.planes[0], ysize);
memcpy(mBuffer + ysize, buf.planes[2], usize);
memcpy(mBuffer + ysize + usize, buf.planes[1], usize);
freemsg(im);
if (size > 0) {
ComPtr<VideoBuffer> spVideoBuffer = NULL;
MakeAndInitialize<VideoBuffer>(&spVideoBuffer, mBitstream, size);
MakeAndInitialize<VideoBuffer>(&spVideoBuffer, mBuffer, size);
mSampleHandler->Feed(VideoBuffer::GetIBuffer(spVideoBuffer), f->ticker->time);
}
}
if (requestPLI) {
ms_warning("[MSWinRTDis] Requesting PLI");
if (mAVPFEnabled) ms_filter_notify_no_arg(f, MS_VIDEO_DECODER_SEND_PLI);
else ms_filter_notify_no_arg(f, MS_VIDEO_DECODER_DECODING_ERRORS);
}
} else {
if (f->inputs[0] != NULL) {
ms_queue_flush(f->inputs[0]);
......@@ -419,176 +280,3 @@ void MSWinRTDis::setVideoSize(MSVideoSize vs)
mSampleHandler->Width = vs.width;
mSampleHandler->Height = vs.height;
}
int MSWinRTDis::nalusToFrame(MSQueue *nalus, bool *new_sps_pps)
{
mblk_t *im;
uint8_t *dst, *src, *end;
int nal_len;
bool start_picture = true;
uint8_t nalu_type;
if (!mBitstream) mBitstream = (uint8_t *)ms_malloc(mBitstreamSize);
dst = mBitstream;
*new_sps_pps = false;
end = mBitstream + mBitstreamSize;
while ((im = ms_queue_get(nalus)) != NULL) {
src = im->b_rptr;
nal_len = im->b_wptr - src;
if (dst + nal_len + 100 > end) {
int pos = dst - mBitstream;
enlargeBitstream(mBitstreamSize + nal_len + 100);
dst = mBitstream + pos;
end = mBitstream + mBitstreamSize;
}
if (src[0] == 0 && src[1] == 0 && src[2] == 0 && src[3] == 1) {
int size = im->b_wptr - src;
/* Workaround for stupid RTP H264 sender that includes nal markers */
memcpy(dst, src, size);
dst += size;
} else {
nalu_type = (*src) & ((1 << 5) - 1);
if (nalu_type == 7)
*new_sps_pps = checkSPSChange(im) || *new_sps_pps;
if (nalu_type == 8)
*new_sps_pps = checkPPSChange(im) || *new_sps_pps;
if (start_picture || nalu_type == 7/*SPS*/ || nalu_type == 8/*PPS*/ ) {
*dst++ = 0;
start_picture = false;
}
/* Prepend nal marker */
*dst++ = 0;
*dst++ = 0;
*dst++ = 1;
*dst++ = *src++;
while (src < (im->b_wptr - 3)) {
if (src[0] == 0 && src[1] == 0 && src[2] < 3) {
*dst++ = 0;
*dst++ = 0;
*dst++ = 3;
src += 2;
}
*dst++ = *src++;
}
*dst++ = *src++;
*dst++ = *src++;
*dst++ = *src++;
}
freemsg(im);
}
return dst - mBitstream;
}
void MSWinRTDis::enlargeBitstream(int newSize)
{
mBitstreamSize = newSize;
mBitstream = (uint8_t *)ms_realloc(mBitstream, mBitstreamSize);
}
bool MSWinRTDis::checkSPSChange(mblk_t *sps)
{
bool ret = false;
if (mSPS) {
ret = (msgdsize(sps) != msgdsize(mSPS)) || (memcmp(mSPS->b_rptr, mSPS->b_rptr, msgdsize(sps)) != 0);
if (ret) {
ms_message("[MSWinRTDis] SPS changed ! %i,%i", msgdsize(sps), msgdsize(mSPS));
updateSPS(sps);
updatePPS(nullptr);
}
} else {