FFmpeg can't decode H264 stream/frame data - stream

Recently I had chance to work with two devices that are streaming the H264 through RTSP.
And I've ran into some problem trying to decompress this stream using FFmpeg library.
Every time the "avcodec_decode_video2" is called - FFmpeg just says something like:
[h264 # 00339220] no frame!
My raw H264 stream I frame data starts like this: "65 88 84 21 3F F8 F8 0D..."
(as far as I understand this 0x65 indicates that it's a IDR frame?)
Other frames for one device starts like: "41 9A 22 07 F3 4E 48 CC...."
and for other device - like this: "61 9A 25 C1 1C 45 62 39...."
Am I missing some frame data here?
Does FFmpeg needs to have some extra parameters set up?
I was expecting at least "00 00 00 01" bytes at the start for the frame data... but this is what I've got..

Ok, managed to make things working.
I needed to include the sequence (SPS) and picture parameter sets
(PPS) for my frame data before sending frame to the FFmpeg.
I needed to add 4 extra bytes "00 00 00 01" after SPS and PPS data.
Here is a little picture showing what I mean:
Bytes "65 88..." is where my original frame data begins.
This SPS and PPS information was not included in RTP packet. I'm using Live555 library for RTSP streaming, so I've used subsessions "fmtp_spropparametersets" function to get what I need. This information was Base64 encoded. (Sample: Something like this "Z0KAKNoC0EkQ,aM48gA==") Note that there are two "parameters" SPS and PPS seperated by "," and those parameters doesn't have a "00 00 00 01" included, so you need to add them.
Some code sample (I'm using Qt library here):
QByteArray ba = pSubSession->fmtp_spropparametersets();
QList<QByteArray> recordsList = ba.split(',');
for (int i = 0; i < recordsList.size(); i++)
{
mExtraData.append(char(0x00));
mExtraData.append(char(0x00));
mExtraData.append(char(0x00));
mExtraData.append(char(0x01));
mExtraData += QByteArray::fromBase64(recordsList.at(i));
}
Now for every frame I do something like this:
QByteArray ba = QByteArray(4, 0); // Prepare the "00 00 00 01"
ba[3] = 0x01;
mpTrackVideo->buffer.insert(0, mExtraData);
mpTrackVideo->buffer.insert(mExtraData.size(), ba);
Year ago I thought I had H264 stream support integrated in my project till I've had chance to test it with some other devices...
So you need to keep in mind that some devices might send SPS and PPS data for every I frame... and some might not!

Related

problem computing/parsing oggs/opus audio files header

I am reading an ogg audio file header and am having some difficulty understanding how to compute the location of the next ogg file segment. i was able to use this webpage as an example: https://www.file-recovery.com/ogg-signature-format.htm using this example.ogg file i was able to compute the right locations of the oggs headers.
BUT... in the example link, at offset (dec) 128 + 1 there is FF FF FF FF FF FF FF FF FF FF FF FF B6 and calculating this is simple, 12*255 = 3060, 3060 + 182 (hex B6) = 3242, 3242 + 1 + 13 + 128 = 3384. so from the start of the last read header 0x3A (dec 58), if i seek a total of 3384 bytes, i am exactly at the spot of the next ogg file header.
now, where my problem comes in is this. in a real ogg/opus file, the values to calculate where the next ogg header are slightly confusing me. here is an image hopefully it will make it a little easier to get my problem across.
i am not sure how to proceed here. 0x48 = dec 72. so i would assume that there are 72 records here that are 3 bytes long each? that doesnt make sense. Or would it be 72 records, and the 0x03 at offset 0xAC is just part of the calculation? this is confusing to me, and i am not sure if i am asking the question right. but what i am trying to do is just parse the whole ogg file from top to bottom. im not looking to do any sort of processing at each header (yet) and i just need to fogire out the correct way to calculate these ogg header/segment location. if i need to elaborate on anything please ask and i will do my best. thanks in advance
i was able to figure this out. was just a simple misunderstanding on my part. when you read (as in the example above) 0x48 = dec 72. next add current position in file, then add 72 to that, then add/sum the next 72 characters, whatever they may be. this will give you the offset ((from the beginning of the file) of the next ogg entry

How to filter MQTT traffic on base of topic name in tcpdump

I am capturing MQTT traffic for troubleshooting using below command
tcpdump -i team0 -w mqtt-trace.pcap src 10.x.x.x
But it results in very big file within minutes, Can i filter tcpdump on base of topic name
Following is tcp payload, I want it only capture payload which has PKGCTRL/1/status/frequency or if tcpdump can directly support filter on application layer protocol like wireshark mqtt.topic == PKGCTRL/1/status/frequency
0000 00 13 95 36 2e ef 00 10 7e 07 87 3d 08 00 45 00 ...6....~..=..E.
0010 00 77 2e 0d 40 00 40 06 f6 78 0a 0b 80 f3 0a 0b .w..#.#..x......
0020 80 f2 c3 6a 75 83 e4 f8 f7 7a 0a 89 67 76 50 18 ...ju....z..gvP.
0030 ea 60 59 f8 00 00 30 4d 00 1a 50 4b 47 43 54 52 .`Y...0M..PKGCTR
0040 4c 2f 31 2f 73 74 61 74 75 73 2f 66 72 65 71 75 L/1/status/frequ
0050 65 6e 63 79 0a 11 09 c2 7a 85 14 d0 71 37 16 12 ency....z...q7..
0060 06 08 01 10 01 18 00 12 1c 0a 0d 09 0b 46 25 75 .............F%u
0070 02 f2 48 40 10 21 18 00 11 00 60 76 14 d0 71 37 ..H#.!....`v..q7
0080 16 20 00 28 00 . .(.
I don't think the previously accepted answer necessarily does what you think it does and possibly not even what you want it to do. The original question stated, "But it results in very big file within minutes, Can i filter tcpdump on base of topic name"
If you're trying to limit the size of the capture file, then the previously accepted answer isn't doing that because it uses the exact same capture filter as was originally provided, namely src 10.x.x.x. This means that you're capturing the same amount of data as you were before. Just because a capture file name wasn't specified doesn't mean that packets aren't being written to a file; they are. In the case of tshark, packets are written to a temporary file, which will continue to grow until the capture session is terminated and then ideally it will be deleted, but not always. The location of the temporary file varies depending on the platform that tshark is run on, but you should be able to easily locate the directory by running tshark -G folders | grep "^Temp".
Now, if you want to reduce the size of the capture file, or the number of packets that you see, then you should be able to modify the tcpdump or tshark command-line arguments to accomplish that.
First off, if you don't need the entire payload, you can apply a snaplen to cut the packets short after some appropriate value. This is done using the -s option, and it's the same option for either capture tool.
OK, but whether you decide to apply a snaplen or not, if you want to filter based on the specific topic name, most likely you can achieve this; however there are a couple of caveats that I listed below. The main idea is to use the slice operator, [] (see the pcap-filter man page) to compare various bytes of the TCP payload to specific values. (NOTE: Neither tcpdump itself nor pcap-filter refers to this operator as the slice operator, but wireshark-filter does, so I do as well.) So the filter should:
Match packets only to/from a particular host, in this case 10.x.x.x
Match only MQTT packets (typically by port number, which I'll assume to be the standard tcp/1883 port)
Match only PUBLISH messages with QoS 0
Match only PUBLISH messages where the topic length is 26 bytes
Match only PUBLISH messages where the topic is "PKGCTRL/1/status/frequency"
Here's a command that should work (at least in most cases -> see caveats below):
tcpdump -i team0 -w mqtt-trace.pcap \
"(src host 10.x.x.x) and \
(tcp port 1883) and \
((tcp[20]&0xf6)=0x30) and \
(tcp[22:2]=26) and \
(tcp[24:4]=0x504b4743 and tcp[28:4]=0x54524c2f and \
tcp[32:4]=0x312f7374 and tcp[36:4]=0x61747573 and \
tcp[40:4]=0x2f667265 and tcp[44:4]=0x7175656e and tcp[48:2]=0x6379)"
It should be obvious from the description of the desired filter above what each separate component of the filter is doing for you.
Here, you'll end up with a capture file of the desired packets that you can reference later on if you need to. You can even apply this same filter to the tshark solution too if you prefer as well as writing to the named capture file, because as I explained earlier, tshark is writing packets to a file whether you explicitly specify one or not.
Caveats:
The filter assumes TCP headers are 20 bytes for simplicity in illustrating the solution, but that may not be the case. If you want a more robust solution to accommodate any TCP header size, then you'll need to determine the TCP header size from the data offset field of the TCP header, which is done in the filter using ((tcp[12]&0xf0)>>4)*4, and then replace every occurrence of 20 in the slice operator's offset field with that value. So for example, tcp[22:2]=26 becomes tcp[(((tcp[12]&0xf0)>>4)*4)+2:2]=26, etc.
Because the MQTT remaining message length field is variable-length encoded per MQTT3.1.1 section 2.2.3 Remaining Length, the filter, as provided above, will only work for values of the remaining length field from 0 to 127, i.e., the remaining length field must only be a single byte. Given that the topic in this case is 26 bytes and the topic length itself is 2 bytes, this means the filter will only work for MQTT message payloads of 99 bytes or less (127 - (2 + 26)).
As #hardillb suggested, use tshark instead. Due to tshark's architecture, you can't write a file at the same time as a display filter (it would be too slow).
To get the information you need, it would look something like this
$ tshark -i team0 -f "src 10.x.x.x" \
-Y "mqtt.topic == PKGCTRL/1/status/frequency" -T fields -e mqtt.topic
-i team0: Filter on interface team0
-f "src 10.x.x.x": Use a capture filter, which is the same as tcpdump's filtering. This will speed up processing as it's faster than a display filter (next bullet).
-Y "mqtt.topic == PKGCTRL/1/status/frequency": Filter for packets that match this display filter
-T fields -e mqtt.topic: Output only the mqtt.topic field, as that is the target information.
-T fields will output columnar data vertically delimited by newlines. It won't be horizontally delimited because there is only column, but the default is \t.

Parsing variable byte length message

I'd like to parse a proprietary message with the following format. The messages are of variable length from 8bytes to 16 bytes. If the message is more than 8 bytes, it is put into multi packet message.
Byte0 Byte1 Byte2 Byte3 Byte4 Byte5 Byte6 Byte7-14 Byte15
Header Header Flags SlaveID Sequence Command Command Data Chksum
I send these messages to a device and expect a response from said device with similar format. I know what the messages are supposed to say, but I'm really struggling to find a away to parse the data in real time and display the information in somesort of GUI framework. Currently, I'm planning on dumping the data into a .txt/.csv file and post-processing with matlab.
I'm a hardware guy. This is not my strong suit.
Example:
Command, Reponse
0xAC 04 01 01 00 8C 01 01 chksum
0x04 AC 83 01 00 8C 01 01 0B D9 chksum
0x8c01 command to test power supply 0x01
Device echos the command and power supply it was checking and also returns the bit-shifted value of the power supply voltage 0x0BD9

midi file parsing, unrecognised event type

I have a problem trying to parse a midi file. I am trying to parse the notes files used by the frets on fire game (it just uses midi files so i don't think this is relevent) if any of you are familiar with it, the problem i am having is a general midi problem. I have a file with a track called guitar part, the hex, as viewed in a hex editor is as follows:
4D 54 72 6B 00 00 1E 74 00 FF 03 0B 50 41 52 54 20 47 55 49 54 41 52 A9 20 90 61 40 9A 20 61 00 83 60 63 40 BC
My program parses this fine as follows:
4D M
54 T
72 R
6B K
00 < --
00 size of
1E track part
74 -- >
00 time of this event
FF event type (this is meta)
03 meta event type
0B length of data
50 "P"
41 "A"
52 "R"
54 "T"
20 " "
47 "G"
55 "U"
49 "I"
54 "T"
41 "A"
52 "R"
A9 time of event (variable length) 10101001
20 time of event (variable length) 00100000
90 event,channel (non-meta) 1001=note on,channel=0000
61 note on has 2 params this is the first
40 this is the second
9A variable time 10011010
20 variable time 00100000
This is where my problem lies, there is no event that has event type 0x6, since 0x61 is 01100001 we have to assume it's non meta, therefore the event type should be 6 (0110) and the channel is (0001) but the midi specification contains no identification for this event.. I've added a few of the bytes after this incase they are somehow relevent but obviously at the moment my program hits the next byte, doesn't recognise the event and bombs out.
61
00
83
60
63
40
BC
If anyone thinks they could shed any light on where my parsing logic has gone wrong i'd be most appreciative, sorry for the formatting, i couldn't think of a better way to illustrate my problem.
I have been using this site: http://www.sonicspot.com/guide/midifiles.html as a reference and it hasn't led me wrong so far. I figured this might be something directly relating to frets on fire but it doesn't seem to be as i downloaded another notes file for the game and that file did not contain this event.
Thanks in advance.
It's called running status. If an event is of the same type as the previous event, the MIDI status byte can be eliminated. So if the first byte after the timing info is < $80, use the previous status. In the case of your $61 byte, the previous status was $90, so it's Note On, channel 0. Which makes sense since the previous event was note number $61 velocity $40. This event is note number $61 velocity 0 (releasing the previously played note). The next event is note number $63 velocity $40.

Addressing memory data in 32 bit protected mode with nasm

So my book says i can define a table of words like so:
table: dw "13,37,99,99"
and that i can snatch values from the table by incrementing the index into the address of the table like so:
mov ax, [table+2] ; should give me 37
but instead it places 0x2c33 in ax rather than 0x3337
is this because of a difference in system architecture? maybe because the book is for 386 and i'm running 686?
0x2C is a comma , and 0x33 is the character 3, and they appear at positions 2 and 3 in your string, as expected. (I'm a little confused as to what you were expecting, since you first say "should give me 37" and later say "rather than 0x3337".)
You have defined a string constant when I suspect that you didn't mean to. The following:
dw "13,37,99,99"
Will produce the following output:
Offset 00 01 02 03 04 05 06 07 08 09 0A 0B
31 33 2C 33 37 2C 39 39 2C 39 39 00
Why? Because:
31 is the ASCII code for '1'
33 is the ASCII code for '3'
2C is the ASCII code for ','
...
39 is the ASCII code for '9'
NASM also null-terminates your string by putting 0 byte at the end (If you don't want your strings to be null-terminated use single quotes instead, '13,37,99,99')
Take into account that ax holds two bytes and it should be fairly clear why ax contains 0x2C33.
I suspect what you wanted was more along the lines of this (no quotes and we use db to indicate we are declaring byte-sized data instead of dw that declares word-sized data):
db 13,37,99,99
This would still give you 0x6363 (ax holds two bytes / conversion of 99, 99 to hex). Not sure where you got 0x3337 from.
I recommend that you install yourself a hex editor and have an experiment inspecting the output from NASM.

Resources