<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: 宛涵</title>
    <description>The latest articles on DEV Community by 宛涵 (@hannes_wan).</description>
    <link>https://dev.to/hannes_wan</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F3998153%2Feefb549f-721a-4bb3-b28c-cbaa28b5b11d.jpg</url>
      <title>DEV Community: 宛涵</title>
      <link>https://dev.to/hannes_wan</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/hannes_wan"/>
    <language>en</language>
    <item>
      <title>USBPcap and usbmon debugging: what to collect before blaming firmware</title>
      <dc:creator>宛涵</dc:creator>
      <pubDate>Tue, 23 Jun 2026 07:16:50 +0000</pubDate>
      <link>https://dev.to/hannes_wan/usbpcap-and-usbmon-debugging-what-to-collect-before-blaming-firmware-3kci</link>
      <guid>https://dev.to/hannes_wan/usbpcap-and-usbmon-debugging-what-to-collect-before-blaming-firmware-3kci</guid>
      <description>&lt;p&gt;USB bugs are easy to describe badly.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;The device is not detected.
The HID report is wrong.
The endpoint stalls.
It works on one machine but not another.
The firmware team says the host is wrong.
The host team says the firmware is wrong.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The fastest way out is to collect evidence at the USB transfer level.&lt;/p&gt;

&lt;p&gt;On Windows, that often means USBPcap. On Linux, that often means usbmon. The capture alone is only the beginning; the useful work is turning that capture into a readable explanation.&lt;/p&gt;

&lt;h2&gt;
  
  
  Start with the failure mode
&lt;/h2&gt;

&lt;p&gt;Before capturing, write down the exact failure.&lt;/p&gt;

&lt;p&gt;Examples:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Device never enumerates
Configuration is selected but interface does not start
HID input report length is unexpected
Bulk IN endpoint stops responding
CDC device opens but no data arrives
Mass Storage command times out
UVC camera exposes descriptors but preview fails
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Different failures require different evidence.&lt;/p&gt;

&lt;h2&gt;
  
  
  Capture enumeration first
&lt;/h2&gt;

&lt;p&gt;If the device is not recognized correctly, capture from plug-in through configuration.&lt;/p&gt;

&lt;p&gt;Look for:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;reset&lt;/li&gt;
&lt;li&gt;device descriptor request&lt;/li&gt;
&lt;li&gt;configuration descriptor request&lt;/li&gt;
&lt;li&gt;string descriptor requests&lt;/li&gt;
&lt;li&gt;set address&lt;/li&gt;
&lt;li&gt;set configuration&lt;/li&gt;
&lt;li&gt;interface and endpoint descriptors&lt;/li&gt;
&lt;li&gt;class-specific descriptors&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Enumeration bugs often hide in descriptors, not payload data.&lt;/p&gt;

&lt;h2&gt;
  
  
  Read descriptors like a contract
&lt;/h2&gt;

&lt;p&gt;Descriptors tell the host what the device claims to be.&lt;/p&gt;

&lt;p&gt;Check:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;bDeviceClass / bInterfaceClass
idVendor / idProduct
bcdUSB
configuration count
interface count
endpoint address and direction
endpoint transfer type
wMaxPacketSize
polling interval
HID report descriptor
CDC class descriptors
UVC class descriptors
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If the descriptor contract is wrong, the host may behave correctly while the product still fails.&lt;/p&gt;

&lt;h2&gt;
  
  
  Separate control, interrupt, bulk, and isochronous traffic
&lt;/h2&gt;

&lt;p&gt;Not every transfer means the same thing.&lt;/p&gt;

&lt;p&gt;Control transfers often explain setup and class requests.&lt;/p&gt;

&lt;p&gt;Interrupt transfers often matter for HID devices.&lt;/p&gt;

&lt;p&gt;Bulk transfers often matter for CDC, storage, vendor protocols, and firmware update flows.&lt;/p&gt;

&lt;p&gt;Isochronous transfers often matter for cameras, audio, and real-time media.&lt;/p&gt;

&lt;p&gt;A readable timeline should keep these categories visible.&lt;/p&gt;

&lt;h2&gt;
  
  
  Check setup packets before payloads
&lt;/h2&gt;

&lt;p&gt;For control transfers, inspect the setup packet:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;bmRequestType
bRequest
wValue
wIndex
wLength
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;A single wrong &lt;code&gt;wIndex&lt;/code&gt; or request direction can explain a failure that looks like a payload problem.&lt;/p&gt;

&lt;h2&gt;
  
  
  Compare good vs bad hosts
&lt;/h2&gt;

&lt;p&gt;If the device works on one machine and fails on another, capture both.&lt;/p&gt;

&lt;p&gt;Compare:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;descriptor requests&lt;/li&gt;
&lt;li&gt;selected configuration&lt;/li&gt;
&lt;li&gt;class driver behavior&lt;/li&gt;
&lt;li&gt;endpoint polling interval&lt;/li&gt;
&lt;li&gt;transfer sizes&lt;/li&gt;
&lt;li&gt;timeout patterns&lt;/li&gt;
&lt;li&gt;stall/clear-feature sequences&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Do not assume the host with the failure is the only interesting one. The working host is your baseline.&lt;/p&gt;

&lt;h2&gt;
  
  
  Avoid overclaiming from software captures
&lt;/h2&gt;

&lt;p&gt;USBPcap and usbmon are software-side evidence. They are very useful, but they are not a replacement for a hardware analyzer when the question is electrical timing, signal integrity, low-level bus errors, or power behavior.&lt;/p&gt;

&lt;p&gt;Use software captures for:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;enumeration logic&lt;/li&gt;
&lt;li&gt;descriptors&lt;/li&gt;
&lt;li&gt;class requests&lt;/li&gt;
&lt;li&gt;transfer sequence&lt;/li&gt;
&lt;li&gt;payload inspection&lt;/li&gt;
&lt;li&gt;host/device protocol behavior&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Use hardware tools when you need electrical truth.&lt;/p&gt;

&lt;h2&gt;
  
  
  What to send to firmware or support
&lt;/h2&gt;

&lt;p&gt;A useful USB debugging handoff should include:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;OS and kernel/build version
Device VID/PID
Firmware version
Capture source: USBPcap or usbmon
Failure mode
Enumeration summary
Descriptor notes
Endpoint involved
Transfer timeline
Relevant setup packets
Payload examples if safe
What changed between good and bad runs
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;That is much better than “USB does not work”.&lt;/p&gt;

&lt;h2&gt;
  
  
  Where Bus Scope fits
&lt;/h2&gt;

&lt;p&gt;You can capture USB evidence with USBPcap, usbmon, Wireshark, and scripts. The hard part is making the session readable enough for firmware, hardware, and support teams to discuss the same evidence.&lt;/p&gt;

&lt;p&gt;I build &lt;a href="https://hannes-software.com/bus-scope/" rel="noopener noreferrer"&gt;Bus Scope&lt;/a&gt; for that workflow. It is a local desktop USB diagnostics workbench for inspecting USBPcap or usbmon evidence, descriptors, endpoints, HID reports, payloads, sessions, filters, and exportable support notes.&lt;/p&gt;

&lt;p&gt;It is not a professional hardware analyzer replacement for electrical timing or signal integrity. It is for daily software-side USB debugging and handoff.&lt;/p&gt;

&lt;p&gt;Disclosure: I build Bus Scope.&lt;/p&gt;

&lt;h2&gt;
  
  
  Quick checklist
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;[ ] Define the exact failure mode
[ ] Capture from plug-in if enumeration matters
[ ] Save descriptors
[ ] Inspect setup packets
[ ] Separate transfer types
[ ] Compare good and bad hosts
[ ] Document OS, firmware, VID/PID
[ ] Export a readable handoff
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



</description>
      <category>tutorial</category>
    </item>
    <item>
      <title>How to prepare a PCAP for vendor support without leaking the whole capture</title>
      <dc:creator>宛涵</dc:creator>
      <pubDate>Tue, 23 Jun 2026 07:02:13 +0000</pubDate>
      <link>https://dev.to/hannes_wan/how-to-prepare-a-pcap-for-vendor-support-without-leaking-the-whole-capture-c70</link>
      <guid>https://dev.to/hannes_wan/how-to-prepare-a-pcap-for-vendor-support-without-leaking-the-whole-capture-c70</guid>
      <description>&lt;p&gt;Packet captures are useful because they are specific. They are risky for the same reason.&lt;/p&gt;

&lt;p&gt;A raw PCAP can contain:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;internal IP addresses&lt;/li&gt;
&lt;li&gt;hostnames&lt;/li&gt;
&lt;li&gt;credentials or tokens in cleartext protocols&lt;/li&gt;
&lt;li&gt;cookies&lt;/li&gt;
&lt;li&gt;DNS queries&lt;/li&gt;
&lt;li&gt;customer traffic unrelated to the bug&lt;/li&gt;
&lt;li&gt;proprietary endpoints&lt;/li&gt;
&lt;li&gt;timing information&lt;/li&gt;
&lt;li&gt;enough context to reveal network architecture&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Before sending a capture to a vendor, support team, customer, or public issue, treat it like evidence that needs minimization.&lt;/p&gt;

&lt;p&gt;The goal is not to make the file pretty. The goal is to preserve the packets needed to reproduce or explain the issue while removing everything that does not belong in the handoff.&lt;/p&gt;

&lt;h2&gt;
  
  
  Start with the question
&lt;/h2&gt;

&lt;p&gt;Do not edit a PCAP until you know what the receiver needs to answer.&lt;/p&gt;

&lt;p&gt;Examples:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Why does TLS negotiation fail after ServerHello?
Why does this device retransmit every request?
Why does the API return 400 only for this payload?
Why does the camera stream freeze after PLAY?
Why does DNS resolve differently on this subnet?
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;That question tells you which packets matter.&lt;/p&gt;

&lt;h2&gt;
  
  
  Keep a read-only original
&lt;/h2&gt;

&lt;p&gt;Always preserve the original capture.&lt;/p&gt;

&lt;p&gt;Recommended structure:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;case-1234/
  original/
    customer-capture-raw.pcapng
  working/
    filtered-draft.pcapng
  handoff/
    vendor-handoff-v1.pcapng
    notes.md
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Never overwrite the original file. If a later question appears, you may need to rebuild the handoff from the untouched source.&lt;/p&gt;

&lt;h2&gt;
  
  
  Reduce the time window
&lt;/h2&gt;

&lt;p&gt;The easiest safe reduction is time.&lt;/p&gt;

&lt;p&gt;If the failure happens between &lt;code&gt;10:42:13&lt;/code&gt; and &lt;code&gt;10:42:18&lt;/code&gt;, the vendor probably does not need a 45-minute capture.&lt;/p&gt;

&lt;p&gt;Keep:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;a small lead-in before the failure&lt;/li&gt;
&lt;li&gt;the failure itself&lt;/li&gt;
&lt;li&gt;enough aftermath to show retries, resets, or recovery&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Remove unrelated browsing, background sync, update checks, and other noise.&lt;/p&gt;

&lt;h2&gt;
  
  
  Filter by conversation, not just protocol
&lt;/h2&gt;

&lt;p&gt;Protocol filters are often too broad.&lt;/p&gt;

&lt;p&gt;Instead of “all HTTP” or “all DNS”, narrow to:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;client IP&lt;/li&gt;
&lt;li&gt;server IP&lt;/li&gt;
&lt;li&gt;port&lt;/li&gt;
&lt;li&gt;stream/conversation&lt;/li&gt;
&lt;li&gt;device MAC&lt;/li&gt;
&lt;li&gt;transaction ID&lt;/li&gt;
&lt;li&gt;request path if visible&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;A narrow conversation makes review faster and reduces accidental disclosure.&lt;/p&gt;

&lt;h2&gt;
  
  
  Redact identifiers deliberately
&lt;/h2&gt;

&lt;p&gt;Common fields to inspect before sharing:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;IP addresses
MAC addresses
Hostnames
DNS queries
HTTP headers
URLs and query strings
Cookies
Authorization headers
Email addresses
Usernames
Device serial numbers
Payload strings
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Redaction should be intentional. Replacing every IP with nonsense can destroy routing evidence. Leaving every internal hostname can leak environment details.&lt;/p&gt;

&lt;p&gt;A good rule:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;preserve structure needed for diagnosis&lt;/li&gt;
&lt;li&gt;remove identities not needed for diagnosis&lt;/li&gt;
&lt;li&gt;document what changed&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Repair checksums when rewriting
&lt;/h2&gt;

&lt;p&gt;If you modify packet bytes, addresses, or headers, checksums may no longer match.&lt;/p&gt;

&lt;p&gt;Some tools ignore bad checksums. Some analysis tools and test harnesses do not.&lt;/p&gt;

&lt;p&gt;After editing, check:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;IP header checksum&lt;/li&gt;
&lt;li&gt;TCP checksum&lt;/li&gt;
&lt;li&gt;UDP checksum&lt;/li&gt;
&lt;li&gt;transport length fields&lt;/li&gt;
&lt;li&gt;capture file format validity&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;If the file is meant for replay, testing, or regression fixtures, checksum correctness matters more.&lt;/p&gt;

&lt;h2&gt;
  
  
  Add a short handoff note
&lt;/h2&gt;

&lt;p&gt;Do not send a PCAP alone.&lt;/p&gt;

&lt;p&gt;Include a note like:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Case: login request fails after TLS renegotiation
Original capture retained internally: yes
Shared file time window: 10:42:10-10:42:22 UTC
Included hosts: client 10.0.0.15, api.example.internal
Redactions: client IP anonymized, hostname shortened, cookies removed
Checksums repaired: yes
Expected symptom: server closes connection after packet 184
Question for vendor: is this close_notify behavior expected?
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;That note prevents the receiver from reverse-engineering your intent.&lt;/p&gt;

&lt;h2&gt;
  
  
  Validate the final file
&lt;/h2&gt;

&lt;p&gt;Before sending:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;[ ] Opens in Wireshark/tshark
[ ] Contains the failure
[ ] Does not contain unrelated traffic
[ ] Redactions are documented
[ ] Checksums are valid if needed
[ ] File size is reasonable
[ ] Receiver knows what question to answer
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Where PCAP Surgery fits
&lt;/h2&gt;

&lt;p&gt;You can do parts of this with Wireshark, editcap, text notes, and scripts. The problem is that safe support handoff is a workflow, not one command.&lt;/p&gt;

&lt;p&gt;I build &lt;a href="https://hannes-software.com/pcap-surgery/" rel="noopener noreferrer"&gt;PCAP Surgery&lt;/a&gt; for that workflow: review, trim, redact, repair checksums, and export focused PCAP/PCAPNG files from a local desktop workbench.&lt;/p&gt;

&lt;p&gt;It is not a live packet sniffer, IDS, VPN, or traffic generator. It is for preparing packet evidence that can be safely handed to another person.&lt;/p&gt;

&lt;p&gt;Disclosure: I build PCAP Surgery.&lt;/p&gt;

&lt;h2&gt;
  
  
  Minimal handoff checklist
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;[ ] Define the support question
[ ] Preserve the original capture
[ ] Trim the time window
[ ] Keep only relevant conversations
[ ] Redact sensitive identifiers
[ ] Repair checksums if rewriting
[ ] Export a focused PCAP/PCAPNG
[ ] Send a short note with the file
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



</description>
      <category>tutorial</category>
    </item>
    <item>
      <title>RTSP black screen troubleshooting: what to check when VLC works but your VMS does not</title>
      <dc:creator>宛涵</dc:creator>
      <pubDate>Tue, 23 Jun 2026 07:01:48 +0000</pubDate>
      <link>https://dev.to/hannes_wan/rtsp-black-screen-troubleshooting-what-to-check-when-vlc-works-but-your-vms-does-not-1pb9</link>
      <guid>https://dev.to/hannes_wan/rtsp-black-screen-troubleshooting-what-to-check-when-vlc-works-but-your-vms-does-not-1pb9</guid>
      <description>&lt;p&gt;An IP camera stream failure is rarely just “RTSP does not work”. The useful question is more specific:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Did RTSP authentication succeed?&lt;/li&gt;
&lt;li&gt;Did DESCRIBE return the SDP you expected?&lt;/li&gt;
&lt;li&gt;Did SETUP choose TCP interleaved or UDP RTP?&lt;/li&gt;
&lt;li&gt;Is media arriving after PLAY?&lt;/li&gt;
&lt;li&gt;Are RTP sequence numbers continuous?&lt;/li&gt;
&lt;li&gt;Does the codec profile match what the client can decode?&lt;/li&gt;
&lt;li&gt;Is ONVIF handing the VMS a different URI than the one you tested in VLC?&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;When a camera plays in VLC but not in an NVR/VMS, the failure is usually in the gap between “the stream exists” and “this client can negotiate, receive, and decode it reliably”.&lt;/p&gt;

&lt;h2&gt;
  
  
  Start with the exact URI
&lt;/h2&gt;

&lt;p&gt;Do not compare two different tests.&lt;/p&gt;

&lt;p&gt;Write down the full RTSP URL used by each client:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;rtsp://user:pass@camera.local:554/path
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Check for differences in:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;profile path&lt;/li&gt;
&lt;li&gt;channel number&lt;/li&gt;
&lt;li&gt;stream subtype&lt;/li&gt;
&lt;li&gt;query parameters&lt;/li&gt;
&lt;li&gt;username/password encoding&lt;/li&gt;
&lt;li&gt;transport settings&lt;/li&gt;
&lt;li&gt;ONVIF-generated URI vs manually copied URI&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Many cameras expose multiple profiles. VLC may be opening the main stream while the VMS is using a substream, or vice versa.&lt;/p&gt;

&lt;h2&gt;
  
  
  Check the RTSP control flow
&lt;/h2&gt;

&lt;p&gt;A normal session usually looks like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;OPTIONS
DESCRIBE
SETUP video
SETUP audio (optional)
PLAY
TEARDOWN
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Useful failure patterns:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;401 loop
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Authentication is not being accepted. Check digest/basic auth, clock drift on some devices, special characters in passwords, and whether the VMS encodes credentials differently.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;DESCRIBE succeeds, SETUP fails
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The client can read metadata but cannot negotiate media transport. Check UDP/TCP mode, client ports, firewall/NAT, and multicast settings.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;PLAY succeeds, black screen
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The control session succeeded, but media or decoding failed. Now inspect RTP and codec details.&lt;/p&gt;

&lt;h2&gt;
  
  
  Read the SDP instead of guessing
&lt;/h2&gt;

&lt;p&gt;The DESCRIBE response should return SDP similar to:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;m=video 0 RTP/AVP 96
a=rtpmap:96 H264/90000
a=control:trackID=1
a=fmtp:96 packetization-mode=1; profile-level-id=...
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Check:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;codec: H.264, H.265, MJPEG&lt;/li&gt;
&lt;li&gt;payload type&lt;/li&gt;
&lt;li&gt;control attribute&lt;/li&gt;
&lt;li&gt;SPS/PPS availability for H.264&lt;/li&gt;
&lt;li&gt;profile-level-id compatibility&lt;/li&gt;
&lt;li&gt;audio track that may confuse weaker clients&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;A stream can be valid but still use a profile or packetization mode the receiving system handles poorly.&lt;/p&gt;

&lt;h2&gt;
  
  
  Verify RTP actually arrives
&lt;/h2&gt;

&lt;p&gt;If RTSP SETUP selected UDP, confirm that RTP packets arrive on the negotiated ports.&lt;/p&gt;

&lt;p&gt;Symptoms of blocked media:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;RTSP commands return 200 OK&lt;/li&gt;
&lt;li&gt;PLAY succeeds&lt;/li&gt;
&lt;li&gt;no RTP packets arrive&lt;/li&gt;
&lt;li&gt;no RTCP receiver reports&lt;/li&gt;
&lt;li&gt;client shows black screen or timeout&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This often means firewall, NAT, VLAN, routing, or client port negotiation is the real issue.&lt;/p&gt;

&lt;p&gt;If TCP interleaved works but UDP does not, you have a transport path problem, not necessarily a camera problem.&lt;/p&gt;

&lt;h2&gt;
  
  
  Inspect RTP continuity
&lt;/h2&gt;

&lt;p&gt;When packets arrive but playback freezes or breaks, look for:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;sequence gaps&lt;/li&gt;
&lt;li&gt;timestamp jumps&lt;/li&gt;
&lt;li&gt;marker bit behavior&lt;/li&gt;
&lt;li&gt;payload type changes&lt;/li&gt;
&lt;li&gt;RTCP sender reports&lt;/li&gt;
&lt;li&gt;jitter patterns&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;A few packet losses may be tolerable. Repeated gaps around keyframes can make a stream look like a decode failure.&lt;/p&gt;

&lt;h2&gt;
  
  
  ONVIF handoff can hide the real URI
&lt;/h2&gt;

&lt;p&gt;Many VMS products discover cameras through ONVIF, then request stream URIs from the device.&lt;/p&gt;

&lt;p&gt;That URI may not match the one you tested manually.&lt;/p&gt;

&lt;p&gt;Compare:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;ONVIF profile token&lt;/li&gt;
&lt;li&gt;returned media URI&lt;/li&gt;
&lt;li&gt;transport protocol requested by ONVIF client&lt;/li&gt;
&lt;li&gt;main/sub stream selection&lt;/li&gt;
&lt;li&gt;authentication behavior after handoff&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;If VLC uses a hand-written URI and the VMS uses an ONVIF URI, you have not tested the same thing yet.&lt;/p&gt;

&lt;h2&gt;
  
  
  What to hand to support
&lt;/h2&gt;

&lt;p&gt;A useful report should include:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Camera model / firmware
Client name and version
RTSP URL path (without password)
Transport mode: TCP or UDP
RTSP request/response summary
SDP video/audio details
RTP arrival status
Packet loss or sequence gap notes
Codec profile notes
Exact failure symptom
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;That is much more actionable than “camera does not play”.&lt;/p&gt;

&lt;h2&gt;
  
  
  Where RTSP Inspector fits
&lt;/h2&gt;

&lt;p&gt;You can do parts of this manually with VLC logs, Wireshark, ONVIF tools, and packet captures. The hard part is turning those pieces into a compact handoff that a camera vendor, installer, or VMS support team can understand.&lt;/p&gt;

&lt;p&gt;I build &lt;a href="https://hannes-software.com/rtsp-inspector/" rel="noopener noreferrer"&gt;RTSP Inspector&lt;/a&gt; for that workflow. It is a local desktop tool for RTSP, RTP, RTCP, SDP, ONVIF handoff, packet loss, and codec-readiness diagnostics. It is not a VMS, NVR, surveillance recorder, or media player; it is meant to explain why a stream does or does not work.&lt;/p&gt;

&lt;p&gt;A practical workflow is:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Reproduce the failure with the same URI the client uses.&lt;/li&gt;
&lt;li&gt;Capture RTSP control messages and SDP.&lt;/li&gt;
&lt;li&gt;Confirm transport mode and media arrival.&lt;/li&gt;
&lt;li&gt;Inspect RTP/RTCP evidence.&lt;/li&gt;
&lt;li&gt;Export a report for support handoff.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Disclosure: I build RTSP Inspector.&lt;/p&gt;

&lt;h2&gt;
  
  
  Quick checklist
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;[ ] Same RTSP URI in both clients
[ ] Authentication result known
[ ] DESCRIBE response saved
[ ] SDP codec/profile inspected
[ ] SETUP transport mode known
[ ] RTP arrival confirmed
[ ] RTP sequence gaps checked
[ ] ONVIF media URI compared
[ ] Report prepared for support
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



</description>
      <category>debugging</category>
      <category>tutorial</category>
    </item>
  </channel>
</rss>
