1
0
mirror of https://github.com/mpv-player/mpv synced 2025-01-03 13:32:16 +00:00

stream_lavf/demux_lavf: export/use HTTP MIME type

This is a fix for web radio streams that send raw AAC [1]. libavformat's
AAC demuxer probe is picky enough to request hundreds of KBs data, which
makes for a slow startup. To speed up stream startup, try use the HTTP
MIME type to identify the format. The webstream in question sends an AAC
specific MIME type, for which demux_lavf will force the AAC demuxer,
without probing anything.

ffmpeg/ffplay do the same thing. Note that as of ffmpeg commit 76d851b,
av_probe_input_buffer() does the mapping from MIME type to demuxer. The
actual mapping is not publicly accessible, and can only be used by
calling that function. This will hopefully be rectified, and ideally
ffmpeg would provide a function like find_demuxer_from_mime_type().

[1] http://lr2mp0.latvijasradio.lv:8000
This commit is contained in:
wm4 2012-12-10 01:28:20 +01:00
parent 222a5cf7c0
commit 180944fe28
4 changed files with 34 additions and 15 deletions

View File

@ -83,8 +83,23 @@ typedef struct lavf_priv {
bool use_dts; bool use_dts;
bool seek_by_bytes; bool seek_by_bytes;
int bitrate; int bitrate;
char *mime_type;
} lavf_priv_t; } lavf_priv_t;
static const char *map_demuxer_mime_type[][2] = {
{"audio/aacp", "aac"},
{0}
};
static const char *find_demuxer_from_mime_type(char *mime_type)
{
for (int n = 0; map_demuxer_mime_type[n][0]; n++) {
if (strcasecmp(map_demuxer_mime_type[n][0], mime_type) == 0)
return map_demuxer_mime_type[n][1];
}
return NULL;
}
static int mp_read(void *opaque, uint8_t *buf, int size) static int mp_read(void *opaque, uint8_t *buf, int size)
{ {
struct demuxer *demuxer = opaque; struct demuxer *demuxer = opaque;
@ -207,6 +222,8 @@ static int lavf_check_file(demuxer_t *demuxer)
format = demuxer->stream->lavf_type; format = demuxer->stream->lavf_type;
if (!format) if (!format)
format = avdevice_format; format = avdevice_format;
if (!format && demuxer->stream->mime_type)
format = (char *)find_demuxer_from_mime_type(demuxer->stream->mime_type);
if (format) { if (format) {
if (strcmp(format, "help") == 0) { if (strcmp(format, "help") == 0) {
list_formats(); list_formats();

View File

@ -179,7 +179,7 @@ static stream_t *open_stream_plugin(const stream_info_t *sinfo,
streaming_ctrl_free(s->streaming_ctrl); streaming_ctrl_free(s->streaming_ctrl);
#endif #endif
free(s->url); free(s->url);
free(s); talloc_free(s);
return NULL; return NULL;
} }
@ -202,6 +202,9 @@ static stream_t *open_stream_plugin(const stream_info_t *sinfo,
mp_msg(MSGT_OPEN,MSGL_V, "STREAM: Author: %s\n", sinfo->author); mp_msg(MSGT_OPEN,MSGL_V, "STREAM: Author: %s\n", sinfo->author);
mp_msg(MSGT_OPEN,MSGL_V, "STREAM: Comment: %s\n", sinfo->comment); mp_msg(MSGT_OPEN,MSGL_V, "STREAM: Comment: %s\n", sinfo->comment);
if (s->mime_type)
mp_msg(MSGT_OPEN, MSGL_V, "Mime-type: '%s'\n", s->mime_type);
return s; return s;
} }
@ -510,8 +513,7 @@ stream_t* new_memory_stream(unsigned char* data,int len){
} }
stream_t* new_stream(int fd,int type){ stream_t* new_stream(int fd,int type){
stream_t *s=calloc(1, sizeof(stream_t)); stream_t *s=talloc_zero(NULL, stream_t);
if(s==NULL) return NULL;
#if HAVE_WINSOCK2_H #if HAVE_WINSOCK2_H
{ {
@ -523,11 +525,6 @@ stream_t* new_stream(int fd,int type){
s->fd=fd; s->fd=fd;
s->type=type; s->type=type;
s->buf_pos=s->buf_len=0;
s->start_pos=s->end_pos=0;
s->priv=NULL;
s->url=NULL;
s->cache_pid=0;
stream_reset(s); stream_reset(s);
return s; return s;
} }
@ -551,11 +548,8 @@ void free_stream(stream_t *s){
mp_msg(MSGT_STREAM,MSGL_V,"WINSOCK2 uninit\n"); mp_msg(MSGT_STREAM,MSGL_V,"WINSOCK2 uninit\n");
WSACleanup(); // there might be a better place for this (-> later) WSACleanup(); // there might be a better place for this (-> later)
#endif #endif
// Disabled atm, i don't like that. s->priv can be anything after all
// streams should destroy their priv on close
//free(s->priv);
free(s->url); free(s->url);
free(s); talloc_free(s);
} }
stream_t* new_ds_stream(demux_stream_t *ds) { stream_t* new_ds_stream(demux_stream_t *ds) {

View File

@ -175,6 +175,7 @@ typedef struct stream {
void* cache_data; void* cache_data;
void* priv; // used for DVD, TV, RTSP etc void* priv; // used for DVD, TV, RTSP etc
char* url; // strdup() of filename/url char* url; // strdup() of filename/url
char *mime_type; // when HTTP streaming is used
char *lavf_type; // name of expected demuxer type for lavf char *lavf_type; // name of expected demuxer type for lavf
struct MPOpts *opts; struct MPOpts *opts;
streaming_ctrl_t *streaming_ctrl; streaming_ctrl_t *streaming_ctrl;

View File

@ -16,10 +16,11 @@
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/ */
#include "config.h" #include <libavformat/avformat.h>
#include <libavformat/avio.h>
#include <libavutil/opt.h>
#include "libavformat/avformat.h" #include "config.h"
#include "libavformat/avio.h"
#include "core/mp_msg.h" #include "core/mp_msg.h"
#include "stream.h" #include "stream.h"
#include "core/m_option.h" #include "core/m_option.h"
@ -139,6 +140,12 @@ static int open_f(stream_t *stream, int mode, void *opts, int *file_format)
if (avio_open(&avio, filename, flags) < 0) if (avio_open(&avio, filename, flags) < 0)
goto out; goto out;
if (avio->av_class) {
uint8_t *mt = NULL;
if (av_opt_get(avio, "mime_type", AV_OPT_SEARCH_CHILDREN, &mt) >= 0)
stream->mime_type = talloc_strdup(stream, mt);
}
char *rtmp[] = {"rtmp:", "rtmpt:", "rtmpe:", "rtmpte:", "rtmps:"}; char *rtmp[] = {"rtmp:", "rtmpt:", "rtmpe:", "rtmpte:", "rtmps:"};
for (int i = 0; i < FF_ARRAY_ELEMS(rtmp); i++) for (int i = 0; i < FF_ARRAY_ELEMS(rtmp); i++)
if (!strncmp(filename, rtmp[i], strlen(rtmp[i]))) { if (!strncmp(filename, rtmp[i], strlen(rtmp[i]))) {