[Ffmpeg-devel] [RFC/Patch] native mms code...

Ryan Martell rdm4
Tue Feb 27 21:28:42 CET 2007


Hi---

On Jan 5, 2007, at 3:56 PM, Ryan Martell wrote:
> On Jan 5, 2007, at 2:23 PM, Michael Niedermayer wrote:
>
>> Hi
>>
>> On Fri, Jan 05, 2007 at 11:36:15AM -0600, Ryan Martell wrote:
>> [...]
>>>> all strings in ffmpeg are supposed to be utf-8 so the name
>>>> convert_to_unicode
>>>> is wrong, it rather should be something like convert_utf8_to_utf16
>>>> and should
>>>> use GET_UTF8() (unless you know that the input will be ASCII)
>>>
>>> Is there an example of unicode conversion in the code base?  I  
>>> really
>>> didn't know how to do this (or even if there was some library
>>> function), so I just punted and did it a simple way.  I didn't want
>>> to get hung up on the conversion....
>>
>> see ascii_to_wc() in mov.c
>
> Perfect.  Thanks.

I couldn't use this one, because it's big endian, and I needed little  
endian.  I have a put_le_utf16 instead.

>>>>> static void generate_guid(char *dst)
>>>>> {
[..]
>>>>>                *dst++= digit[random()%(sizeof(digit)/sizeof(digit
>>>>> [0]))];
>>>>
>>>> random() must not be used in libraries as it changes the user

[..]
>>> Should I roll my own random, or
>>> maybe add an internal random to ffmpeg?
>>
>> a LFG or mersenne twister based av_random() for libavutil would  
>> certainly
>> be welcome see the pseudeocode on http://en.wikipedia.org/wiki/ 
>> Mersenne_twister
>> and http://svn.mplayerhq.hu/ac3/ac3_decoder.c?revision=23&view=markup
>
> Will add it in; there's actually c code available referenced from  
> there, so I'll tweak it to fit in the ffmpeg framework and submit.

Done (on another thread)

>> [...]
>>
>>>> [...]
>>>>> static int mms_read_packet(AVFormatContext *s,
>>>>>                            AVPacket *pkt)
>>>>> {
>>>>>    MMSState *mms = s->priv_data;
>>>>>    int result= 0;
>>>>>
>>>>> //    fprintf(stderr, "mms_read_packet!\n");
>>>>>
>>>>>    if(mms->state==STREAMING || mms->state==STREAM_PAUSED || mms-
>>>>>> state==AWAITING_STREAM_START_PACKET)
>>>>>    {
>>>>> //        result= ff_asf_read_packet(s, pkt, &mms->asf_context,
>>>>> &mms->current_media_packet_context, load_packet, mms);
>>>>> //        result= ff_asf_read_packet(s, pkt, &mms->asf_context,
>>>>> &mms->av_format_ctx->pb, load_packet, mms);
>>>>>        result= ff_asf_read_packet_with_load_proc(s, pkt,
>>>>> load_packet, mms);
>>>>
>>>> isnt it possible that the mms AVInputFormat provides the asf
>>>> AVInputFormat
>>>> with a valid asf stream instead of this callback to get the next
>>>> packet?
>>>
>>> I was trying to do that initially, but i ran into lots and lots of
>>> url_ftell's in the asf code, that were causing it to error out.  by
>>> putting the packet load as a separate call, i could make sure the
>>> ftell's would be valid, and the code would continue.  The asf  
>>> code is
>>> really pretty dependent on it being file based.
>>>
>>> But, I'm not the expert on working with this code base; if anyone  
>>> can
>>> give me any suggestions on how to further separate these, I'd
>>> appreciate them.  I'm not exactly sure what you mean by providing  
>>> the
>>> asf AVInputFormat with a valid asf stream; all that the asf stuff
>>> does is read from the ByteIOContext.
>>
>> hmm, so what about providing the asf demuxer with a ByteIOContext?
>> a simple fixed size buffer + a read_packet function passed to
>> init_put_byte() might work ...
>
> I think I tried that, but it didn't work for some reason.  But I  
> think I have learned more since then & can try it again.

This new solution is much cleaner, it doesn't require any changes to  
asf.c except making asf_reset_header() public (ff_asf_reset_header()).

> From the other thread:
> On Jan 5, 2007, at 11:36 AM, Ryan Martell wrote:
>> On Jan 5, 2007, at 8:07 AM, Michael Niedermayer wrote:
>>
>>> Hi
>>>
>>> On Tue, Jan 02, 2007 at 04:51:07PM -0600, Ryan Martell wrote:
>>>
>>>> 4) MMS has parameters for the tcp connection bitrate; and if there
>>>> are multiple encodings in the file, it will choose the best  
>>>> ones.  I
>>>> am currently only streaming the first audio and first video stream.
>>>> How would i get the bandwidth input from the user?  I know we don't
>>>> want to add new AVOptions that aren't globally useful.  Also, I  
>>>> could
>>>> ask for audio only in this manor.
>>>
>>> see AVStream.discard
>>
>> Will look into it.
>
> I don't think this is what I was looking for.  Specifically, when I  
> am establishing the mms stream, I can ask for any one of a number  
> of streams (it may have an audio stream, and a low, medium, and  
> high quality all in the same file).  The way Windoze handles that  
> is by a bitrate setting, where it chooses the best stream that will  
> fit within the specified bitrate.  So essentially I'd need a  
> bitrate parameter.  Also, I want to be able to stream audio only,  
> so I want to have the option of turning off the video stream.  The  
> rtp stuff uses a similiar feature, with the tcp settings global.  I  
> don't want to use a global if i don't have to; what's the better way?
>
> Code for stream selection:
>     }

I still don't have a good answer for this one; will go back over the  
thread and reread Michael's comments to see if something comes to  
me.  Currently it's still in globals, like rtp's.

>>> [...]
>>>> static int get_server_response(MMSState *mms)
>>>> {
>>>>     // read the 8 byte header...
>>>>     int read_result;
>>>>     int packet_type= -1;
>>>>     int done;
>>>>
>>>>     do {
>>>>         done= 1; // assume we're going to get a valid packet.
>>>>         if((read_result= read_bytes(mms, mms->incoming_buffer,  
>>>> 8))==8)
>>>>         {
>>>>             // check if we are a command packet...
>>>>             if(LE_32(mms->incoming_buffer + 4)==0xb00bface) {
>>>
>>> this is ugly
>>>
>>> (url_fdopen(xyz, mms->mms_hd);)
>>> get_le32(xyz)
>>> get_le32(xyz)
>>>
>>> or similar is much cleaner
>>
>> Will check that out; it sounds better.
>
> That's great; will reimplement to use that.

Done, but I still read them as it was before.  I might be able to  
make a stream scanner, that will ignore garbage until it hits the  
0xb00bface, then starts from there.

>>> [...]
>>>> static int mms_stream_play_from_timestamp(MMSState *mms, int64_t  
>>>> timestamp)
>>>> {
>>>>     double ts= timestamp/1000;
>>>>
>>>>     fprintf(stderr, "mms_stream_play: %lld TS: %lf\n",  
>>>> timestamp, ts);
>>>>     if(mms->state==STREAM_PAUSED)
>>>>     {
>>>>         timestamp= *((int64_t *)&ts);
>>>
>>> completely non portable, see libavutil/intfloat_readwrite.*
>>
>> Thanks for the reference; I knew when I wrote that it was  
>> unportable, but didn't know where to look.  I did it this way just  
>> to check and make sure it would work, and it does.
>
> again, that's just what i needed.

Done.

>>> [...]
>>>>                     if((mms->incoming_flags == 0X08) || (mms- 
>>>> >incoming_flags == 0X0C))
>>>>                     {
>>>>                         // we are done with the header stuff.
>>>>                         ByteIOContext byte_context;
>>>>
>>>>                         fprintf(stderr, "Got the full header! (% 
>>>> d bytes)\n", mms->asf_header_length);
>>>>                         // parse the header....
>>>>                         init_put_byte(&byte_context, mms- 
>>>> >asf_header, mms->asf_header_length, 0, NULL, NULL, NULL, NULL);
>>>>                         if(ff_asf_read_header(mms- 
>>>> >av_format_ctx, &mms->asf_context, &byte_context)==0)
>>>>                         {
>>>>                             int stream_count= 2;
>>>>                             int ii;
>>>>
>>>>                             //  send the streams we want back...
>>>>                             put_flush_packet(&mms->packet_data);
>>>>                             put_le32(&mms->packet_data,  
>>>> stream_count);
>>>>                             for(ii= 0; ii<stream_count; ii++)
>>>>                             {
>>>>                                 put_le16(&mms->packet_data,  
>>>> 0xffff); // flags
>>>>                                 put_le16(&mms->packet_data, ii 
>>>> +1); // stream id
>>>>                                 /*
>>>>                                  00 = stream at full frame rate;
>>>>                                  01 = only stream key frames;
>>>>                                  02 = no stream, switch it off.
>>>>                                  */
>>>>                                 put_le16(&mms->packet_data,  
>>>> 00); // stream at full frame rate
>>>
>>> AVStream.discard could be used here maybe?
>>
>> Not familiar with that; will check it out.
>
> Again, I don't think so (unless I'm missing something).  This is  
> telling the server what to send; it has no bearing on the client  
> (except, of course, that the client can only play what the server  
> sends)
>
> Will work on implementing the other changes over the weekend and  
> getting a another version up for RFC.

Here'a another version.  There are lots of internal changes, mainly  
designed to get it to work as cleanly as possible with asf.c.  This  
version isn't tested as much as the previous version (I've only  
tested it on live video streams, not on demand stuff), but it does  
work for that.

Let me know what people think....

Thanks,
-Ryan

PS: Once this file gets through review, I can submit full patch,  
including makefile.

-------------- next part --------------
A non-text attachment was scrubbed...
Name: native_mms.c
Type: application/octet-stream
Size: 56892 bytes
Desc: not available
URL: <http://lists.mplayerhq.hu/pipermail/ffmpeg-devel/attachments/20070227/8226dc8f/attachment.obj>
-------------- next part --------------





More information about the ffmpeg-devel mailing list