Sintonizador de TV HDHomeRun com GStreamer

0

Estou tentando ler o feed RTP do meu sintonizador HDHR sem sucesso. Alguém tem experiência com isso?

GStreamer:

gst-launch --gst-debug=udpsrc:5 udpsrc port=5000 caps="application/x-rtp,media=(string)video,format=(fourcc)I420, width=(int)720, height=(int)480,encoding-name=(string)RAW,sampling=(string)YUV,pixel-aspect-ratio=(fraction)8/9, framerate=(fraction)30000/1001, interlaced=(boolean)true" ! gstrtpbin ! rtpvrawdepay ! filesink location=/tmp/output
  • Eu consegui os recursos via autodetecção de alguma forma, em algum momento.

HDHR:

hdhomerun_config 1310DA25 set /tuner2/target udp://192.168.5.102:5000

Quando tento enviar via RTP (rtp: //192.168.5.102: 5000, em vez de usar o UDP, como acima), recebo um erro UDP toda vez, não importa quais recursos, sempre que ele afunda no gstrtpbin:

ERROR: from element /GstPipeline:pipeline0/GstUDPSrc:udpsrc0: Internal data flow error.

Estou assumindo que isso significa que os recursos não correspondem entre os blocos vinculados.

Quando uso o esquema UDP (originalmente, acima), não recebo nenhum erro, mas nenhum dado é movido pelo pipeline.

- gst-debug em vários elementos em vários níveis não me deu nada útil.

O VLC funciona perfeitamente, esteja eu enviando para o rtp: //xxx.xxx.xxx.xxx: nnnn e recebendo no rtp: //: nnnn, ou enviando para udp: //xxx.xxx.xxx.xxx : nnnn e recebendo no udp: //: nnnn.

Alguma opinião?

Além disso, o GST não consegue identificar automaticamente os recursos do fluxo RTP? Eu não sei como eu tropecei nele (para obter as capacidades acima), mas não parece muito intuitivo. Parece que se o VLC (super-versátil) pudesse fazer isso, o GStreamer (também super-versátil) poderia fazê-lo.

Obrigado.

Dustin

A propósito, eu comprei isso usando o playbin2:

dustin@dustinlenovo:/tmp$ gst-launch --gst-debug=playbin2:5 playbin2 uri=udp://192.168.5.102:5000
0:00:00.021952272 32470  0x9683400 LOG                 playbin2 gstplaybin2.c:1318:gst_playbin_uri_is_valid:<playbin20> checking uri 'udp://192.168.5.102:5000'
0:00:00.022006314 32470  0x9683400 DEBUG               playbin2 gstplaybin2.c:1372:gst_play_bin_set_uri: set new uri to udp://192.168.5.102:5000
Setting pipeline to PAUSED ...
0:00:00.022144060 32470  0x9683400 LOG                 playbin2 gstplaybin2.c:3895:gst_play_bin_change_state:<playbin20> clearing shutdown flag
0:00:00.022164495 32470  0x9683400 DEBUG               playbin2 gstplaybin2.c:3790:setup_next_source:<playbin20> setup sources
0:00:00.022194614 32470  0x9683400 DEBUG               playbin2 gstplaybin2.c:3477:activate_group:<playbin20> activating group 0x9711318
0:00:00.022208169 32470  0x9683400 DEBUG               playbin2 gstplaybin2.c:3498:activate_group:<playbin20> making new uridecodebin
0:00:00.022597792 32470  0x9683400 DEBUG               playbin2 gstplaybin2.c:3456:group_set_locked_state_unlocked:<playbin20> locked_state 0 on group 0x9711318
0:00:00.023812556 32470  0x9683400 DEBUG               playbin2 gstplaybin2.c:2317:gst_play_bin_handle_message:<playbin20> Ignoring async state change of uridecodebin: uridecodebin0
Pipeline is live and does not need PREROLL ...
Setting pipeline to PLAYING ...
New clock: GstSystemClock





0:00:14.542698212 32470  0x95e5720 DEBUG               playbin2 gstplaybin2.c:3214:autoplug_continue_cb:<playbin20> continue autoplugging group 0x9711318 for '':decodepad0, video/mpegts, systemstream=(boolean)true, packetsize=(int)188: 1
0:00:14.542910589 32470  0x95e5720 DEBUG               playbin2 gstplaybin2.c:3049:autoplug_factories_cb:<playbin20> factories group 0x9711318 for '':decodepad0, video/mpegts, systemstream=(boolean)true, packetsize=(int)188
0:00:14.550811109 32470  0x95e5720 DEBUG               playbin2 gstplaybin2.c:3059:autoplug_factories_cb:<playbin20> found factories 0xb64189b0
0:00:14.551117538 32470  0x95e5720 DEBUG               playbin2 gstplaybin2.c:3268:autoplug_select_cb:<playbin20> select group 0x9711318 for '':decodepad0, video/mpegts, systemstream=(boolean)true, packetsize=(int)188
0:00:14.551202471 32470  0x95e5720 DEBUG               playbin2 gstplaybin2.c:3271:autoplug_select_cb:<playbin20> checking factory mpegtsdemux
0:00:14.713355113 32470  0x95e5720 DEBUG               playbin2 gstplaybin2.c:3214:autoplug_continue_cb:<playbin20> continue autoplugging group 0x9711318 for '':decodepad1, audio/x-ac3: 1
0:00:14.713401299 32470  0x95e5720 DEBUG               playbin2 gstplaybin2.c:3049:autoplug_factories_cb:<playbin20> factories group 0x9711318 for '':decodepad1, audio/x-ac3
0:00:14.713622715 32470  0x95e5720 DEBUG               playbin2 gstplaybin2.c:3059:autoplug_factories_cb:<playbin20> found factories 0xb6418b80
0:00:14.714048757 32470  0x95e5720 DEBUG               playbin2 gstplaybin2.c:3268:autoplug_select_cb:<playbin20> select group 0x9711318 for '':decodepad1, audio/x-ac3
0:00:14.714097628 32470  0x95e5720 DEBUG               playbin2 gstplaybin2.c:3271:autoplug_select_cb:<playbin20> checking factory pulsesink
0:00:14.714125521 32470  0x95e5720 DEBUG               playbin2 gstplaybin2.c:3344:autoplug_select_cb:<playbin20> we found a sink
0:00:14.714151129 32470  0x95e5720 DEBUG               playbin2 gstplaybin2.c:3350:autoplug_select_cb:<playbin20> we found an audio sink
0:00:14.714177845 32470  0x95e5720 DEBUG               playbin2 gstplaybin2.c:3393:autoplug_select_cb:<playbin20> we have no pending sink, try to create one
0:00:14.724957778 32470  0x95e5720 DEBUG               playbin2 gstplaybin2.c:3268:autoplug_select_cb:<playbin20> select group 0x9711318 for '':decodepad1, audio/x-ac3
0:00:14.725003694 32470  0x95e5720 DEBUG               playbin2 gstplaybin2.c:3271:autoplug_select_cb:<playbin20> checking factory ac3parse
0:00:14.725687536 32470  0x95e5720 DEBUG               playbin2 gstplaybin2.c:3049:autoplug_factories_cb:<playbin20> factories group 0x9711318 for '':decodepad2, audio/x-ac3, framed=(boolean)true, channels=(int)[ 1, 6 ], rate=(int)[ 8000, 48000 ], alignment=(string){ iec61937, frame }; audio/x-eac3, framed=(boolean)true, channels=(int)[ 1, 6 ], rate=(int)[ 8000, 48000 ], alignment=(string){ iec61937, frame }
0:00:14.725996661 32470  0x95e5720 DEBUG               playbin2 gstplaybin2.c:3059:autoplug_factories_cb:<playbin20> found factories 0xb6458eb0
0:00:14.728966979 32470  0x95e5720 DEBUG               playbin2 gstplaybin2.c:3214:autoplug_continue_cb:<playbin20> continue autoplugging group 0x9711318 for '':decodepad3, video/mpeg, mpegversion=(int)2, systemstream=(boolean)false: 1
0:00:14.729094763 32470  0x95e5720 DEBUG               playbin2 gstplaybin2.c:3049:autoplug_factories_cb:<playbin20> factories group 0x9711318 for '':decodepad3, video/mpeg, mpegversion=(int)2, systemstream=(boolean)false
0:00:14.730460890 32470  0x95e5720 DEBUG               playbin2 gstplaybin2.c:3059:autoplug_factories_cb:<playbin20> found factories 0xb6418620
0:00:14.731074426 32470  0x95e5720 DEBUG               playbin2 gstplaybin2.c:3268:autoplug_select_cb:<playbin20> select group 0x9711318 for '':decodepad3, video/mpeg, mpegversion=(int)2, systemstream=(boolean)false
0:00:14.731165683 32470  0x95e5720 DEBUG               playbin2 gstplaybin2.c:3271:autoplug_select_cb:<playbin20> checking factory mpegvideoparse
0:00:14.744258860 32470 0xb643be90 DEBUG               playbin2 gstplaybin2.c:3214:autoplug_continue_cb:<playbin20> continue autoplugging group 0x9711318 for '':decodepad5, video/mpeg, mpegversion=(int)2, systemstream=(boolean)false, parsed=(boolean)true: 1
0:00:14.744409010 32470 0xb643be90 DEBUG               playbin2 gstplaybin2.c:3049:autoplug_factories_cb:<playbin20> factories group 0x9711318 for '':decodepad5, video/mpeg, mpegversion=(int)2, systemstream=(boolean)false, parsed=(boolean)true
0:00:14.744667670 32470 0xb643be90 DEBUG               playbin2 gstplaybin2.c:3059:autoplug_factories_cb:<playbin20> found factories 0xb4c00950
0:00:14.744743720 32470 0xb643be90 DEBUG               playbin2 gstplaybin2.c:3268:autoplug_select_cb:<playbin20> select group 0x9711318 for '':decodepad5, video/mpeg, mpegversion=(int)2, systemstream=(boolean)false, parsed=(boolean)true
0:00:14.744758143 32470 0xb643be90 DEBUG               playbin2 gstplaybin2.c:3271:autoplug_select_cb:<playbin20> checking factory mpeg2dec
0:00:14.854031750 32470  0x95e5720 DEBUG               playbin2 gstplaybin2.c:3214:autoplug_continue_cb:<playbin20> continue autoplugging group 0x9711318 for '':decodepad7, audio/x-ac3: 1
0:00:14.854191602 32470  0x95e5720 DEBUG               playbin2 gstplaybin2.c:3049:autoplug_factories_cb:<playbin20> factories group 0x9711318 for '':decodepad7, audio/x-ac3
0:00:14.854649600 32470  0x95e5720 DEBUG               playbin2 gstplaybin2.c:3059:autoplug_factories_cb:<playbin20> found factories 0xb6471880
0:00:14.855619479 32470  0x95e5720 DEBUG               playbin2 gstplaybin2.c:3268:autoplug_select_cb:<playbin20> select group 0x9711318 for '':decodepad7, audio/x-ac3
0:00:14.855700091 32470  0x95e5720 DEBUG               playbin2 gstplaybin2.c:3271:autoplug_select_cb:<playbin20> checking factory pulsesink
0:00:14.855776440 32470  0x95e5720 DEBUG               playbin2 gstplaybin2.c:3344:autoplug_select_cb:<playbin20> we found a sink
0:00:14.855877980 32470  0x95e5720 DEBUG               playbin2 gstplaybin2.c:3350:autoplug_select_cb:<playbin20> we found an audio sink
0:00:14.855955069 32470  0x95e5720 DEBUG               playbin2 gstplaybin2.c:3393:autoplug_select_cb:<playbin20> we have no pending sink, try to create one
0:00:14.861079720 32470  0x95e5720 DEBUG               playbin2 gstplaybin2.c:3268:autoplug_select_cb:<playbin20> select group 0x9711318 for '':decodepad7, audio/x-ac3
0:00:14.861206558 32470  0x95e5720 DEBUG               playbin2 gstplaybin2.c:3271:autoplug_select_cb:<playbin20> checking factory ac3parse
0:00:14.861928499 32470  0x95e5720 DEBUG               playbin2 gstplaybin2.c:3049:autoplug_factories_cb:<playbin20> factories group 0x9711318 for '':decodepad8, audio/x-ac3, framed=(boolean)true, channels=(int)[ 1, 6 ], rate=(int)[ 8000, 48000 ], alignment=(string){ iec61937, frame }; audio/x-eac3, framed=(boolean)true, channels=(int)[ 1, 6 ], rate=(int)[ 8000, 48000 ], alignment=(string){ iec61937, frame }
0:00:14.862580662 32470  0x95e5720 DEBUG               playbin2 gstplaybin2.c:3059:autoplug_factories_cb:<playbin20> found factories 0xb646de20
0:00:14.864351517 32470 0xb643bf50 DEBUG               playbin2 gstplaybin2.c:3214:autoplug_continue_cb:<playbin20> continue autoplugging group 0x9711318 for '':decodepad9, audio/x-ac3, framed=(boolean)true, rate=(int)48000, channels=(int)2, alignment=(string)frame: 1
0:00:14.864560656 32470 0xb643bf50 DEBUG               playbin2 gstplaybin2.c:3049:autoplug_factories_cb:<playbin20> factories group 0x9711318 for '':decodepad9, audio/x-ac3, framed=(boolean)true, rate=(int)48000, channels=(int)2, alignment=(string)frame
0:00:14.865104298 32470 0xb643bf50 DEBUG               playbin2 gstplaybin2.c:3059:autoplug_factories_cb:<playbin20> found factories 0xb4101e40
0:00:14.865443547 32470 0xb643bf50 DEBUG               playbin2 gstplaybin2.c:3268:autoplug_select_cb:<playbin20> select group 0x9711318 for '':decodepad9, audio/x-ac3, framed=(boolean)true, rate=(int)48000, channels=(int)2, alignment=(string)frame
0:00:14.865580106 32470 0xb643bf50 DEBUG               playbin2 gstplaybin2.c:3271:autoplug_select_cb:<playbin20> checking factory pulsesink
0:00:14.865655838 32470 0xb643bf50 DEBUG               playbin2 gstplaybin2.c:3344:autoplug_select_cb:<playbin20> we found a sink
0:00:14.865725210 32470 0xb643bf50 DEBUG               playbin2 gstplaybin2.c:3350:autoplug_select_cb:<playbin20> we found an audio sink
0:00:14.865796342 32470 0xb643bf50 DEBUG               playbin2 gstplaybin2.c:3393:autoplug_select_cb:<playbin20> we have no pending sink, try to create one
0:00:14.871464068 32470 0xb643bf50 DEBUG               playbin2 gstplaybin2.c:3268:autoplug_select_cb:<playbin20> select group 0x9711318 for '':decodepad9, audio/x-ac3, framed=(boolean)true, rate=(int)48000, channels=(int)2, alignment=(string)frame
0:00:14.871598227 32470 0xb643bf50 DEBUG               playbin2 gstplaybin2.c:3271:autoplug_select_cb:<playbin20> checking factory a52dec

Dustin

    
por Dustin Oprea 14.11.2012 / 08:33

2 respostas

1

Você pode usar o GStreamer, mas parece haver uma dificuldade consistente de obter os dados do MPEGTS para ter o vídeo decodificado pronto para renderização. Eu acredito que os plug-ins padrão do MPEGTS sufocam em quadros malformados, assim como o VLC.

Então, se você quiser apenas empurrar os dados MPEGTS brutos do RTP para o mplayer, ele funcionará bem (o mplayer é ótimo para decodificar um fluxo MPEGTS contendo erros):

gst-launch udpsrc port=5011 caps="application/x-rtp, media=video, payload=33, clock-rate=90000" ! fdsink | mplayer -

O valor da capacidade de "carga útil" vem do "Perfil de Áudio / Vídeo RTP" para fluxos MPEG2 compostos por MPEGTS no RFC 3551. O VLC provavelmente tenta decodificar sob alguns desses códigos para receber sem esforço alguns fluxos RTP , como de um HDHomeRun, evitando assim o requisito de um arquivo SDP irritante.

Por outro lado, se você não se importar em usar as ferramentas HDHomeRun para obter os dados do MPEGTS, o GStreamer o verá perfeitamente.

Versão fácil:

hdhomerun_config FFFFFFFF save /tuner0/ - | gst-launch-1.0 fdsrc ! decodebin ! autovideosink

Versão específica (a filtragem de limite é usada para deixar claro que dados estão sendo movidos):

hdhomerun_config FFFFFFFF save /tuner0/ - | gst-launch-1.0 fdsrc ! video/mpegts ! tsdemux ! video/mpeg ! queue ! mpegvideoparse ! mpeg2dec ! xvimagesink

Obviamente, os exemplos não estão preocupados com os fluxos de áudio (o vídeo é sempre uma prioridade mais alta e a fonte do maior erro / risco, pelo menos para mim).

Os caras do Fluendo me dizem que os plugins do GStreamer devem levar em conta o erro. Eu ainda tenho que testar isso. Seu plugin também funciona apenas dentro do GStreamer .10.

EDITAR

Esta é a linha de comando para "assistir" a um feed HDHomeRun. Observe que o número da porta e o número do programa precisarão ser definidos para o que você estiver assistindo, e a biblioteca "A52" AC3 deve ser instalada junto com o plugin "bad" correspondente "a52dec":

gst-launch-0.10 udpsrc port=5011 caps="application/x-rtp, media=video, encoding-name=H264, clock-rate=90000" ! \
    gstrtpbin ! rtpmp2tdepay ! tsdemux program-number=12 name=demux \
        demux. ! queue ! ac3parse ! a52dec ! queue ! audioconvert ! audioresample ! volume ! autoaudiosink \
        demux. ! queue ! mpegvideoparse ! mpeg2dec ! xvimagesink

Note que você pode obter um fluxograma realmente informativo usando a variável de ambiente GST_DEBUG_DUMP_DOT_DIR combinada com o playbin (se você tiver todos os plugins necessários disponíveis).

    
por 20.06.2013 / 07:30
1

Depois de brincar com isso por alguns dias, pude fazer isso funcionar na minha placa de linux Jetson TK1. Você não precisa usar o hdhomerun_config ou abrir um fluxo de rtp / udp. A partir do HDHR você pode simplesmente pegar o stream via http (se você estiver usando um HDHR PRIME).

O abaixo é o seguinte que eu precisava para despejar um canal para um arquivo para um POC. A parte mais importante é "video / x-raw, format = I420" ou você receberá um erro. omxh264enc é extremamente exigente quanto ao tamanho do quadro, e com o I420 você pode usar qualquer tamanho.

# 10.10.10.100 is the IP of the HDHR
# v588 is the example virtual channel to grab on the HDHR
# Audio is encoded to aac @ 192k

sudo gst-launch-1.0 souphttpsrc location="http://10.10.10.100:5004/auto/v588" is-live=true ! decodebin name=demux demux. ! queue ! audioresample ! audioconvert dithering=0 ! "audio/x-raw,channels=2" ! voaacenc bitrate=192000 ! mux. matroskamux name=mux streamable=true ! filesink location=output.mkv demux. ! queue ! videoconvert ! video/x-raw,format=I420 ! omxh264enc ! video/x-h264,stream-format=byte-stream,profile=high ! h264parse ! mux.

Agora eu gostaria de usar o flvmux + rtmpsink, mas não sei como construir o pipe.

    
por 09.12.2015 / 06:45

Tags