Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

mp4 files cannot be played directly, need to be copied first. #108

Closed
marcone opened this issue Sep 12, 2024 · 18 comments
Closed

mp4 files cannot be played directly, need to be copied first. #108

marcone opened this issue Sep 12, 2024 · 18 comments

Comments

@marcone
Copy link
Contributor

marcone commented Sep 12, 2024

I set this up on a Raspberry Pi Zero W and pointed it at a folder full of mp4 files. The files show up on the attached Windows 10 PC, and Windows by default opens them with Media Player, however they won't play (Media Player just shows the progress spinner animation forever).
If I copy (using drag&drop) them to the Windows hard drive first, the files can be played from there.

@jfdelnero
Copy link
Member

Can you make a wireshark usb dump ?
Have you another device/smartphone to compare ?

@marcone
Copy link
Contributor Author

marcone commented Nov 3, 2024

I'll look into wireshark. For now, I've attached umtprd debug logs showing the process of navigating to the folder where the file is located, then double clicking on the file to open it with Windows Media Player.
After this, Media Player hangs indefinitely, and after closing Media Player, I can no longer access the MTP device at all (any operation just makes Windows block), and have to restart umtprd.

umtprdlog.txt

(note that this logging is with #112 applied, so it'll look slightly different than what you're used to)

I also tried without debug logs, in case the problem is related to logging, or because enabling debug logs also disables compiler optimizations, but it behaves the same with and without logs/debug mode.

These logs are from a Raspberry Pi Zero 2 W, not the Raspberry Pi Zero W that I originally tried.

@marcone
Copy link
Contributor Author

marcone commented Nov 3, 2024

Here's a Wireshark capture. Not sure I did it right, since it seems a bit short.
What I did was uncheck the "Capture from all devices connected" checkbox in the USBPcap1 settings (since I also have a mouse, keyboard, drives, etc. and I didn't want it to capture those), then start the capture, then start umtprd so Wireshark saw it as a new device and would start capturing it. I then opened the MTP device, navigated to a short (763KB) test video, and double clicked it to open Media Player. I let that spin for a while, then closed Media Player, stopped the capture, and saved the attached capture file.

mtpcapture.pcapng.gz

@marcone
Copy link
Contributor Author

marcone commented Nov 3, 2024

For what's worth, I also tried using gadgetfs instead of functionfs, which behaved the same when trying to play a file, but caused the Pi to go into an infinite loop and become unresponsive when stopping umtrpd.

@marcone
Copy link
Contributor Author

marcone commented Nov 4, 2024

Also, to make sure the problem isn't with Windows or Media Player I copied the same test video to my Pixel 5, and verified that Windows/Media Player could play the file just fine when accessing the file using MTP from the Pixel 5.

@jfdelnero
Copy link
Member

Also, to make sure the problem isn't with Windows or Media Player I copied the same test video to my Pixel 5, and verified that Windows/Media Player could play the file just fine when accessing the file using MTP from the Pixel 5.

I am interested by a wireshark dump with the Pixel 5 too.

Anyway this is for sure related to the Setup Request 0x64 MTP_REQ_CANCEL operation sent by the PC (probably the URB_FUNCTION_ABORT_PIPE in the wireshark capture). This seems to kill the whole stack and i am really not sure how to handle this properly ...

@marcone
Copy link
Contributor Author

marcone commented Nov 4, 2024

Here's a capture of the Pixel 5. Started Wireshark, then enabled the "File transfer / Android Auto" USB mode, then opened the "Pixel 5" device in Windows and played the test file.

mtpcapturepixel.pcapng.gz

@marcone
Copy link
Contributor Author

marcone commented Nov 4, 2024

Anyway this is for sure related to the Setup Request 0x64 MTP_REQ_CANCEL operation sent by the PC

That request doesn't happen until Media Player has already been spinning for 30 seconds or so though, so that can't be the reason why it doesn't start playback.

@marcone
Copy link
Contributor Author

marcone commented Nov 6, 2024

Anyway this is for sure related to the Setup Request 0x64 MTP_REQ_CANCEL operation sent by the PC

That request doesn't happen until Media Player has already been spinning for 30 seconds or so though, so that can't be the reason why it doesn't start playback.

Correction: it might be the MTP_CANCEL_REQ that is the problem, however it doesn't seem like it is caused by the URB_FUNCTION_ABORT_PIPE from the host, since I don't see that ...ABORT_PIPE until it already hangs.

I looked in to this some more, and it appears the problem is that this call to write_usb blocks forever. I tried enabling CONFIG_USB_NON_BLOCKING_WRITE but that didn't help (it still blocks on the call to write() inside of write_usb(), even though both the fnctl() to make it nonblocking as well as the poll() to check whether it can receive data succeed).

Edit: I also tried rewriting the do/while inside of write_usb to poll and then write one byte at a time, but that doesn't work at all, it writes one byte, then blocks on the second byte despite poll() reporting the fd is ready to receive data.

@marcone
Copy link
Contributor Author

marcone commented Nov 7, 2024

Found a fix: 1e6936a

Not sure if this is the right solution, and note that there are several other places that do status = read (ctx->usb_device, &status, 0);.

@jfdelnero
Copy link
Member

Same issue :
#92

@jfdelnero
Copy link
Member

Another one :
#30

@jfdelnero
Copy link
Member

This one is interesting :
#96

@marcone
Copy link
Contributor Author

marcone commented Nov 7, 2024

Those other issues all seem to talk about kernel crashes/segfaults, which I'm not seeing. I'm just seeing that write() in write_usb() hang forever, unless I remove the read() in the MTP_REQ_CANCEL case.

(this is using kernel 6.6.51 in case that matters)

@jfdelnero
Copy link
Member

can you try to cancel a big file transfer (from and to the device) ?

@marcone
Copy link
Contributor Author

marcone commented Nov 7, 2024

Copying a large file from Windows to the device I noticed the following:

  • the Windows progress indicator is all wrong. It slowly goes to about 20% or so, and then the transfer is complete.
  • canceling the copy works fine, with no crashes in either umtprd or the kernel

Copying a large file from the device to Windows:

  • the Windows progress indicator appears correct
  • letting the file copy without interruption works fine
  • canceling the transfer hangs, and required restarting umtprd afterwards
  • no crashes observed in either umtprd or the kernel

If I remove the read() call like I did in 1e6936a then canceling the file transfer to the device works OK.

@jfdelnero
Copy link
Member

ok !
I hope that this is not device / soc dependent..

@marcone
Copy link
Contributor Author

marcone commented Nov 8, 2024

ok ! I hope that this is not device / soc dependent..

It looks like it is device dependent. I just tried this on a Rock Pi 4C+ running Armbian with kernel 6.1.63, and removing the read() doesn't appear to be necessary there (but removing it doesn't seem to cause any problems either)

However, also on the Rock Pi 4C+, I could only get it to work if I connect the device to the PC as a USB2 device. When using it as a USB3 device, mtprd starts up seemingly fine and there are no errors in umtprd's debug log or dmesg, but the PC complains about "USB device not recognized", while USB Device Tree Viewer says there's a port malfunction.

Unrelated to this, but I also found that Windows apparently caches the product name of the device based on the serial number. Once it has seen device with a serial number 'S' and name 'N', any subsequent device that uses serial number 'S' will be shown with name 'N' in Explorer, even if a different name is used in strings/0x409/product. Right-clicking on the device and selecting 'properties' shows both the cached name 'N' and the actual name from the product string.

marcone added a commit to marcone/uMTP-Responder that referenced this issue Nov 14, 2024
Doing a blocking read (even with count=0) when handling a cancel request
from the host ends up blocking both the read in the request handler as
well as a write in the thread that's being cancelled, blocking both threads
indefinitely.
Removing the read appears to fix the problem.
Fixes viveris#108
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants