[FFmpeg-soc] [soc]: r5666 - mms/mmst.c

spyfeng subversion at mplayerhq.hu
Sun Mar 14 18:36:16 CET 2010


Author: spyfeng
Date: Sun Mar 14 18:36:15 2010
New Revision: 5666

Log:
rewrite the mmst.c.
simplify the code with removing state machine.

Modified:
   mms/mmst.c

Modified: mms/mmst.c
==============================================================================
--- mms/mmst.c	Sat Mar 13 14:55:11 2010	(r5665)
+++ mms/mmst.c	Sun Mar 14 18:36:15 2010	(r5666)
@@ -26,30 +26,6 @@
 #include "network.h"
 #include "asf.h"
 
-#define DEBUG
-#define MMS_MAXIMUM_PACKET_LENGTH 512
-#define DEFAULT_MMS_PORT      1755
-
-/** State machine states. */
-typedef enum {
-    AWAITING_SC_PACKET_CLIENT_ACCEPTED= 0,
-    AWAITING_SC_PACKET_TIMING_TEST_REPLY_TYPE,
-    AWAITING_CS_PACKET_PROTOCOL_ACCEPTANCE,
-    AWAITING_PASSWORD_QUERY_OR_MEDIA_FILE,
-    AWAITING_PACKET_HEADER_REQUEST_ACCEPTED_TYPE,
-    AWAITING_STREAM_ID_ACCEPTANCE,
-    AWAITING_STREAM_START_PACKET,
-    AWAITING_ASF_HEADER,
-    ASF_HEADER_DONE,
-    AWAITING_PAUSE_ACKNOWLEDGE,
-    AWAITING_HTTP_PAUSE_CONTROL_ACKNOWLEDGE,
-    STREAMING,
-    STREAM_DONE,
-    STATE_ERROR,
-    STREAM_PAUSED,
-    USER_CANCELLED
-} MMSState;
-
 /** Client to server packet types. */
 typedef enum {
     CS_PACKET_INITIAL_TYPE= 0x01,
@@ -101,7 +77,6 @@ typedef struct {
     uint32_t local_ip_address; ///< Not ipv6 compatible, but neither is the protocol (sent, but not correct).
     int local_port; ///< My local port (sent but not correct).
     int sequence_number; ///< Outgoing packet sequence number.
-    MMSState state; ///< Packet state machine current state.
     char path[256]; ///< Path of the resource being asked for.
     char host[128]; ///< Host of the resources.
     int port; ///< Port of the resource.
@@ -111,7 +86,7 @@ typedef struct {
     /** Buffer for outgoing packets. */
     /*@{*/
     ByteIOContext outgoing_packet_data; ///< Outgoing packet stream
-    uint8_t outgoing_packet_buffer[MMS_MAXIMUM_PACKET_LENGTH]; ///< Outgoing packet data
+    uint8_t outgoing_packet_buffer[512]; ///< Outgoing packet data
     /*@}*/
 
     /** Buffer for incoming control packets. */
@@ -150,28 +125,9 @@ typedef struct {
     int stream_num;
 } MMSContext;
 
-/** Perform state transition. */
-static void ff_mms_set_state(MMSContext *mms, int new_state)
-{
-    /* Can't exit error state */
-    if(mms->state==STATE_ERROR) {
-        dprintf(NULL, "Trying to set state to %d from %d!\n", new_state, mms->state);
-        return;
-    }
-
-    dprintf(NULL, "Set state to %d from %d!\n", new_state, mms->state);
-    if(mms->state==new_state && new_state==USER_CANCELLED) {
-        ff_mms_set_state(mms, STATE_ERROR);
-        return;
-    }
-
-    mms->state= new_state;
-}
-
 /** Close the remote connection. */
 static void close_connection(MMSContext *mms)
 {
-//    av_freep(&mms->incoming_io_buffer.buffer);
     url_close(mms->mms_hd);
 }
 
@@ -257,29 +213,15 @@ static int send_command_packet(MMSContex
     write_result= url_write(mms->mms_hd, context->buffer, exact_length);
     if(write_result != exact_length) {
         dprintf(NULL, "url_write returned: %d != %d\n", write_result, exact_length);
-
-        ff_mms_set_state(mms, STATE_ERROR);
         return AVERROR_IO;
     }
 
     return 0;
 }
 
-
-/** Log unexpected incoming packet */
-static void log_packet_in_wrong_state(MMSContext *mms, MMSSCPacketType packet_type)
-{
-    if(packet_type>=0) {
-       dprintf(NULL, "Got a packet 0x%02x in the wrong state: %d!\n", packet_type, mms->state);
-    } else {
-       dprintf(NULL, "Got a pseudo-packet %d in the wrong state: %d!\n", packet_type,  mms->state);
-    }
-}
-
 static int send_protocol_select(MMSContext *mms)
 {
     char data_string[256];
-    int err= 0;
 
     // send the timing request packet...
     start_command_packet(mms, CS_PACKET_PROTOCOL_SELECT_TYPE);
@@ -297,14 +239,11 @@ static int send_protocol_select(MMSConte
     put_le_utf16(&mms->outgoing_packet_data, data_string);
     put_le16(&mms->outgoing_packet_data, 0x30);
 
-    err = send_command_packet(mms);
-    ff_mms_set_state(mms, AWAITING_CS_PACKET_PROTOCOL_ACCEPTANCE);
-    return err;
+    return send_command_packet(mms);
 }
 
 static int send_media_file_request(MMSContext *mms)
 {
-    int err= 0;
     start_command_packet(mms, CS_PACKET_MEDIA_FILE_REQUEST_TYPE);
     insert_command_prefixes(mms, 1, 0xffffffff);
     put_le32(&mms->outgoing_packet_data, 0);
@@ -312,9 +251,7 @@ static int send_media_file_request(MMSCo
     put_le_utf16(&mms->outgoing_packet_data, mms->path+1); // +1 because we skip the leading /
     put_le32(&mms->outgoing_packet_data, 0); /* More zeroes */
 
-    err = send_command_packet(mms);
-    ff_mms_set_state(mms, AWAITING_PASSWORD_QUERY_OR_MEDIA_FILE);
-    return err;
+    return send_command_packet(mms);
 }
 
 static int read_bytes(MMSContext *mms, uint8_t *buffer, int length_to_read)
@@ -334,15 +271,49 @@ static int read_bytes(MMSContext *mms, u
     return len;
 }
 
+static void handle_packet_stream_changing_type(MMSContext *mms)
+{
+    ByteIOContext pkt;
+    dprintf(NULL, "Stream changing!\n");
+
+    // read these from the incoming buffer.. (40 is the packet header size, without the prefixes)
+    init_put_byte(&pkt, mms->incoming_buffer+40, mms->incoming_buffer_length-40, 0, NULL, NULL, NULL, NULL);
+    get_le32(&pkt); // prefix 1
+    mms->header_packet_id= (get_le32(&pkt) & 0xff); // prefix 2
+    dprintf(NULL, "Changed header prefix to 0x%x", mms->header_packet_id);
+}
+
+static int send_keepalive_packet(MMSContext *mms)
+{
+    // respond to a keepalive with a keepalive...
+    start_command_packet(mms, CS_PACKET_KEEPALIVE_TYPE);
+    insert_command_prefixes(mms, 1, 0x100FFFF);
+    return send_command_packet(mms);
+}
+
+/** Pad media packets smaller than max_packet_size and/or adjust read position
+  * after a seek. */
+static void pad_media_packet(MMSContext *mms)
+{
+    if(mms->media_packet_buffer_length<mms->asf_packet_len) {
+        int padding_size = mms->asf_packet_len - mms->media_packet_buffer_length;
+        memset(mms->media_packet_incoming_buffer+mms->media_packet_buffer_length, 0, padding_size);
+        mms->media_packet_buffer_length += padding_size;
+    }
+    if(mms->media_packet_seek_offset) {
+        mms->media_packet_buffer_length -= mms->media_packet_seek_offset;
+        mms->media_packet_read_ptr += mms->media_packet_seek_offset;
+        mms->media_packet_seek_offset = 0;
+    }
+}
+
 /** Read incoming MMST media, header or command packet. */
 static MMSSCPacketType get_tcp_server_response(MMSContext *mms)
 {
-    // read the 8 byte header...
     int read_result;
     MMSSCPacketType packet_type= -1;
     int done;
 
-    // use url_fdopen & url_fclose...
     do {
         done= 1; // assume we're going to get a valid packet.
         if((read_result= read_bytes(mms, mms->incoming_buffer, 8))==8) {
@@ -399,7 +370,6 @@ static MMSSCPacketType get_tcp_server_re
                     if(packet_id_type == mms->header_packet_id) {
                         // asf header
                         packet_type = SC_PACKET_ASF_HEADER_TYPE;
-
                         // Store the asf header
                         if(!mms->header_parsed) {
                             mms->asf_header = av_realloc(mms->asf_header, mms->asf_header_size + mms->media_packet_buffer_length);
@@ -427,6 +397,16 @@ static MMSSCPacketType get_tcp_server_re
         }
     } while(!done);
 
+    if (packet_type == SC_PACKET_KEEPALIVE_TYPE) {
+        send_keepalive_packet(mms);
+    }
+    if (packet_type == SC_PACKET_STREAM_CHANGING_TYPE) {
+        handle_packet_stream_changing_type(mms);
+        //TODO: Handle new header when change the stream type.
+    }
+    if (packet_type == SC_PACKET_ASF_MEDIA_TYPE) {
+        pad_media_packet(mms);
+    }
     return packet_type;
 }
 
@@ -449,7 +429,6 @@ static void handle_packet_media_file_det
     if(flags==0xffffffff) {
         // this is a permission denied event.
         dprintf(NULL, "Permission denied!\n");
-        ff_mms_set_state(mms, STATE_ERROR);
     } else {
         get_le32(&pkt);
         get_le32(&pkt);
@@ -485,7 +464,6 @@ static void handle_packet_media_file_det
 
 static int send_media_header_request(MMSContext *mms)
 {
-    int err= 0;
     start_command_packet(mms, CS_PACKET_MEDIA_HEADER_REQUEST_TYPE);
     insert_command_prefixes(mms, 1, 0);
     put_le32(&mms->outgoing_packet_data, 0);
@@ -501,265 +479,12 @@ static int send_media_header_request(MMS
     put_le32(&mms->outgoing_packet_data, 2);
     put_le32(&mms->outgoing_packet_data, 0);
 
-    err = send_command_packet(mms);
-    ff_mms_set_state(mms, AWAITING_PACKET_HEADER_REQUEST_ACCEPTED_TYPE);
-    return err;
-}
-
-static void handle_packet_stream_changing_type(MMSContext *mms)
-{
-    ByteIOContext pkt;
-    dprintf(NULL, "Stream changing!\n");
-
-    // read these from the incoming buffer.. (40 is the packet header size, without the prefixes)
-    init_put_byte(&pkt, mms->incoming_buffer+40, mms->incoming_buffer_length-40, 0, NULL, NULL, NULL, NULL);
-    get_le32(&pkt); // prefix 1
-    mms->header_packet_id= (get_le32(&pkt) & 0xff); // prefix 2
-
-    dprintf(NULL, "Changed header prefix to 0x%x", mms->header_packet_id);
-
-    ff_mms_set_state(mms, AWAITING_ASF_HEADER); // this is going to hork our avstreams.
-}
-
-static int send_keepalive_packet(MMSContext *mms)
-{
-    // respond to a keepalive with a keepalive...
-    start_command_packet(mms, CS_PACKET_KEEPALIVE_TYPE);
-    insert_command_prefixes(mms, 1, 0x100FFFF);
     return send_command_packet(mms);
 }
 
-/** Handling pf TCP-specific packets.
- * @param packet_type incoming packet type to process.
- * @return  0 if the packet_type wasn't handled by this function.
- *          1 if it expected and handled.
- *         -1 if it the packet was unexpected in the current state.
- */
-static int tcp_packet_state_machine(MMSContext *mms, MMSSCPacketType packet_type)
-{
-    switch(packet_type) {
-    case SC_PACKET_CLIENT_ACCEPTED:
-        if(mms->state==AWAITING_SC_PACKET_CLIENT_ACCEPTED) {
-            dprintf(NULL, "Transitioning from AWAITING_SC_PACKET_CLIENT_ACCEPTED to AWAITING_SC_PACKET_TIMING_TEST_REPLY_TYPE\n");
-            // send the timing request packet...
-            start_command_packet(mms, CS_PACKET_TIMING_DATA_REQUEST_TYPE);
-            insert_command_prefixes(mms, 0xf0f0f0f1, 0x0004000b);
-            send_command_packet(mms);
-
-            ff_mms_set_state(mms, AWAITING_SC_PACKET_TIMING_TEST_REPLY_TYPE);
-        } else
-            return -1;
-        break;
-
-    case SC_PACKET_TIMING_TEST_REPLY_TYPE: // we may, or may not have timing tests.
-        if(mms->state==AWAITING_SC_PACKET_TIMING_TEST_REPLY_TYPE || mms->state==AWAITING_SC_PACKET_CLIENT_ACCEPTED) {
-            send_protocol_select(mms);
-        } else
-            return -1;
-        break;
-
-    case SC_PACKET_PROTOCOL_ACCEPTED_TYPE:
-        if(mms->state==AWAITING_CS_PACKET_PROTOCOL_ACCEPTANCE) {
-            send_media_file_request(mms);
-        } else
-            return -1;
-        break;
-
-    case SC_PACKET_PROTOCOL_FAILED_TYPE:
-        if(mms->state==AWAITING_CS_PACKET_PROTOCOL_ACCEPTANCE) {
-            // abort;
-            dprintf(NULL, "Protocol failed\n");
-            ff_mms_set_state(mms, STATE_ERROR);
-        } else
-            return -1;
-        break;
-
-    case SC_PACKET_PASSWORD_REQUIRED_TYPE:
-        if(mms->state==AWAITING_PASSWORD_QUERY_OR_MEDIA_FILE) {
-            // we don't support this right now.
-            dprintf(NULL, "Password required\n");
-            ff_mms_set_state(mms, STATE_ERROR);
-        } else
-            return -1;
-        break;
-
-    case SC_PACKET_MEDIA_FILE_DETAILS_TYPE:
-        if(mms->state==AWAITING_PASSWORD_QUERY_OR_MEDIA_FILE) {
-            handle_packet_media_file_details(mms);
-            if(mms->state != STATE_ERROR)
-                send_media_header_request(mms);
-        } else
-            return -1;
-        break;
-
-    case SC_PACKET_HEADER_REQUEST_ACCEPTED_TYPE:
-        if(mms->state==AWAITING_PACKET_HEADER_REQUEST_ACCEPTED_TYPE) {
-            ff_mms_set_state(mms, AWAITING_ASF_HEADER);
-        } else
-            return -1;
-        break;
-
-    case SC_PACKET_STREAM_CHANGING_TYPE:
-        if(mms->state==STREAMING) {
-            handle_packet_stream_changing_type(mms);
-        } else
-            return -1;
-        break;
-
-    case SC_PACKET_STREAM_ID_ACCEPTED_TYPE:
-        if(mms->state==AWAITING_STREAM_ID_ACCEPTANCE) {
-            dprintf(NULL, "Stream ID's accepted!\n");
-            ff_mms_set_state(mms, STREAM_PAUSED); // only way to get out of this is to play...
-        } else
-            return -1;
-        break;
-
-    case SC_PACKET_MEDIA_PACKET_FOLLOWS_TYPE:
-        if(mms->state==AWAITING_STREAM_START_PACKET) {
-            // get the stream packets...
-            ff_mms_set_state(mms, STREAMING);
-        } else
-            return -1;
-        break;
-
-    case SC_PACKET_KEEPALIVE_TYPE:
-        if(mms->state==STREAMING || mms->state==STREAM_PAUSED) {
-           dprintf(NULL, "Got a Keepalive!\n");
-            send_keepalive_packet(mms);
-        } else
-            return -1;
-        break;
-
-    default:
-        return 0; // Not handled here
-    }
-
-    return 1; // Handled here
-}
-
-/** Pad media packets smaller than max_packet_size and/or adjust read position
- * after a seek. */
-static void pad_media_packet(MMSContext *mms)
-{
-    if(mms->media_packet_buffer_length<mms->asf_packet_len) {
-        int padding_size = mms->asf_packet_len - mms->media_packet_buffer_length;
-        memset(mms->media_packet_incoming_buffer+mms->media_packet_buffer_length, 0, padding_size);
-        mms->media_packet_buffer_length += padding_size;
-    }
-
-    if(mms->media_packet_seek_offset) {
-        mms->media_packet_buffer_length -= mms->media_packet_seek_offset;
-        mms->media_packet_read_ptr += mms->media_packet_seek_offset;
-        mms->media_packet_seek_offset = 0;
-    }
-}
-
-/** Single-step the packet-pumping state machine.
- * @return The type of the last packet from the server.
- */
-static MMSSCPacketType ff_mms_packet_state_machine(MMSContext *mms)
-{
-    MMSSCPacketType packet_type = get_tcp_server_response(mms);
-
-    /* First, try protocol-specific packet handling */
-    int ret = tcp_packet_state_machine(mms, packet_type);
-    if(ret != 0) {
-        if(ret == -1)
-            log_packet_in_wrong_state(mms, packet_type);
-        return packet_type;
-    }
-
-    /* Common packet handling */
-    switch(packet_type) {
-    case SC_PACKET_ASF_HEADER_TYPE:
-        if(mms->state==AWAITING_ASF_HEADER) {
-            dprintf(NULL, "Got a SC_PACKET_ASF_HEADER: %d\n", mms->media_packet_buffer_length);
-            if((mms->incoming_flags == 0X08) || (mms->incoming_flags == 0X0C))
-            {
-                dprintf(NULL, "Got the full header!\n");
-                ff_mms_set_state(mms, ASF_HEADER_DONE);
-            }
-        } else {
-            log_packet_in_wrong_state(mms, packet_type);
-        }
-        break;
-
-    case SC_PACKET_ASF_MEDIA_TYPE:
-        if(mms->state==STREAMING || mms->state==AWAITING_PAUSE_ACKNOWLEDGE || mms->state==AWAITING_HTTP_PAUSE_CONTROL_ACKNOWLEDGE) {
-            pad_media_packet(mms);
-        } else {
-            log_packet_in_wrong_state(mms, packet_type);
-        }
-        break;
-
-    case SC_PACKET_STREAM_STOPPED_TYPE:
-        if(mms->state==AWAITING_PAUSE_ACKNOWLEDGE) {
-            dprintf(NULL, "Server echoed stream pause\n");
-            ff_mms_set_state(mms, STREAM_PAUSED);
-        } else if(mms->state==STREAMING) {
-            /*
-            When echoing a start (from me):
-             receive command 0x1e, 48 bytes
-             start sequence 00000001
-             command id     b00bface
-             length               20
-             protocol       20534d4d
-             len8                  4
-             sequence #     00000006
-             len8  (II)            2
-             dir | comm     0004001e
-             prefix1        00000000
-             prefix2        ffff0100
-
-             When Ending on it's own:
-             receive command 0x1e, 48 bytes
-             start sequence 09000001
-             command id     b00bface
-             length               20
-             protocol       20534d4d
-             len8                  4
-             sequence #     00000006
-             len8  (II)            2
-             dir | comm     0004001e
-             prefix1        00000000
-             prefix2        00000004
-            */
-            dprintf(NULL, "** Server hit end of stream (may be sending new header information)\n");
-            // TODO: if this is a live stream, on the resumption of a pause, this happens, then it follows with a SC_PACKET_STREAM_CHANGING_TYPE
-            // otherwise it means this stream is done.
-            ff_mms_set_state(mms, STREAM_DONE);
-        } else {
-            log_packet_in_wrong_state(mms, packet_type);
-        }
-        break;
-
-    case SC_PACKET_TYPE_CANCEL:
-        dprintf(NULL, "Got a -1 packet type\n");
-        // user cancelled; let us out so it gets closed down...
-        ff_mms_set_state(mms, USER_CANCELLED);
-        break;
-
-    case SC_PACKET_TYPE_NO_DATA:
-       dprintf(NULL, "Got no data (closed?)\n");
-        ff_mms_set_state(mms, STREAM_DONE); //?
-        break;
-
-    case SC_PACKET_HTTP_CONTROL_ACKNOWLEDGE:
-        ff_mms_set_state(mms, AWAITING_PAUSE_ACKNOWLEDGE);
-        break;
-
-    default:
-        dprintf(NULL, "Unhandled packet type %d\n", packet_type);
-        break;
-    }
-
-    return packet_type;
-}
-
 /** Send the initial handshake. */
 static int send_startup_packet(MMSContext *mms)
 {
-    int err;
     char data_string[256];
 
     snprintf(data_string, sizeof(data_string), "NSPlayer/7.0.0.1956; {%s}; Host: %s",
@@ -771,18 +496,7 @@ static int send_startup_packet(MMSContex
     put_le_utf16(&mms->outgoing_packet_data, data_string);
     put_le16(&mms->outgoing_packet_data, 0); // double unicode ended string...
 
-    err = send_command_packet(mms);
-    ff_mms_set_state(mms, AWAITING_SC_PACKET_CLIENT_ACCEPTED);
-    return err;
-}
-
-static void print_guid(const ff_asf_guid *g)
-{
-    int i;
-    av_log(NULL, AV_LOG_DEBUG, "{");
-    for(i=0;i<16;i++)
-        av_log(NULL, AV_LOG_DEBUG, " 0x%02x,", (*g)[i]);
-    av_log(NULL, AV_LOG_DEBUG, "}\n");
+    return send_command_packet(mms);
 }
 
 static int asf_header_parser(MMSContext *mms)
@@ -810,44 +524,13 @@ static int asf_header_parser(MMSContext 
         p += chunksize;
     } while (end - p >= sizeof(ff_asf_guid) + 8);
 
-    return -1;
-}
-
-/** Read the whole mms header into a buffer of our own .*/
-static int read_mms_header(MMSContext *mms)
-{
-    if(mms->state != AWAITING_ASF_HEADER) {
-        dprintf(NULL, "cannot read header this state\n");
-        ff_mms_set_state(mms, STATE_ERROR);
-        return -1;
-    }
-
-    /* TODO: add timeout */
-    /* This will run until the header is stored */
-    while(mms->state != ASF_HEADER_DONE && mms->state != STATE_ERROR)
-        ff_mms_packet_state_machine(mms);
-
-    if(mms->state == STATE_ERROR)
-        return -1;
-
-    asf_header_parser(mms);
-    mms->header_parsed = 1;
-
     return 0;
 }
 
-/** Clear all buffers of partial and old packets after a seek or other discontinuity */
-static void clear_stream_buffers(MMSContext *mms)
-{
-    mms->media_packet_buffer_length = 0;
-    mms->media_packet_read_ptr = mms->media_packet_incoming_buffer;
-}
-
 /** Send MMST stream selection command based on the AVStream->discard values. */
 static int send_stream_selection_request(MMSContext *mms)
 {
     int ii;
-    int err;
 
     //  send the streams we want back...
     start_command_packet(mms, CS_PACKET_STREAM_ID_REQUEST_TYPE);
@@ -860,62 +543,7 @@ static int send_stream_selection_request
 
     put_le16(&mms->outgoing_packet_data, 0); /* Extra zeroes */
 
-    err = send_command_packet(mms);
-    ff_mms_set_state(mms, AWAITING_STREAM_ID_ACCEPTANCE);
-    return err;
-}
-
-/** Request a MMST stream from a timestamp or packet offset.
- * @param rate Play rate. (Only 1 supported as for now)
- * @param byte_offset Byte position to seek to. Set to -1 when seeking by timestamp.
- *  The position is from the start of the media stream, i.e. not counting header size.
- * @param timestamp Time point in ms. Set to 0 when seeking from packet offsets.
- */
-static int request_streaming_from(MMSContext *mms,
-        int rate, int64_t byte_offset, int64_t timestamp)
-{
-    int32_t packet = -1;
-    int result;
-
-    if(byte_offset > 0)
-        packet = byte_offset / mms->asf_packet_len;
-
-    /* Send a stream selection request if this is the first call to play */
-    if(mms->state == ASF_HEADER_DONE) {
-        result = send_stream_selection_request(mms);
-
-        if(result==0) {
-            while(mms->state != STREAM_PAUSED && mms->state != STATE_ERROR && mms->state != STREAM_DONE) {
-                ff_mms_packet_state_machine(mms);
-            }
-        }
-    }
-
-    if(mms->state==STREAM_PAUSED || mms->state == ASF_HEADER_DONE) {
-        timestamp= av_dbl2int((double)timestamp/1000.0); // is this needed?
-
-        start_command_packet(mms, CS_PACKET_START_FROM_PACKET_ID_TYPE);
-        insert_command_prefixes(mms, 1, mms->packet_id);
-        put_le64(&mms->outgoing_packet_data, timestamp); // seek timestamp
-        put_le32(&mms->outgoing_packet_data, 0xffffffff);  // unknown
-        put_le32(&mms->outgoing_packet_data, packet);    // packet offset
-        put_byte(&mms->outgoing_packet_data, 0xff); // max stream time limit
-        put_byte(&mms->outgoing_packet_data, 0xff); // max stream time limit
-        put_byte(&mms->outgoing_packet_data, 0xff); // max stream time limit
-        put_byte(&mms->outgoing_packet_data, 0x00); // stream time limit flag
-
-        mms->packet_id++; // new packet_id so we can separate new data from old data
-        put_le32(&mms->outgoing_packet_data, mms->packet_id);
-        send_command_packet(mms);
-
-        ff_mms_set_state(mms, AWAITING_STREAM_START_PACKET);
-        return 0;
-    } else {
-#if (MMS_DEBUG_LEVEL>0)
-        dprintf(NULL, "Tried a read_play when the state was not stream paused (%s)\n", state_names[mms->state]);
-#endif
-        return -1;
-    }
+    return send_command_packet(mms);
 }
 
 /** Read at most one media packet (or a whole header). */
@@ -925,85 +553,62 @@ static int read_mms_packet(MMSContext *m
     MMSSCPacketType packet_type;
     int size_to_copy;
 
-    if(mms->state != STREAM_DONE && mms->state != STREAM_PAUSED && mms->state != STATE_ERROR) {
-        do {
-            if(mms->asf_header_read_pos < mms->asf_header_size) {
-                /* Read from ASF header buffer */
-                size_to_copy= FFMIN(buf_size, mms->asf_header_size - mms->asf_header_read_pos);
-                memcpy(buf, mms->asf_header + mms->asf_header_read_pos, size_to_copy);
-                mms->asf_header_read_pos += size_to_copy;
+    do {
+        if(mms->asf_header_read_pos < mms->asf_header_size) {
+            /* Read from ASF header buffer */
+            size_to_copy= FFMIN(buf_size, mms->asf_header_size - mms->asf_header_read_pos);
+            memcpy(buf, mms->asf_header + mms->asf_header_read_pos, size_to_copy);
+            mms->asf_header_read_pos += size_to_copy;
+            result += size_to_copy;
+            dprintf(NULL, "Copied %d bytes from stored header. left: %d\n", size_to_copy, mms->asf_header_size - mms->asf_header_read_pos);
+        } else if(mms->media_packet_buffer_length) {
+            /* Read from media packet buffer */
+            size_to_copy = FFMIN(buf_size, mms->media_packet_buffer_length);
+            memcpy(buf, mms->media_packet_read_ptr, size_to_copy);
+            mms->media_packet_buffer_length -= size_to_copy;
+            mms->media_packet_read_ptr+= size_to_copy;
+            result += size_to_copy;
+        } else {
+            /* Read from network */
+            packet_type= get_tcp_server_response(mms);
+            switch (packet_type) {
+            case SC_PACKET_ASF_MEDIA_TYPE:
+               if(mms->media_packet_buffer_length>mms->asf_packet_len) {
+                    dprintf(NULL, "Incoming packet larger than the asf packet size stated (%d>%d)\n", mms->media_packet_buffer_length, mms->asf_packet_len);
+                    result= AVERROR_IO;
+                    break;
+                }
+
+                // copy the data to the packet buffer...
+                size_to_copy= FFMIN(buf_size, mms->media_packet_buffer_length);
+                memcpy(buf, mms->media_packet_read_ptr, size_to_copy);
+                mms->media_packet_buffer_length -= size_to_copy;
+                mms->media_packet_read_ptr += size_to_copy;
                 result += size_to_copy;
-                dprintf(NULL, "Copied %d bytes from stored header. left: %d\n", size_to_copy, mms->asf_header_size - mms->asf_header_read_pos);
-            } else if(mms->media_packet_buffer_length) {
-                /* Read from media packet buffer */
-                size_to_copy = FFMIN(buf_size, mms->media_packet_buffer_length);
+                break;
+            case SC_PACKET_ASF_HEADER_TYPE:
+                // copy the data to the packet buffer...
+                size_to_copy= FFMIN(buf_size, mms->media_packet_buffer_length);
                 memcpy(buf, mms->media_packet_read_ptr, size_to_copy);
                 mms->media_packet_buffer_length -= size_to_copy;
                 mms->media_packet_read_ptr+= size_to_copy;
-                result += size_to_copy;
-            } else {
-                /* Read from network */
-                packet_type= ff_mms_packet_state_machine(mms);
-                switch (packet_type) {
-                case SC_PACKET_ASF_MEDIA_TYPE:
-                   if(mms->media_packet_buffer_length>mms->asf_packet_len) {
-                        dprintf(NULL, "Incoming packet larger than the asf packet size stated (%d>%d)\n", mms->media_packet_buffer_length, mms->asf_packet_len);
-                        result= AVERROR_IO;
-                        break;
-                    }
-
-                    // copy the data to the packet buffer...
-                    size_to_copy= FFMIN(buf_size, mms->media_packet_buffer_length);
-                    memcpy(buf, mms->media_packet_read_ptr, size_to_copy);
-                    mms->media_packet_buffer_length -= size_to_copy;
-                    mms->media_packet_read_ptr += size_to_copy;
-                    result += size_to_copy;
-                    break;
-                case SC_PACKET_ASF_HEADER_TYPE:
-                    // copy the data to the packet buffer...
-                    size_to_copy= FFMIN(buf_size, mms->media_packet_buffer_length);
-                    memcpy(buf, mms->media_packet_read_ptr, size_to_copy);
-                    mms->media_packet_buffer_length -= size_to_copy;
-                    mms->media_packet_read_ptr+= size_to_copy;
-                    result+= size_to_copy;
-                    break;
-                default:
-                    if(mms->state==STREAM_PAUSED) {
-                        result= 0;
-                    } else if(mms->state==STREAM_DONE || mms->state==USER_CANCELLED) {
-                        result=-1;
-                    } else if(mms->state==AWAITING_ASF_HEADER) {
-                        // we have reset the header; spin though the loop..
-                        while(mms->state != STREAMING && mms->state != STATE_ERROR) {
-                            ff_mms_packet_state_machine(mms);
-                        }
-                    } else {
-                        dprintf(NULL, "Got a packet in odd state: %d Packet Type: 0x%x\n", mms->state, packet_type);
-                    }
-                    break;
-                }
+                result+= size_to_copy;
+                break;
+            default:
+                dprintf(NULL, "Got a unkown Packet Type: 0x%x\n", packet_type);
+                break;
             }
-        } while(result==0 && mms->state!=STREAM_PAUSED); // only return one packet...
-    } else {
-        if(mms->state==STREAM_PAUSED) {
-            result= 0;
-        } else {
-            result= -1;
         }
-    }
-
+    } while(!result); // only return one packet...
     return result;
 }
 
 static int send_close_packet(MMSContext *mms)
 {
-    int err;
     start_command_packet(mms, CS_PACKET_STREAM_CLOSE_TYPE);
     insert_command_prefixes(mms, 1, 1);
 
-    err = send_command_packet(mms);
-    ff_mms_set_state(mms, AWAITING_PAUSE_ACKNOWLEDGE);
-    return err;
+    return send_command_packet(mms);
 }
 
 /** Close the MMSH/MMST connection */
@@ -1012,12 +617,7 @@ static int mms_close(URLContext *h)
     MMSContext *mms = (MMSContext *)h->priv_data;
 
     if(mms->mms_hd) {
-        // send the close packet if we should...
-        if(mms->state != STATE_ERROR) {
-            send_close_packet(mms);
-        }
-
-        // need an url_fdclose()
+        send_close_packet(mms);
         close_connection(mms);
     }
 
@@ -1040,7 +640,7 @@ static int mms_open_cnx(URLContext *h)
               &mms->port, mms->path, sizeof(mms->path), mms->location);
 
     if(mms->port<0)
-        mms->port = DEFAULT_MMS_PORT;
+        mms->port = 1755; // defaut mms protocol port
 
     /* the outgoing packet buffer */
     init_put_byte(&mms->outgoing_packet_data, mms->outgoing_packet_buffer, sizeof(mms->outgoing_packet_buffer), 1, NULL, NULL, NULL, NULL);
@@ -1055,41 +655,58 @@ static int mms_open_cnx(URLContext *h)
     mms->packet_id = 3; // default, initial value. (3 will be incremented to 4 before first use)
     mms->header_packet_id = 2; // default, initial value.
 
-    /* okay, now setup stuff.  working from unclear specifications is great! */
-    //mms->protocol->send_startup_message(mms); //TOBEDONE
     send_startup_packet(mms);
+    if (get_tcp_server_response(mms) == SC_PACKET_CLIENT_ACCEPTED) {
+//        start_command_packet(mms, CS_PACKET_TIMING_DATA_REQUEST_TYPE);
+//        insert_command_prefixes(mms, 0xf0f0f0f1, 0x0004000b);
+//        send_command_packet(mms);
+            send_protocol_select(mms);
+    } else
+        goto fail;
 
-    // TODO: add timeout here... (mms_watchdog_reset() ?)
-    while(mms->state != AWAITING_ASF_HEADER &&
-            mms->state != STATE_ERROR &&
-            mms->state != STREAM_DONE) {
-        ff_mms_packet_state_machine(mms); // TOBEDONE
-    }
+//    if (get_tcp_server_response(mms) == SC_PACKET_TIMING_TEST_REPLY_TYPE) {
+//        send_protocol_select(mms);
+//    } else
+//        goto fail;
 
-    /* We store the header internally */
-    if(mms->state != STATE_ERROR)
-        read_mms_header(mms); // TOBEDONE use asf_read_header?
+    if (get_tcp_server_response(mms) == SC_PACKET_PROTOCOL_ACCEPTED_TYPE) {
+        send_media_file_request(mms);
+    } else
+        goto fail;
 
-    if(mms->state == STATE_ERROR) {
-        err = AVERROR(EIO);
+    if (get_tcp_server_response(mms) == SC_PACKET_MEDIA_FILE_DETAILS_TYPE) {
+        handle_packet_media_file_details(mms);
+        send_media_header_request(mms);
+    } else
         goto fail;
-    }
 
-    dprintf(NULL, "Leaving open (success)\n");
+    if (get_tcp_server_response(mms) == SC_PACKET_HEADER_REQUEST_ACCEPTED_TYPE) {
+        // recv asf header data
+        if (get_tcp_server_response(mms) == SC_PACKET_ASF_HEADER_TYPE) {
+            if((mms->incoming_flags == 0X08) || (mms->incoming_flags == 0X0C)) {
+                asf_header_parser(mms);
+                mms->header_parsed = 1;
+            }  else
+                goto fail;
+        } else
+            goto fail;
+    } else
+        goto fail;
 
+    if (!mms->asf_packet_len || !mms->stream_num)
+        goto fail;
+
+    dprintf(NULL, "Leaving open (success)\n");
     return 0;
 fail:
     mms_close(h);
-
     dprintf(NULL, "Leaving open (failure: %d)\n", err);
-
     return err;
 }
 
 static int mms_open(URLContext *h, const char *uri, int flags)
 {
     MMSContext *mms;
-    int ret;
 
     h->is_streamed = 1;
     mms = av_malloc(sizeof(MMSContext));
@@ -1099,29 +716,24 @@ static int mms_open(URLContext *h, const
     h->priv_data = mms;
     av_strlcpy(mms->location, uri, sizeof(mms->location));
 
-    ret = mms_open_cnx(h);
-    return ret;
+    return mms_open_cnx(h);
 }
 
-/** Like AVInputFormat::read_play().
- * @see AVInputFormat::read_play()
- */
-static int ff_mms_play(URLContext *h)
+static int send_media_packet_request(MMSContext *mms)
 {
-    MMSContext *mms = h->priv_data;
-    int64_t stream_offset = 0;
-
-    /* Early return if already playing. */
-    if(mms->state == STREAMING || mms->state == AWAITING_STREAM_START_PACKET)
-        return 0;
-
-    /* If resuming from pause */
-    if(mms->state==STREAM_PAUSED)
-        stream_offset = (mms->pause_resume_seq+1) * mms->asf_packet_len;
-
-    clear_stream_buffers(mms);
+    start_command_packet(mms, CS_PACKET_START_FROM_PACKET_ID_TYPE);
+    insert_command_prefixes(mms, 1, 0x0001FFFF);
+    put_le64(&mms->outgoing_packet_data, 0); // seek timestamp
+    put_le32(&mms->outgoing_packet_data, 0xffffffff);  // unknown
+    put_le32(&mms->outgoing_packet_data, 0xffffffff);    // packet offset
+    put_byte(&mms->outgoing_packet_data, 0xff); // max stream time limit
+    put_byte(&mms->outgoing_packet_data, 0xff); // max stream time limit
+    put_byte(&mms->outgoing_packet_data, 0xff); // max stream time limit
+    put_byte(&mms->outgoing_packet_data, 0x00); // stream time limit flag
 
-    return request_streaming_from(mms, 1, stream_offset, 0);
+    mms->packet_id++; // new packet_id so we can separate new data from old data
+    put_le32(&mms->outgoing_packet_data, mms->packet_id);
+    return send_command_packet(mms);
 }
 
 /** Read ASF data through the protocol. */
@@ -1136,26 +748,25 @@ static int mms_read(URLContext *h, uint8
 
     /* Automatically start playing if the app wants to read before it has called play()
      * (helps with non-streaming aware apps) */
-    if(mms->state == ASF_HEADER_DONE && mms->asf_header_read_pos >= mms->asf_header_size) {
-        dprintf(NULL, "mms_read() before play(). Playing automatically.\n");
-        result = ff_mms_play(h);// TOBEDONE
-        if(result < 0)
-            return result;
-    }
-
-    /* We won't get any packets from the server if paused. Nothing else to do than
-     * to return. FIXME: return AVERROR(EAGAIN)? */
-    if(mms->state == STREAM_PAUSED) {
-        dprintf(NULL, "mms_read in STREAM_PAUSED\n");
-        return 0;
-    } else if(mms->state==STREAMING || mms->state==AWAITING_STREAM_START_PACKET || mms->state == ASF_HEADER_DONE) {
-        result = read_mms_packet(mms, buf, size);//TOBEDONE use asf_read_packet?
+    if(mms->header_parsed) {
+        if (mms->asf_header_read_pos >= mms->asf_header_size) {
+            dprintf(NULL, "mms_read() before play(). Playing automatically.\n");
+            result = send_stream_selection_request(mms);
+            if(result < 0)
+                return result;
+            if (get_tcp_server_response(mms) != SC_PACKET_STREAM_ID_ACCEPTED_TYPE) {
+                dprintf(NULL, "Canot get stream id accepted packet from server.\n");
+                return 0;
+            }
 
-        /* Note which packet we last returned. FIXME: doesn't handle partially read packets */
-        mms->pause_resume_seq = mms->incoming_packet_seq;
-    } else {
-        dprintf(NULL, "mms_read: wrong state %d, returning AVERROR_IO!\n", mms->state);
-        result = AVERROR(EIO);
+            // send media packet request
+            send_media_packet_request(mms);
+            if (get_tcp_server_response(mms) != SC_PACKET_MEDIA_PACKET_FOLLOWS_TYPE) {
+                dprintf(NULL, "Canot get media follows packet from server.\n");
+                return 0;
+            }
+        }
+        result = read_mms_packet(mms, buf, size);
     }
 
     return result;


More information about the FFmpeg-soc mailing list