mirror of
https://github.com/moonlight-stream/moonlight-ios.git
synced 2026-04-08 00:46:02 +00:00
Video is mostly working now. It's just chopped off in the view now.
This commit is contained in:
@@ -13,17 +13,20 @@
|
||||
Boolean waitingForSps, waitingForPpsA, waitingForPpsB;
|
||||
|
||||
NSData *spsData, *ppsDataA, *ppsDataB;
|
||||
unsigned char ppsDataAFirstByte;
|
||||
CMVideoFormatDescriptionRef formatDesc;
|
||||
}
|
||||
|
||||
- (id)init
|
||||
- (id)initWithView:(UIView*)view
|
||||
{
|
||||
self = [super init];
|
||||
|
||||
displayLayer = [[AVSampleBufferDisplayLayer alloc] init];
|
||||
displayLayer.bounds = CGRectMake(0, 0, 300, 300);
|
||||
displayLayer.backgroundColor = [UIColor blackColor].CGColor;
|
||||
displayLayer.position = CGPointMake(500, 500);
|
||||
displayLayer.bounds = view.bounds;
|
||||
displayLayer.backgroundColor = [UIColor greenColor].CGColor;
|
||||
displayLayer.position = CGPointMake(CGRectGetMidX(view.bounds), CGRectGetMidY(view.bounds));
|
||||
displayLayer.videoGravity = AVLayerVideoGravityResize;
|
||||
[view.layer addSublayer:displayLayer];
|
||||
|
||||
// We need some parameter sets before we can properly start decoding frames
|
||||
waitingForSps = true;
|
||||
@@ -34,7 +37,6 @@
|
||||
}
|
||||
|
||||
#define ES_START_PREFIX_SIZE 4
|
||||
#define ES_DATA_OFFSET 5
|
||||
- (void)submitDecodeBuffer:(unsigned char *)data length:(int)length
|
||||
{
|
||||
unsigned char nalType = data[ES_START_PREFIX_SIZE] & 0x1F;
|
||||
@@ -42,23 +44,24 @@
|
||||
|
||||
if (formatDesc == NULL && (nalType == 0x7 || nalType == 0x8)) {
|
||||
if (waitingForSps && nalType == 0x7) {
|
||||
spsData = [NSData dataWithBytes:&data[ES_DATA_OFFSET] length:length - ES_DATA_OFFSET];
|
||||
NSLog(@"Got SPS");
|
||||
spsData = [NSData dataWithBytes:&data[ES_START_PREFIX_SIZE] length:length - ES_START_PREFIX_SIZE];
|
||||
waitingForSps = false;
|
||||
}
|
||||
// Nvidia's stream has 2 PPS NALUs so we'll wait for both of them
|
||||
else if ((waitingForPpsA || waitingForPpsB) && nalType == 0x8) {
|
||||
// Read the NALU's PPS index to figure out which PPS this is
|
||||
if (data[ES_DATA_OFFSET] == 0) {
|
||||
if (waitingForPpsA) {
|
||||
ppsDataA = [NSData dataWithBytes:&data[ES_DATA_OFFSET] length:length - ES_DATA_OFFSET];
|
||||
waitingForPpsA = false;
|
||||
}
|
||||
printf("PPS BYTE: %02x", data[ES_START_PREFIX_SIZE + 1]);
|
||||
if (waitingForPpsA) {
|
||||
NSLog(@"Got PPS 1");
|
||||
ppsDataA = [NSData dataWithBytes:&data[ES_START_PREFIX_SIZE] length:length - ES_START_PREFIX_SIZE];
|
||||
waitingForPpsA = false;
|
||||
ppsDataAFirstByte = data[ES_START_PREFIX_SIZE + 1];
|
||||
}
|
||||
else if (data[ES_DATA_OFFSET] == 1) {
|
||||
if (waitingForPpsB) {
|
||||
ppsDataA = [NSData dataWithBytes:&data[ES_DATA_OFFSET] length:length - ES_DATA_OFFSET];
|
||||
waitingForPpsB = false;
|
||||
}
|
||||
else if (data[ES_START_PREFIX_SIZE + 1] != ppsDataAFirstByte) {
|
||||
NSLog(@"Got PPS 2");
|
||||
ppsDataA = [NSData dataWithBytes:&data[ES_START_PREFIX_SIZE] length:length - ES_START_PREFIX_SIZE];
|
||||
waitingForPpsB = false;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -67,8 +70,9 @@
|
||||
const uint8_t* const parameterSetPointers[] = { [spsData bytes], [ppsDataA bytes], [ppsDataB bytes] };
|
||||
const size_t parameterSetSizes[] = { [spsData length], [ppsDataA length], [ppsDataB length] };
|
||||
|
||||
NSLog(@"Constructing format description");
|
||||
status = CMVideoFormatDescriptionCreateFromH264ParameterSets(kCFAllocatorDefault,
|
||||
3, /* count of parameter sets */
|
||||
2, /* count of parameter sets */
|
||||
parameterSetPointers,
|
||||
parameterSetSizes,
|
||||
4 /* size of length prefix */,
|
||||
@@ -89,6 +93,11 @@
|
||||
return;
|
||||
}
|
||||
|
||||
if (nalType != 0x1 && nalType != 0x5) {
|
||||
// Don't submit parameter set data
|
||||
return;
|
||||
}
|
||||
|
||||
// Now we're decoding actual frame data here
|
||||
CMBlockBufferRef blockBuffer;
|
||||
status = CMBlockBufferCreateWithMemoryBlock(NULL, data, length, kCFAllocatorNull, NULL, 0, length, 0, &blockBuffer);
|
||||
@@ -98,7 +107,9 @@
|
||||
}
|
||||
|
||||
// Compute the new length prefix to replace the 00 00 00 01
|
||||
const uint8_t lengthBytes[] = {(uint8_t)(length >> 24), (uint8_t)(length >> 16), (uint8_t)(length >> 8), (uint8_t)length};
|
||||
int dataLength = length - ES_START_PREFIX_SIZE;
|
||||
const uint8_t lengthBytes[] = {(uint8_t)(dataLength >> 24), (uint8_t)(dataLength >> 16),
|
||||
(uint8_t)(dataLength >> 8), (uint8_t)dataLength};
|
||||
status = CMBlockBufferReplaceDataBytes(lengthBytes, blockBuffer, 0, 4);
|
||||
if (status != noErr) {
|
||||
NSLog(@"CMBlockBufferReplaceDataBytes failed: %d", (int)status);
|
||||
@@ -120,12 +131,22 @@
|
||||
|
||||
CFArrayRef attachments = CMSampleBufferGetSampleAttachmentsArray(sampleBuffer, YES);
|
||||
CFMutableDictionaryRef dict = (CFMutableDictionaryRef)CFArrayGetValueAtIndex(attachments, 0);
|
||||
CFDictionarySetValue(dict, kCMSampleAttachmentKey_DisplayImmediately, kCFBooleanTrue);
|
||||
|
||||
dispatch_async(dispatch_get_main_queue(),^{
|
||||
[displayLayer enqueueSampleBuffer:sampleBuffer];
|
||||
[displayLayer setNeedsDisplay];
|
||||
});
|
||||
CFDictionarySetValue(dict, kCMSampleAttachmentKey_DisplayImmediately, kCFBooleanTrue);
|
||||
CFDictionarySetValue(dict, kCMSampleAttachmentKey_IsDependedOnByOthers, kCFBooleanTrue);
|
||||
|
||||
if (nalType == 1) {
|
||||
// P-frame
|
||||
CFDictionarySetValue(dict, kCMSampleAttachmentKey_NotSync, kCFBooleanTrue);
|
||||
CFDictionarySetValue(dict, kCMSampleAttachmentKey_DependsOnOthers, kCFBooleanTrue);
|
||||
}
|
||||
else {
|
||||
// I-frame
|
||||
CFDictionarySetValue(dict, kCMSampleAttachmentKey_NotSync, kCFBooleanFalse);
|
||||
CFDictionarySetValue(dict, kCMSampleAttachmentKey_DependsOnOthers, kCFBooleanFalse);
|
||||
}
|
||||
|
||||
[displayLayer enqueueSampleBuffer:sampleBuffer];
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
Reference in New Issue
Block a user