Wrap InputStream in a File (for MediaPortal TVserver client in XBMC)
#1
I am writing a MediaPortal TVServer client in XBMC, and want to write a new File that will represent a channel. I want to be able to switch channels directly while watching a single channel.

To do this, I have a class, TVServerFile, and in this class, I need to wrap an RTSP file (As that is the actual format of the file I get back from TV Server).

So - I have NO idea how to do this. My poor attempt,
http://pastebin.com/m1b62646a

Tries to open a rtsp file using an input stream, but this .. doesn't really seem to work. So what is the *proper* way to open the RTSP file, and then wrap my file around it?
Reply
#2
if you want to present a file, use the file system classes. there is no need to do a special input stream unless you need broader control, i.e. if things like seek() does not only take place on the file level.
Reply
#3
How can I create a file out of the RTSP url?

Is there a standard way to open and get a file out of it that I can then then decorate?
Reply
#4
you implement a CFile class, CFileTVServer. this again returns only the rtsp formatted data in Read() etc. all the players would see is a bitstream holding a rtsp file.
Reply
#5
Oh sorry - the CTVServerFile class is an implementation of CFile, the problem is I don't know how I can return the rtsp data. Here is the CTVServerFile.h file,
http://pastebin.com/m221491b5

The problem is with opening the RTSP file, and returning that data when a function in my class is called.
Reply
#6
there is no need for an input stream in the file class.

you just return the rtsp data in Read(), perform seeks on the rtsp file etc. the world outside the CFile doesn't care WHERE its data comes from. if the outside worl ask for 16 bytes, you return 16 bytes. where you read that data from is utterly irrelevant. you probably want to use a CFileCurl to actually read from the tvserver end, then forward the calls to that class.
Reply
#7
Hm I think I may have forgotten to mention - it is a network stream, so

rtsp://192.168.1.2/stream1.0 is the file I am trying to play.

Now, I understand the idea of just returning the data, which would work if it was a local file, but I don't have access to the file itself. In fact, I'm not even sure how rtsp connects (I think it can use TCP or UDP).

Thanks for your help by the way Smile
Reply
#8
well, rtsp can transport its data over either rtp or http. (and probably others).

if its a http transport, you simply use a CFileCurl (as i mentioned) to open the rtsp file to get the data. if its a rtp transport, you need to do a rtp file class that is used to get the data.

note that there is already rtsp input support in ffmpeg, and hence in dvdplayer. not sure how well it works currently though. if you want to use that, you should do this as an input stream in dvdplayer, which passes the actual reading on to CDVDInputStreamFFmpeg
Reply
#9
Oh of course! I was implementing it as a file when I should have been making it as an input stream. I will use the ffmpeg one and hopefully get it working. Thanks for all your help.
Reply
#10
So modified the file, made it an input stream,
http://pastebin.com/m5c671ae0

It doesn't work however.. The way it is done currently causes it to fail at:

Code:
01:42:05 T:2961010688 M:204980224  NOTICE: Creating Demuxer
01:42:05 T:2961010688 M:204951552   ERROR: ABOUT TO READ??
01:42:05 T:2961010688 M:204951552   ERROR: ABOUT TO READ AMOUNT 32768
01:42:05 T:2961010688 M:204951552   ERROR: READ RETURNED : 32768
01:42:05 T:2961010688 M:204951552   ERROR: YES. READING COMPLETE WITH 001:42:05 T:2961010688 M:204951552   ERROR: Open - error reading from input stream,
01:42:05 T:2961010688 M:204951552   ERROR: OpenDemuxStream - Error creating demuxer

The extra logs are by me, the first and last about to read / read complete are in the ffmpeg input stream code,
Code:
CLog::Log(LOGERROR, "ABOUT TO READ??\n");
      pd.buf_size = m_dllAvFormat.get_buffer(m_ioContext, pd.buf, sizeof(probe_buffer));            
      CLog::Log(LOGERROR, "YES. READING COMPLETE WITH %d\n", pd.buf_size);

whereas the others are just in my CTVServerFile.

I am not 100% sure what to do - it looks like I need to declare myself as DVDSTREAM_TYPE_FFMPEG, but then FFMPEG won't open me as my protocol is tvserver:// which it has no idea about. Doing what I'm doing now, for some reason the demuxer fails. I have no idea what the m_dllAvFormat.get_buffer is failing at, as it obviously reads the bytes it wants from the rtsp file (READ RETURNED : 32768), yet it returns that it read 0 bytes.

Is it likely this will work, as I'm starting to doubt whether this is possible in the way I am doing it.
Reply
#11
you need to

1) add a DVDSTREAM_TYPE_TVSERVER and assign this to your class in the factory, e.g. tvserver://
2) have a CDVDInputStreamFFMPEG as a member var
3) do the tvserver parsing to get the real rtsp url
4) open your member var on this url
5) make Read() etc in tvserver wrapper functions which calls through to your member var input stream
Reply
#12
Hm, I have managed to get it working:
http://pastebin.com/m1bc4159b

I haven't yet tried to get channel + / - working.

The main thing that I couldn't figure out earlier, I had to do this:
Code:
+  else if (m_pInput->IsStreamType(DVDSTREAM_TYPE_TVSERVER))
+  {
+    // we have a tv server file, but it wraps rtsp, an internal ffmpeg protocol
+    
+    CTVServerFile *tvServerFile = static_cast<CTVServerFile*>(pInput);
+    const CStdString rtspUrl = tvServerFile->GetRTSPStream();
+    CLog::Log(LOGERROR, "About to open a TVSERVER stream: %s\n", rtspUrl.c_str());
+    // supposedly speeds up opening live tv
+    // m_pFormatContext->max_analyze_duration = 500000;
+    
+    if( m_dllAvFormat.av_open_input_file(&m_pFormatContext, rtspUrl.c_str(), iformat, FFMPEG_FILE_BUFFER_SIZE, NULL) < 0 )

Basically opens the actual RTSP file using internal ffmpeg libraries. Wrapping read etc doesn't work because rtsp is internal to ffmpeg. It looks like it works now - just want to make sure its the right way to do it. It takes ages to open a file at the moment - where can I disable caching?

Also, a small bug in the code I found:
Code:
cores/dvdplayer/DVDInputStreams/DVDFactoryInputStream.cpp:55:       || file.substr(0, 7) == "cmyth://"
cores/dvdplayer/DVDInputStreams/DVDFactoryInputStream.cpp:56:       || file.substr(0, 7) == "gmyth://")

I am quite sure substr's second argument should be 8.
Reply
#13
thx, typos fixed in svn
Reply
#14
Thumbs Up 
@EvilDude, have you looked at the MythTV client ("mythtv://") in XBMC for reference and comparison?

Huh
Always read the XBMC online-manual, FAQ and search the forum before posting.
Do not e-mail XBMC-Team members directly asking for support. Read/follow the forum rules.
For troubleshooting and bug reporting please make sure you read this first.
Reply
#15
see DVDDemuxFFmpeg.cpp - replicate what's done for DVDSTREAM_TYPE_FFMPEG there
Reply

Logout Mark Read Team Forum Stats Members Help
Wrap InputStream in a File (for MediaPortal TVserver client in XBMC)0