MPlayer でHTTP 302エラーを限界までハンドリングする
MPlayer という非常に便利なストリーミング再生ソフトがあります。Windows では WMP とかあるのでいいのですが、Linux 環境では この MPlayer や VideoLAN(VLC) などが選択肢となります。
MPlayer でストリーミングを再生しようとしたとき、再生先のリソースが HTTP 302 や 303 で移動している事はよくあります。それはいいんですが、「ストリーミング情報が記録されたメタファイルの中のURLにアクセスすると HTTP 302」というすごい運用をしている放送局があったりします*1。この場合、MPlayer で再生しようとすると無条件でエラーになってしまいます。
こんな感じです。
Connecting to server SERVER_NAME[SERVER_IP]: SERVER_PORT... Server returned 302:Found Failed to parse header. Failed, exiting.
それでは困るので、少なくとも移動先をハンドリングできるように、Location ヘッダを読み込んで標準出力に書き出すように改造してみます。
diff -c mplayer-checkout-2009-12-12/stream/asf_streaming.c mplayer-moved_ver/stream/asf_streaming.c *** mplayer-checkout-2009-12-12/stream/asf_streaming.c 2009-12-12 14:15:03.000000000 +0900 --- mplayer-moved_ver/stream/asf_streaming.c 2009-12-13 14:32:54.000000000 +0900 *************** *** 622,627 **** --- 622,628 ---- static int asf_http_parse_response(asf_http_streaming_ctrl_t *asf_http_ctrl, HTTP_header_t *http_hdr ) { char *content_type, *pragma; + char *next_url; // added by @pen2 char features[64] = "\0"; size_t len; if( http_response_parse(http_hdr)<0 ) { *************** *** 631,636 **** --- 632,643 ---- switch( http_hdr->status_code ) { case 200: break; + case 302: // Moved, added by @pen2 + next_url = http_get_field( http_hdr, "Location" ); + if (next_url != NULL) { + printf("Moved: Using this url instead %s\n",next_url); + } + return -1; case 401: // Authentication required return ASF_Authenticate_e; default:
これによって、
Connecting to server SERVER_NAME[SERVER_IP]: SERVER_PORT... Moved: Using this url instead http://{RESOURCE_URI} Failed to parse header. Failed, exiting.
と言う形で移転先が返ってくるので、これをハンドリングして再度読み込めば上手くいきます。
本当は MPlayer 内で再帰的に読み込みを行えればベストなんですが、リソースURLを読み込む部分は "stream/asf_streaming.c" であり、ストリーム再生部分のかなり深い部分で、ここで再度メタファイルを読み込み治すようにするには、この辺の部分のコードを全面的に書き直す必要があるので、断念しました。
*1:ちなみに、WindowsMedia形式のネットラジオなどの場合、メタファイルは wma などの形式になっていて、ここに本来のリソースを指定できます。なので、本来のリソースの位置が変更になったら、ここを書き換えればいいはずですが… なんででしょうね?