[FFmpeg-devel] [patch]add mmsh protocol and extract common code for mmst.c

Stefano Sabatini stefano.sabatini-lala
Thu Aug 19 18:16:49 CEST 2010


On date Thursday 2010-08-19 23:55:40 +0800, zhentan feng encoded:
[...]
> Index: libavformat/mmsh.c
> ===================================================================
> --- libavformat/mmsh.c	(revision 0)
> +++ libavformat/mmsh.c	(revision 0)
[...]
> +static int read_data_packet(MMSHContext *mmsh, const int len)
> +{
> +    MMSContext *mms   = &mmsh->mms;
> +    int res;
> +    if (len > sizeof(mms->in_buffer)) {
> +        av_log(NULL, AV_LOG_ERROR,
> +                "Data packet length %d exceeds the in_buffer size %d\n",
> +                len, sizeof(mms->in_buffer));

weird indent "foo" is usually vertically aligned to the first char
after (, like in

       av_log(NULL, AV_LOG_ERROR,
              "Data packet length %d exceeds the in_buffer size %d\n",
              len, sizeof(mms->in_buffer));

> +        return AVERROR(EIO);
> +    }
> +    res = url_read_complete(mms->mms_hd, mms->in_buffer, len);
> +    dprintf(NULL, "Data packet len = %d\n", len);
> +    if (res != len) {
> +        av_log(NULL, AV_LOG_ERROR, "Read data packet failed!\n");
> +        return AVERROR(EIO);
> +    }
> +    if (len > mms->asf_packet_len) {
> +        av_log(NULL, AV_LOG_ERROR,
> +                "Chunk length %d exceed packet length %d\n",
> +                len, mms->asf_packet_len);

ditto

> +        return AVERROR_INVALIDDATA;
> +    } else {
> +        memset(mms->in_buffer + len, 0, mms->asf_packet_len - len); // padding
> +    }
> +    mms->read_in_ptr      = mms->in_buffer;
> +    mms->remaining_in_len = mms->asf_packet_len;
> +    return 0;
> +}
> +
> +static int get_http_header_data(MMSHContext *mmsh)
> +{
> +    MMSContext *mms = &mmsh->mms;
> +    int res, len;
> +    ChunkType chunk_type;
> +
> +    for (;;) {
> +        len = 0;
> +        chunk_type = get_chunk_header(mmsh, &len);
> +        if (chunk_type < 0) {
> +            return chunk_type;
> +        } else if (chunk_type == CHUNK_TYPE_ASF_HEADER){
> +            // get asf header and stored it
> +            if (!mms->header_parsed) {
> +                if (mms->asf_header) {
> +                    if (len != mms->asf_header_size) {
> +                        mms->asf_header_size = len;
> +                        dprintf(NULL, "Header len changed from %d to %d\n",
> +                                mms->asf_header_size, len);
> +                        av_freep(&mms->asf_header);
> +                    }
> +                }
> +                mms->asf_header = av_mallocz(len);
> +                if (!mms->asf_header) {
> +                    return AVERROR(ENOMEM);
> +                }
> +                mms->asf_header_size = len;
> +            }

> +            if (len > mms->asf_header_size) {
> +                av_log(NULL, AV_LOG_ERROR,
> +                   "Asf header packet len = %d exceed the asf header buf size %d\n",
> +                   len, mms->asf_header_size);

weird indent

> +                return AVERROR(EIO);
> +            }
> +            res = url_read_complete(mms->mms_hd, mms->asf_header, len);
> +            if (res != len) {
> +                av_log(NULL, AV_LOG_ERROR,
> +                        "Recv asf header data len %d != expected len %d\n", res, len);

ditto

> +                return AVERROR(EIO);
> +            }
> +            mms->asf_header_size = len;
> +            if (!mms->header_parsed) {
> +                res = ff_mms_asf_header_parser(mms);
> +                mms->header_parsed = 1;
> +                return res;
> +            }
> +        } else if (chunk_type == CHUNK_TYPE_DATA) {
> +            // read data packet and do padding
> +            return read_data_packet(mmsh, len);
> +        } else {
> +            if (len) {

> +                if (len > sizeof(mms->in_buffer)) {
> +                    av_log(NULL, AV_LOG_ERROR,
> +                        "Other packet len = %d exceed the in_buffer size %d\n",
> +                        len, sizeof(mms->in_buffer));

ditto

> +                    return AVERROR(EIO);
> +                }
> +                res = url_read_complete(mms->mms_hd, mms->in_buffer, len);
> +                if (res != len) {
> +                    av_log(NULL, AV_LOG_ERROR, "Read other chunk type data failed!\n");
> +                    return AVERROR(EIO);
> +                } else {
> +                    dprintf(NULL, "Skip chunk type %d \n", chunk_type);
> +                    continue;
> +                }
> +            }
> +        }
> +    }
> +    return 0;
> +}
> +
> +static int mmsh_open(URLContext *h, const char *uri, int flags)
> +{
> +    int i, port, err;
> +    char httpname[256], path[256], host[128], location[1024];
> +    char *stream_selection;
> +    char headers[1024];
> +    MMSHContext *mmsh;
> +    MMSContext *mms;
> +
> +    mmsh = h->priv_data = av_mallocz(sizeof(MMSHContext));
> +    if (!h->priv_data)
> +        return AVERROR(ENOMEM);
> +    mmsh->request_seq = h->is_streamed = 1;
> +    mms = &mmsh->mms;
> +    av_strlcpy(location, uri, sizeof(location));
> +
> +    av_url_split(NULL, 0, NULL, 0,
> +        host, sizeof(host), &port, path, sizeof(path), location);
> +    if (port<0)
> +        port = 80; // default mmsh protocol port
> +    ff_url_join(httpname, sizeof(httpname), "http", NULL, host, port, path);
> +
> +    if (url_alloc(&mms->mms_hd, httpname, URL_RDONLY) < 0) {
> +        return AVERROR(EIO);
> +    }
> +

> +    snprintf(headers, sizeof(headers),
> +        "Accept: */*\r\n"
> +        USERAGENT
> +        "Host: %s:%d\r\n"
> +        "Pragma: no-cache,rate=1.000000,stream-time=0,"
> +        "stream-offset=0:0,request-context=%u,max-duration=0\r\n"
> +        CLIENTGUID
> +        "Connection: Close\r\n\r\n",
> +        host, port, mmsh->request_seq++);

ditto

> +    ff_http_set_headers(mms->mms_hd, headers);
> +
> +    err = url_connect(mms->mms_hd);
> +    if (err) {
> +          goto fail;
> +    }
> +    err = get_http_header_data(mmsh);
> +    if (err) {
> +        av_log(NULL, AV_LOG_ERROR, "Get http header data failed!\n");
> +        goto fail;
> +    }
> +
> +    // close the socket and then reopen it for sending the second play request.
> +    url_close(mms->mms_hd);
> +    memset(headers, 0, sizeof(headers));
> +    if (url_alloc(&mms->mms_hd, httpname, URL_RDONLY) < 0) {
> +        return AVERROR(EIO);
> +    }
> +    stream_selection = av_mallocz(mms->stream_num * 19 + 1);
> +    if (!stream_selection)
> +        return AVERROR(ENOMEM);
> +    for (i = 0; i < mms->stream_num; i++) {
> +        char tmp[20];
> +        err = snprintf(tmp, sizeof(tmp), "ffff:%d:0 ", mms->streams[i].id);
> +        if (err < 0)
> +            goto fail;
> +        av_strlcat(stream_selection, tmp, mms->stream_num * 19 + 1);
> +    }

> +    // send play request
> +    err = snprintf(headers, sizeof(headers),
> +        "Accept: */*\r\n"
> +        USERAGENT
> +        "Host: %s:%d\r\n"
> +        "Pragma: no-cache,rate=1.000000,request-context=%u\r\n"
> +        "Pragma: xPlayStrm=1\r\n"
> +        CLIENTGUID
> +        "Pragma: stream-switch-count=%d\r\n"
> +        "Pragma: stream-switch-entry=%s\r\n"
> +        "Connection: Close\r\n\r\n",
> +        host, port, mmsh->request_seq++, mms->stream_num, stream_selection);

ditto

[...]

> +URLProtocol mmsh_protocol = {
> +    .name      = "mmsh",
> +    .url_open  = mmsh_open,
> +    .url_read  = mmsh_read,

> +    .url_write = NULL, // write
> +    .url_seek  = NULL, // seek

redundant comments

> +    .url_close = mmsh_close,
> +};
> Index: doc/protocols.texi
> ===================================================================
> --- doc/protocols.texi	(revision 24834)
> +++ doc/protocols.texi	(working copy)
> @@ -73,6 +73,15 @@
>  
>  MMS (Microsoft Media Server) protocol over TCP.
>  
> + at section mmsh
> +
> +MMS (Microsoft Media Server) protocol over HTTP.
> +
> +The required syntax is:
> + at example
> +mmsh://@var{server}[:@var{port}][/@var{app}][/@var{playpath}] 
> + at end example
> +
>  @section md5

I assume this is the right syntax.

No other objections from me.

Regards.
-- 
FFmpeg = Fast Faithful Mournful Perennial Excellent Gymnast



More information about the ffmpeg-devel mailing list