Decoding H.264 stream from dvr - stream

I have a security DVR that uses h264 streams. I have been trying to get this to work with zoneminder. I have successfully logged into the dvr and recieved some form of data streams. The data stream is dumped to a fifo/pipe, and then zoneminder uses ffmpeg to read this in.
Note: i know very very little about h.264 streams. just enough to be stupid.
The video only updates about every 15 seconds in ZM. I can dump the stream to a file with ffmpeg or avconv (avconv -i /tmp/mypipe cam.mp4) but it is still not right. However, the file created by avconv is WAY WAY better than the one created by ffmpeg.
I've included a link to the wireshark dump (I did change the PW and login info, etc...). From the data, It appears that the dvr is adding a header to the h264 data streams. I understand that the h264 stream starts with a (0x00 00 01 67) or (0x00 00 01 61). Here is an example of the header plus start of stream:
0x33, 0x30, 0x64, 0x63, 0x48, 0x32, 0x36, 0x34,
0x3f, 0x55, 0x00, 0x00, 0x08, 0x00, 0x20, 0x00,
0xa2, 0x7a, 0xea, 0xdc, 0xcf, 0x08, 0x00, 0x00,
0x0d, 0x0a, 0x11, 0x07, 0x13, 0x20, 0x00, 0x00,
0x00, 0x00, 0x00, 0x01, 0x67, 0x42, 0xe0, 0x14,
0xdb, 0x05, 0x87, 0xc4, 0x00, 0x00, 0x00, 0x01,
0x68, 0xce, 0x30, 0xa4, 0x80, 0x00, 0x00, 0x00,
0x01, 0x06, 0xe5, 0x01, 0x51, 0x80, 0x00, 0x00,
0x00, 0x01, 0x65, 0xb8, 0x00, 0x01, 0xa8, 0xac,
I can see that there are a few frame indicators in this message. The DVR's header appears to be 32 bytes long in this case, and in some other messages in the dump, it appears to be 24 bytes long. I am striping the header off before I dump the stream to the pipe. (I have verified the output doesn't include the dvr's headers in any way.
What I would like help with is determining what I should be sending to the pipe. should I start with the first h.264 key? Is there something out of order? I'm very surprised that ffmpeg is only getting 15 second updates, but avconv is much better (lots of dropped frames, and playback is "sped up".
using ffmpeg to read the pipe produces a file that shows it's codec as: H264 - MPEG-4 AVC (part 10) (avc1) with a Decoded format: Planar 4:2:0 YUV using vlc.
Appreciate any help you can provide!
Wireshark h264 dump
edit: on Ubuntu 13.04
ffmpeg version: 6:0.8.6-1ubuntu2
avconv 0.8.6-6:0.8.6-1ubuntu2

Related

Toggle virtual keyboard with Bluetooth HID

I am developing a HID device on the NRF52810.
After testing the work of HID on IOS, I found out that the virtual keyboard disappears when the HID device is connected and it is impossible to return it to the iphone.
After reading the documentation for the HID, I did not find the right command.
I found a BLE keyboard that has this key to enable the virtual keyboard. After testing the keyboard, I found out the following things:
1) On windows, this button launches the context menu, key code 0x65
2) On android, this button launches the context menu
3) On ios, hides and opens the virtual keyboard
I tried to send this code (0x65) through my device. And as expected on windows and android opens a context menu. However, on ios it is not recognized. The keyboard does not appear, programs see the key as undefined.
Does anyone know what the problem is? What code do I need to send to IOS to open the virtual keyboard? Can there be a problem in the HID descriptor?
0x05, 0x01, // Usage Page (Generic Desktop)
0x09, 0x06, // Usage (Keyboard)
0xA1, 0x01, // Collection (Application)
0x85, 0x01, // Report id(1)
0x15, 0x00, // Logical Minimum (0)
0x25, 0x01, // Logical Maximum (1)
0x95, 0x05, // Report Count (5)
0x75, 0x01, // Report Size (1)
0x05, 0x08, // Usage Page (Page# for LEDs)
0x19, 0x01, // Usage Minimum (1)
0x29, 0x05, // Usage Maximum (5)
0x91, 0x02, // Output (Data, Variable, Absolute), Led report
0x95, 0x01, // Report Count (1)
0x75, 0x03, // Report Size (3)
0x91, 0x01, // Output (Data, Variable, Absolute), Led report padding
0x95, 0x04, // Report Count (5)
0x75, 0x08, // Report Size (8)
0x15, 0x00, // Logical Minimum (0)
0x25, 0xFF, // Logical Maximum (255)
0x05, 0x07, // Usage Page (Key codes)
0x19, 0x00, // Usage Minimum (0)
0x29, 0xFF, // Usage Maximum (255)
0x81, 0x00, // Input (Data, Array) Key array(6 bytes)
0xC0, // End Collection (Application)
0x05, 0x01, // Usage Page (Desktop),
0x09, 0x80, // Usage (Generic Desktop),
0xA1, 0x01, // Collection (Application),
0x85, 0x02, // Report id(2)
0x75, 0x01, // Report Size (1)
0x95, 0x08, // Report Count (8)
0x15, 0x00, // Logical Minimum (0)
0x25, 0x01, // Logical Maximum (1)
0x09, 0x81, // Usage (System Power Down)
0x09, 0x82, // Usage (System Sleep)
0x09, 0x83, // Usage (System Wake Up)
0x09, 0x84, // Usage (System Context Menu)
0x09, 0x85, // Usage (System Main Menu)
0x09, 0x86, // Usage (System App Menu)
0x09, 0x87, // Usage (System Menu Help)
0x09, 0x88, // Usage (System Menu Exit)
0x81, 0x02, // Input (Data,Var,Abs,NWrp,Lin,Pref,NNul,Bit)
0xC0, // End Collection,
I realise this was asked 9 months ago, but I wanted to add the answer anyway since I was trying to do the same and figured it out recently. I managed it using the Consumer Control usage page, with the specific usage:
0x0A, 0xAE, 0x01, // Usage (AL Keyboard Layout)
For more information, see HID Usage Tables section 15.15.

UInt8 from Swift to Objective-C

I need a clarification. I'm following a tutorial on Hash sha256 in Swift and my app is in Objective-C. I have trouble translating this UInt8 in Objective-C. What is the equivalent in Objective-C?
let rsa2048Asn1Header:[UInt8] = [
0x30, 0x82, 0x01, 0x22, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86,
0xf7, 0x0d, 0x01, 0x01, 0x01, 0x05, 0x00, 0x03, 0x82, 0x01, 0x0f, 0x00
]
I tried this but I'm not sure it's right I'd like to have confirmation
UInt8 rsa2048AsnlHeader[] = {
0x30, 0x82, 0x01, 0x22, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86,
0xf7, 0x0d, 0x01, 0x01, 0x01, 0x05, 0x00, 0x03, 0x82, 0x01, 0x0f, 0x00};
Yes what you posted above would work if you're just looking to use a primitive array in Objective-C.
Another option would be to use NSArray, shown below:
NSArray<NSNumber *> *rsa2048AsnlHeader = #[
#0x30, #0x82, #0x01, #0x22, #0x30, #0x0d, #0x06, #0x09, #0x2a, #0x86, #0x48, #0x86,
#0xf7, #0x0d, #0x01, #0x01, #0x01, #0x05, #0x00, #0x03, #0x82, #0x01, #0x0f, #0x00
];
To get the equivalent UInt8 value from the NSNumber elements, use the unsignedCharValue property of the NSNumber class (which is equivalent to uint8Value in Swift). For example:
for (NSNumber *value in rsa2048AsnlHeader) {
UInt8 uint8Value = value.unsignedCharValue;
// ...
}
Source

convert c char to swift

I am trying to conver the following code to swift:
static unsigned char rsa2048Asn1Header[] = {
0x30, 0x82, 0x01, 0x22, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86,
0xf7, 0x0d, 0x01, 0x01, 0x01, 0x05, 0x00, 0x03, 0x82, 0x01, 0x0f, 0x00
};
static unsigned char rsa4096Asn1Header[] = {
0x30, 0x82, 0x02, 0x22, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86,
0xf7, 0x0d, 0x01, 0x01, 0x01, 0x05, 0x00, 0x03, 0x82, 0x02, 0x0f, 0x00
};
static unsigned char ecDsaSecp256r1Asn1Header[] = {
0x30, 0x59, 0x30, 0x13, 0x06, 0x07, 0x2a, 0x86, 0x48, 0xce, 0x3d, 0x02,
0x01, 0x06, 0x08, 0x2a, 0x86, 0x48, 0xce, 0x3d, 0x03, 0x01, 0x07, 0x03,
0x42, 0x00
};
static unsigned char *asn1HeaderBytes[3] = { rsa2048Asn1Header, rsa4096Asn1Header, ecDsaSecp256r1Asn1Header };
static unsigned int asn1HeaderSizes[3] = { sizeof(rsa2048Asn1Header), sizeof(rsa4096Asn1Header), sizeof(ecDsaSecp256r1Asn1Header) };
My swift code looks like this:
let rsa2048Asn1Header:[CUnsignedChar] = [0x30, 0x82, 0x01, 0x22, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d,0x01, 0x01, 0x01, 0x05, 0x00, 0x03, 0x82, 0x01, 0x0f, 0x00]
let rsa4096Asn1Header:[CUnsignedChar] = [0x30, 0x82, 0x01, 0x22, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x01, 0x05, 0x00, 0x03, 0x82, 0x01, 0x0f, 0x00]
let ecDsaSecp256r1Asn1Header:[CUnsignedChar] = [0x30, 0x59, 0x30, 0x13, 0x06, 0x07, 0x2a, 0x86, 0x48, 0xce, 0x3d, 0x02, 0x01, 0x06, 0x08, 0x2a, 0x86, 0x48, 0xce, 0x3d, 0x03, 0x01, 0x07, 0x03, 0x42, 0x00]
let asn1HeaderBytes:[[CUnsignedChar]] = [rsa2048Asn1Header, rsa4096Asn1Header, ecDsaSecp256r1Asn1Header]
let asn1HeaderSizes:[UInt] = [sizeof(rsa2048Asn1Header.dynamicType).toUInt, sizeof(rsa4096Asn1Header.dynamicType).toUInt, sizeof(ecDsaSecp256r1Asn1Header.dynamicType).toUInt]
However i failing at his badly, per example using rsa2048Asn1Header and converting it to NSData:
let data:NSData = NSData(bytes: rsa2048Asn1Header, length:strideofValue(rsa2048Asn1Header))
swift prints with length 8:
<30820122 300d0609>
objc for the following code:
[NSData dataWithBytes:rsa2048Asn1Header length:sizeof(rsa2048Asn1Header)];
prints
<30820122 300d0609 2a864886 f70d0101 01050003 82010f00> size: 24
looking at apple documentation, strideOfvalue should return the right size for each one of those [CUnsignedChar] but that doesnt seem to be the case, my question is shouldnt a [CUnsignedChar] have same size as usigned char [] in objc, if not what could i use to change?
also [[CUnsignedChar]] makes no sense whatsoever in my head, how would the code below convert to swift, should i convert those arrays to an NSString and extract the CString when required, if so what encoding should I use?
static unsigned char *asn1HeaderBytes[3] = { rsa2048Asn1Header, rsa4096Asn1Header, ecDsaSecp256r1Asn1Header };
I don't think strideofValue is the function you are looking for. I haven't heard of it before, but the documentation states:
Returns the least possible interval between distinct instances of T in memory. The result is always positive.
If this is returning 8, that means that the minimum distance between [CUnsignedChar]s in memory is 8 bytes.
To use NSData(data:length:) properly, the second parameter needs to be the size of the array. You can use the count property for this:
let data: NSData = NSData(bytes: rsa2048Asn1Header, length:rsa2048Asn1Header.count)
[[CUnsignedChar]] is an array of arrays (two-dimensional array) of CUnsignedChar.
Your headers are raw bytes, so technically no encoding is 'correct' to convert to NSString. The cryptographic headers you have don't appear to be strings, and contain unprintable characters.
You should not use strideofValue function. 'strideofValue' it's not a replacement for 'sizeof'. Just go for ".count" property.

Using the iOS9 Compression Framework in Swift2

I have some NSData that is stored with the DEFLATE compression protocol?
DEFLATE Compression Method DEFLATE is a lossless compressed data
format that compresses data using a combination of the LZ77 algorithm
and Huffman coding, with efficiency comparable to the best currently
available general-purpose compression methods. The data can be
produced or consumed, even for an arbitrarily long sequentially
presented input data stream, using only a priority-bounded amount of
intermediate storage. The format can be implemented readily in a
manner not covered by patents. Specifications for DEFLATE can be found
in RFC 1951 - DEFLATE Compressed Data Format Specification, May 1996.
If I understand it correctly in IOS9 there is a new Compression Framework which "might" handle this case. The documentation lists the following supported algorithms: LZFSE, LZ4, LZMA, and ZLIB level 5.
I'm not sure but I believe ZLIB supports the LZ77 Deflate algorithm. The question I have is how do I actually use this framework:
So I believe the function i want to use is compression_decode_buffer
#available(iOS 9.0, *)
public func compression_decode_buffer(
dst_buffer: UnsafeMutablePointer<UInt8>,
_ dst_size: Int,
_ src_buffer: UnsafePointer<UInt8>,
_ src_size: Int,
_ scratch_buffer: UnsafeMutablePointer<Void>,
_ algorithm: compression_algorithm) -> Int
but I'm not sure exactly how to utilize this algorithm.
So from reading the header it looks like i need an input size dst_size: bytes.size and output size a inputBuffer an &outputbuffer and a compression algorithm
dst_buffer: UnsafeMutablePointer,
_ dst_size: Int,
_ src_buffer: UnsafePointer,
_ src_size: Int,
_ scratch_buffer: UnsafeMutablePointer,
_ algorithm: compression_algorithm) -> Int
Assuming i have some sample data (see below)
let bytes : [UInt8] = [ .... ] // see below
compression_decode_buffer(
<DST_BUFFER>,
<DST_SIZE>,
bytes,
bytes.count,
<SCRATCH_BUFFER>,
COMPRESSION_ZLIB
)
Where i'm at a loss is as to what goes into <DST_BUFFER>, <DST_SIZE>, <SCRATCH_BUFFER>.
Any suggestions?
Sample Data
let bytes : [UInt8] = [0x7e, 0x07, 0x07, 0xff, 0xff, 0x41, /* <1~....A */
0x10, 0x33, 0x51, 0x3e, 0x94, 0xb2, 0xa0, 0x27, /* .3Q>...' */
0x80, 0x00, 0x21, 0x65, 0x26, 0xd8, 0x22, 0x10, /* ..!e&.". */
0x2c, 0xd5, 0x99, 0x00, 0x00, 0x44, 0xbb, 0xd4, /* ,....D.. */
0x54, 0x38, 0xf5, 0x01, 0x36, 0xd1, 0x20, 0x2c, /* T8..6. , */
0xd5, 0x99, 0xbb, 0x1c, 0xaf, 0xc3, 0x2c, 0x60, /* ......,` */
0xcb, 0x0c, 0x79, 0xcb, 0x76, 0xa0, 0x84, 0xd5, /* ..y.v... */
0x99, 0x83, 0x1c, 0xaf, 0xc3, 0x2c, 0x60, 0x35, /* .....,`5 */
0x66, 0x60, 0x49, 0x76, 0x60, 0xc7, 0x5b, 0xf3, /* f`Iv`.[. */
0xce, 0x05, 0x08, 0x3a, 0x04, 0x13, 0x4a, 0x00, /* ...:..J. */
0x92, 0x05, 0x08, 0x17, 0x14, 0x68, 0x31, 0xc3, /* .....h1. */
0x1c, 0xb2, 0xc3, 0x1e, 0x72, 0xdd, 0xe0, 0x00, /* ....r... */
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* ........ */
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* ........ */
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* ........ */
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* ........ */
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* ........ */
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* ........ */
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* ........ */
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* ........ */
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* ........ */
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* ........ */
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* ........ */
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* ........ */
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* ........ */
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* ........ */
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* ........ */
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* ........ */
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* ........ */
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* ........ */
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* ........ */
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* ........ */
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* ........ */
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* ........ */
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* ........ */
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* ........ */
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* ........ */
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* ........ */
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* ........ */
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* ........ */
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* ........ */
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* ........ */
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* ........ */
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* ........ */
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* ........ */
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* ........ */
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* ........ */
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* ........ */
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* ........ */
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* ........ */
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* ........ */
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* ........ */
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* ........ */
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* ........ */
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* ........ */
0x00, 0x00, 0x00, 0x00, 0x27, 0x00, 0x00, 0x00, /* ....'... */
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, /* .......0 */
0x8e, 0x7e]
Generally compression_decode_buffer() is used like this:
import Compression
let bytes : [UInt8] = [ .... ] // Compressed data
var dst = [UInt8](count: 1000, repeatedValue: 0) // destination buffer
let size = compression_decode_buffer(&dst, dst.count, bytes, bytes.count, nil, COMPRESSION_ZLIB)
The destination buffer must be large enough for the decompressed data.
On return, size is the number of bytes that were written to the
destination buffer (or zero if the decompression failed).
(There is also a "streaming" interface
compression_stream_init()
compression_stream_process()
compression_stream_destroy()
which can be used to process the data in chunks.)
However, I tried to decompress your data with all available
COMPRESSION_XXX methods without success.
From my experiments it seems that COMPRESSION_ZLIB corresponds
to the "raw deflate" method, i.e. what you get with the zlib
deflateInit2() function if the windowBits parameter is set
to a negative value.

avcodec_decode_audio4 decoded data different on device and simulator

I'm having issues where the decoded audio sounds punchy/garbled simply can't tell what is being heard when decoded on an iPhone/iPad device. However, when decoding the audio on simulator the audio is perfect.
I do realize emulator runs on a different CPU architecture i386 while actual device is ARMv7 so the issue could be something around that.
I have printed the compressed data on device and simulator before being decoded and it matches. Then I printed the decoded data for device and simulator and they are different. That leads me to think something is happening with the decoder. I can see that it is not a byte swap issue since the data is just completely different.
Any ideas on what I could or look into? I don't have this issue on Android...
First decoded audio frame.
DEVICE:
0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x70, 0x08, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0xda, 0x0a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
EMULATOR:
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
UPDATE 1
I was able to resolve the issue by disabling asm with --disable-asm. Something must not be working correctly with the ARM asm files.

Resources