[FFmpeg-devel] [patch]add mmsh protocol and extract common code for mmst.c
Ronald S. Bultje
rsbultje
Thu Aug 12 01:14:54 CEST 2010
Hi,
On Mon, Aug 9, 2010 at 12:05 PM, zhentan feng <spyfeng at gmail.com> wrote:
> #9 adds mmsh.c
[..]
> +#define DEBUG
No. :-).
> +#define CHUNK_TYPE_DATA 0x4424
> +#define CHUNK_TYPE_ASF_HEADER 0x4824
> +#define CHUNK_TYPE_END 0x4524
> +#define CHUNK_TYPE_STREAM_CHANGE 0x4324
Do these mean anything? (If not, that's OK, just wondering...)
You could consider making CHUNK_TYPE_* an enum.
> +// mmsh request messages.
> +static const char* mmsh_first_request =
[..]
> +static const char* mmsh_seekable_request =
[..]
> +static const char* mmsh_live_request =
char[] would save 4-8 bytes for the actual pointer.
More importantly, each of these are used only once, so I'd prefer if
you'd just inline them where they are used.
> +typedef struct
> +{
No new line.
> + char location[1024];
Only used in mmsh_open() and mmsh_open_cnx(), there's no reason to
store this in the struct. You could probably merge these two functions
as per mmst.c.
> + int seekable;
What is this? It's never set.
+ int stream_num;
Seems a duplicate of MMSContext->stream_num.
> + int request_seq;
> + int chunk_seq;
Missing doxy.
> +static int get_chunk_header(MMSHContext *mmsh, int *len)
[..]
> + res = url_read(mms->mms_hd, chunk_header, CHUNK_HEADER_LENGTH);
> + if (res != CHUNK_HEADER_LENGTH) {
> + dprintf(NULL, "read data packet header failed!\n");
> + return AVERROR(EIO);
> + }
I think now would be a great time to introduce good error messages.
Please look at how I did it in mmst.c. The problem here is that a user
does ./ffplay mmsh://..., and it gives an "I/O error". There's no way
to debug what happened or do something useful with it. Please use
av_log() to make it a little easier to work with.
> + if (chunk_type == CHUNK_TYPE_END ||chunk_type == CHUNK_TYPE_STREAM_CHANGE) {
> + ext_header_len = 4;
> + } else if (chunk_type == CHUNK_TYPE_ASF_HEADER || chunk_type == CHUNK_TYPE_DATA) {
> + ext_header_len = 8;
> + }
> + if (ext_header_len) {
> + res = url_read(mms->mms_hd, ext_header, ext_header_len);
> + if (res != ext_header_len) {
> + dprintf(NULL, "read ext header failed!\n");
> + return AVERROR(EIO);
> + }
> + } else {
> + dprintf(NULL, "strange chunk type %d\n", chunk_type);
> + return -1;
> + }
The following would sound more logical to me:
int ext_header; // no = 0
switch (chunk_type) {
case CHUNK_TYPE_END:
case CHUNK_TYPE_STREAM_CHANGE:
ext_header_len = 4;
break;
case ..:
ext_header_len = 8;
break;
default:
av_log(!!!);
return AVERROR(..);
}
res = url_read(..);
if (res != .. ) {
av_log(..);
return AVERROR(EIO);
}
> + if (chunk_type == CHUNK_TYPE_END || chunk_type == CHUNK_TYPE_DATA)
> + mmsh->chunk_seq = AV_RL32(ext_header);
Here, the if() is more logical, so don't change this one. ;-).
> +static int read_data_packet(MMSHContext *mmsh, const int len)
> +{
[..]
> + res = url_read_complete(mms->mms_hd, mms->in_buffer, len);
Why do you use url_read() elsewhere and _complete() here? One of the
two is wrong, I think.
Are you checking in_buffer's length to prevent overflows?
> +static int get_http_header_data(MMSHContext *mmsh)
[..]
> + res = url_read_complete(mms->mms_hd, mms->asf_header, len);
Same as above, overflow check?
> + res = url_read_complete(mms->mms_hd, mms->in_buffer, len);
Same. It also seems like this is data skipping, could url_fskip() be
useful here?
> + port = 80; // defaut mmsh protocol port
default.
> + // send paly request
play.
> +static int handle_chunk_type(MMSHContext *mmsh)
> +{
> + MMSContext *mms = &mmsh->mms;
> + int res, len = 0;
> + int chunk_type;
> + chunk_type = get_chunk_header(mmsh, &len);
> +
> + if(chunk_type == CHUNK_TYPE_END) {
> + if (mmsh->chunk_seq == 0) {
> + dprintf(NULL, "The stream is end.\n");
> + return -1;
> + }
> + // reconnect
> + mmsh->request_seq = 1;
> + if ((res = mmsh_open_cnx(mmsh)) !=0) {
> + dprintf(NULL, "Reconnect failed!\n");
> + return res;
> + }
> + } else if (chunk_type == CHUNK_TYPE_STREAM_CHANGE) {
> + mms->header_parsed = 0;
> + if ((res = get_http_header_data(mmsh)) !=0) {
> + dprintf(NULL,"stream changed! get new header failed!\n");
> + return res;
> + }
> + } else if (chunk_type == CHUNK_TYPE_DATA) {
> + return read_data_packet(mmsh, len);
> + } else {
> + dprintf(NULL, "recv other type packet %d\n", chunk_type);
> + return -1;
> + }
switch().
> +static int mmsh_read(URLContext *h, uint8_t *buf, int size)
[..]
> + } else if (mms->remaining_in_len){
> + res = ff_mms_read_data(mms, buf, size);
> + } else {
> + // read data packet from network
> + res = handle_chunk_type(mmsh);
> + if (res == 0) {
> + res = ff_mms_read_data(mms, buf, size);
> + } else {
> + dprintf(NULL, "other situation!\n");
> + }
> + }
else {
if (!mms->remaining_in_len && (res = handle_chunk_type(..)))
return res;
res = ff_mms_read_data(..);
}
Looks good in general, great work so far, let's get this in before SoC end!
Ronald
More information about the ffmpeg-devel
mailing list