[Interest] Playing RTSP video on android

Israel Brewster ijbrewster at alaska.edu
Tue Jul 16 21:43:29 CEST 2024


On Jul 12, 2024, at 9:18 AM, ekke <ekke at ekkes-corner.org> wrote:
> 
> have you tried Qt Example Declarative Camera ?
> you should be able to record or view videos.
> sometimes there are problems running on emulator, so it's a good idea to verify
> 
> Am 10.07.24 um 19:32 schrieb Israel Brewster via Interest:
>> Environment:
>> 
>> Qt version: 6.6.3
>> Android version: 14, running via emulator
>> Android build-tools version: 34.0.0 (also tried 31.0.0)
>> Android build platform SDK: android-33 (also tried android-34)
>> JDK version 17 (tried 21 early on, but that one wouldn’t even build/deploy)
>> NDK version 25.1.8937393 (26.1.10909125 and 27.0.11902837 don’t create any kits, so not using them)
>> Building using Qt Creator version 12.0.2 on MacOS

So after playing around with this some more, I find the following:
- Behavior on a physical device is the same as on the emulator (so it doesn’t appear to be an emulator issue)
- Of the half dozen rtsp streams I have access to, *one* works. It’s a newer camera, streaming in h.265, while the one I really want streams in h.264 (so it doesn’t appear to be a fundamental code issue)
- A couple of other cameras work for audio, but not video. Even other cameras with h.265 streams.
- No difference in functionality between using the ffmpeg backend, and the “android” backend.
- Things work fine when compiled/running on my Mac instead of android.
- I CAN view the stream using ffmpeg installed in termux, as long as I give it the "rtsp_transport tcp" option.



Here is the full code I am using for testing:

#include <QApplication>
#include <QMainWindow>
#include <QMediaPlayer>
#include <QVideoWidget>
#include <QHBoxLayout>
#include <QAudioOutput>

int main(int argc, char *argv[])
{
    qputenv("QT_MEDIA_BACKEND","ffmpeg");
    QApplication a(argc, argv);
    QMainWindow w;

    QWidget *centralWidget=w.centralWidget();
    if(!centralWidget){
        centralWidget=new QWidget(&w);
        w.setCentralWidget(centralWidget);
    }

    QHBoxLayout layout;
    centralWidget->setLayout(&layout);

    QMediaPlayer player;
    QObject::connect(&player, &QMediaPlayer::errorOccurred, [](QMediaPlayer::Error error, const QString &errorString) {
        qWarning() << "MediaPlayer error:" << error << errorString;
    });

    QVideoWidget videoWidget;

    layout.addWidget(&videoWidget);
    player.setVideoOutput(&videoWidget);

    QAudioOutput audioOutput;
    player.setAudioOutput(&audioOutput);

    videoWidget.show();
    w.show();

    player.setSource(QUrl("rtsp://10.27.81.62:554/11"));
    player.play();

    return a.exec();
}

And the output I get when running that code, after I specify the source:

W qt.multimedia.ffmpeg.libsymbolsresolver: : Couldn't load OpenSsl library
I ImeTracker: org.qtproject.example.TestAndroidVideo:f900fc2d: onRequestHide at ORIGIN_CLIENT_HIDE_SOFT_INPUT reason HIDE_SOFT_INPUT
I ImeTracker: org.qtproject.example.TestAndroidVideo:f900fc2d: onFailed at PHASE_CLIENT_VIEW_SERVED
W qt.multimedia.ffmpeg.mediadataholder: : AVStream duration -9223372036854775808 is invalid. Taking it from the metadata
W qt.multimedia.ffmpeg.mediadataholder: : AVStream duration -9223372036854775808 is invalid. Taking it from the metadata
E EGL_emulation: eglQueryContext 32c0  EGL_BAD_ATTRIBUTE
E EGL_emulation: tid 16364: eglQueryContext(2146): error 0x3004 (EGL_BAD_ATTRIBUTE)
D CCodec  : allocate(c2.goldfish.h264.decoder)
I Codec2Client: Available Codec2 services: "default" "software"
I CCodec  : setting up 'default' as default (vendor) store
I CCodec  : Created component [c2.goldfish.h264.decoder]
D CCodecConfig: read media type: video/avc
D ReflectedParamUpdater: extent() != 1 for single value type: algo.buffers.max-count.values
D ReflectedParamUpdater: extent() != 1 for single value type: output.subscribed-indices.values
D ReflectedParamUpdater: extent() != 1 for single value type: input.buffers.allocator-ids.values
D ReflectedParamUpdater: extent() != 1 for single value type: output.buffers.allocator-ids.values
D ReflectedParamUpdater: extent() != 1 for single value type: algo.buffers.allocator-ids.values
D ReflectedParamUpdater: extent() != 1 for single value type: output.buffers.pool-ids.values
D ReflectedParamUpdater: extent() != 1 for single value type: algo.buffers.pool-ids.values
D ReflectedParamUpdater: ignored struct field coded.color-format.locations
D CCodecConfig: ignoring local param raw.size (0xd2001800) as it is already supported
D CCodecConfig: ignoring local param default.color (0x5200180b) as it is already supported
D ReflectedParamUpdater: ignored struct field raw.hdr-static-info.mastering
I CCodecConfig: query failed after returning 12 values (BAD_INDEX)
D CCodecConfig: c2 config diff is Dict {
D CCodecConfig:   c2::u32 coded.pl.level = 20496
D CCodecConfig:   c2::u32 coded.pl.profile = 20481
D CCodecConfig:   c2::u32 coded.vui.color.matrix = 0
D CCodecConfig:   c2::u32 coded.vui.color.primaries = 0
D CCodecConfig:   c2::u32 coded.vui.color.range = 2
D CCodecConfig:   c2::u32 coded.vui.color.transfer = 0
D CCodecConfig:   c2::u32 default.color.matrix = 0
D CCodecConfig:   c2::u32 default.color.primaries = 0
D CCodecConfig:   c2::u32 default.color.range = 0
D CCodecConfig:   c2::u32 default.color.transfer = 0
D CCodecConfig:   c2::u32 input.buffers.max-size.value = 6291456
D CCodecConfig:   c2::u32 input.delay.value = 0
D CCodecConfig:   string input.media-type.value = "video/avc"
D CCodecConfig:   c2::u32 output.delay.value = 8
D CCodecConfig:   string output.media-type.value = "video/raw"
D CCodecConfig:   c2::u32 raw.color.matrix = 0
D CCodecConfig:   c2::u32 raw.color.primaries = 0
D CCodecConfig:   c2::u32 raw.color.range = 2
D CCodecConfig:   c2::u32 raw.color.transfer = 0
D CCodecConfig:   c2::u32 raw.max-size.height = 240
D CCodecConfig:   c2::u32 raw.max-size.width = 320
D CCodecConfig:   c2::u32 raw.pixel-format.value = 35
D CCodecConfig:   c2::i32 raw.rotation.flip = 0
D CCodecConfig:   c2::i32 raw.rotation.value = 0
D CCodecConfig:   c2::u32 raw.sar.height = 1
D CCodecConfig:   c2::u32 raw.sar.width = 1
D CCodecConfig:   c2::u32 raw.size.height = 240
D CCodecConfig:   c2::u32 raw.size.width = 320
D CCodecConfig:   c2:
W ColorUtils: expected specified color aspects (2:0:0:0)
D MediaCodec: flushMediametrics
D SurfaceUtils: connecting to surface 0x7711d4fabf10, reason connectToSurface
I MediaCodec: [c2.goldfish.h264.decoder] setting surface generation to 16730113
D SurfaceUtils: disconnecting from surface 0x7711d4fabf10, reason connectToSurface(reconnect)
D SurfaceUtils: connecting to surface 0x7711d4fabf10, reason connectToSurface(reconnect)
D CCodec  : [c2.goldfish.h264.decoder] buffers are bound to CCodec for this session
D CCodecConfig: no c2 equivalents for csd-1
D CCodecConfig: no c2 equivalents for native-window
D CCodecConfig: no c2 equivalents for flags
D CCodecConfig: config failed => CORRUPTED
D CCodecConfig: c2 config diff is   c2::u32 raw.size.height = 1080
D CCodecConfig:   c2::u32 raw.size.width = 1920
W Codec2Client: query -- param skipped: index = 1107298332.
D CCodec  : encoding statistics level = 0
D CCodec  : setup formats input: AMessage(what = 0x00000000) = {
D CCodec  :   int32_t height = 1080
D CCodec  :   int32_t level = 65536
D CCodec  :   int32_t max-input-size = 6291456
D CCodec  :   string mime = "video/avc"
D CCodec  :   int32_t profile = 65536
D CCodec  :   int32_t width = 1920
D CCodec  :   Rect crop(0, 0, 1919, 1079)
D CCodec  : }
D CCodec  : setup formats output: AMessage(what = 0x00000000) = {
D CCodec  :   int32_t android._color-format = 2135033992
D CCodec  :   int32_t android._video-scaling = 1
D CCodec  :   int32_t rotation-degrees = 0
D CCodec  :   int32_t color-standard = 1
D CCodec  :   int32_t color-range = 2
D CCodec  :   int32_t color-transfer = 3
D CCodec  :   int32_t sar-height = 1
D CCodec  :   int32_t sar-width = 1
D CCodec  :   Rect crop(0, 0, 1919, 1079)
D CCodec  :   int32_t width = 1920
D CCodec  :   int32_t height = 1080
D CCodec  :   int32_t max-height = 240
D CCodec  :   int32_t max-width = 320
D CCodec  :   string mime = "video/raw"
D CCodec  :   int32_t android._dataspace = 260
D CCodec  :   int32_t color-format = 2130708361
D CCodec  : }
I CCodecConfig: query failed after returning 12 values (BAD_INDEX)
D CCodecConfig: c2 config diff is   c2::u32 raw.max-size.height = 1080
D CCodecConfig:   c2::u32 raw.max-size.width = 1920
W Codec2Client: query -- param skipped: index = 1342179345.
W Codec2Client: query -- param skipped: index = 2415921170.
W Codec2Client: query -- param skipped: index = 1610614798.
W Codec2Client: query -- param skipped: index = 2684356609.
D C2Store : Using DMABUF Heaps
D CCodecBufferChannel: [c2.goldfish.h264.decoder#552] Created input block pool with allocatorID 16 => poolID 17 - OK (0)
D CCodecBufferChannel: [c2.goldfish.h264.decoder#552] Query output surface allocator returned 0 params => BAD_INDEX (6)
I CCodecBufferChannel: [c2.goldfish.h264.decoder#552] Created output block pool with allocatorID 18 => poolID 41 - OK
D CCodecBufferChannel: [c2.goldfish.h264.decoder#552] Configured output block pool ids 41 => OK
D Codec2-OutputBufferQueue: remote graphic buffer migration 0/0
D Codec2Client: setOutputSurface -- failed to set consumer usage (6/BAD_INDEX)
D Codec2Client: setOutputSurface -- generation=16730113 consumer usage=0x900
D Codec2Client: Surface configure completed
I DMABUFHEAPS: Using DMA-BUF heap named: system
D CCodecBufferChannel: [c2.goldfish.h264.decoder#552] Ignoring stale input buffer done callback: last flush index = 0, frameIndex = 0
D CCodecBufferChannel: [c2.goldfish.h264.decoder#552] MediaCodec discarded an unknown buffer
D CCodecBufferChannel: [c2.goldfish.h264.decoder#552] MediaCodec discarded an unknown buffer
I CCodecConfig: query failed after returning 12 values (BAD_INDEX)
W Codec2Client: query -- param skipped: index = 1342179345.
W Codec2Client: query -- param skipped: index = 2415921170.
W Codec2Client: query -- param skipped: index = 1610614798.
D BufferPoolAccessor2.0: bufferpool2 0x771134fb5ce8 : 5(31457280 size) total buffers - 4(25165824 size) used buffers - 5/10 (recycle/alloc) - 2/2 (fetch/transfer)
D BufferPoolAccessor2.0: evictor expired: 1, evicted: 1

---
Israel Brewster
Software Engineer
Alaska Volcano Observatory 
Geophysical Institute - UAF 
2156 Koyukuk Drive 
Fairbanks AK 99775-7320
Work: 907-474-5172
cell:  907-328-9145

>> 
>> Question/problem:
>> 
>> So now that I have photos displaying on Android, I wanted to be able to display a RTSP stream. To that end, I have the following code:
>> 
>> void MainWindow::testMediaPlayer(){
>>     if(videoFrame!=nullptr){
>>         videoFrame->deleteLater();
>>     }
>>     videoFrame=new QVideoWidget;
>>     ui->videoLayout->addWidget(videoFrame);
>> 
>>     if(videoPlayer!=nullptr){
>>         videoPlayer->deleteLater();
>>     }
>>     if(audioOutput!=nullptr){
>>         audioOutput->deleteLater();
>>     }
>> 
>>     videoPlayer=new QMediaPlayer;
>>     connect(this, &MainWindow::stopRTSP,
>>            videoPlayer,&QMediaPlayer::stop,
>>            Qt::QueuedConnection);
>>     audioOutput=new QAudioOutput;
>>     videoPlayer->setAudioOutput(audioOutput);
>>     videoPlayer->setVideoOutput(videoFrame);
>>     videoPlayer->setSource(QUrl("rtsp://xx.xx.xx.xx:554/11" <rtsp://xx.xx.xx.xx:554/11>));
>>     ui->viewStack->setCurrentIndex(1); //using a stacked widget to display video separately from still images.
>>     videoPlayer->play();
>> }
>> 
>> This code works fine when compiled/run on my mac, but when run on Android I just get a black screen. The QMediaPlayer documentation seems to indicate that FFMPEG is used on both Mac and Android platforms, so it seems as though if it works on one, it should work on the other (unless the Android version of FFMPEG is more limited?)
>> 
>> I tried giving my app the android.permission.INTERNET, which returns that it is granted when I request it, but that doesn’t appear to have helped.
>> 
>> Also, VLC on the emulator does play the video correctly, so apparently it’s not an access issue with the tablet not being able to access the stream.
>> ---
>> Israel Brewster
>> Software Engineer
>> Alaska Volcano Observatory 
>> Geophysical Institute - UAF 
>> 2156 Koyukuk Drive 
>> Fairbanks AK 99775-7320
>> Work: 907-474-5172
>> cell:  907-328-9145
>> 
>> 
>> 
>> _______________________________________________
>> Interest mailing list
>> Interest at qt-project.org <mailto:Interest at qt-project.org>
>> https://lists.qt-project.org/listinfo/interest
> 
> _______________________________________________
> Interest mailing list
> Interest at qt-project.org
> https://lists.qt-project.org/listinfo/interest

-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.qt-project.org/pipermail/interest/attachments/20240716/e20476c9/attachment.htm>


More information about the Interest mailing list