예제 #1
0
static int open_f(stream_t *stream, int mode, void *opts, int *file_format)
{
    int flags = 0;
    const char *filename;
    AVIOContext *ctx = NULL;
    int res = STREAM_ERROR;
    int64_t size;
    int dummy;

    init_avformat();
    if (mode == STREAM_READ)
        flags = AVIO_FLAG_READ;
    else if (mode == STREAM_WRITE)
        flags = AVIO_FLAG_WRITE;
    else {
        mp_msg(MSGT_OPEN, MSGL_ERR, "[ffmpeg] Unknown open mode %d\n", mode);
        res = STREAM_UNSUPPORTED;
        goto out;
    }

#ifdef AVIO_FLAG_DIRECT
    flags |= AVIO_FLAG_DIRECT;
#else
    mp_msg(MSGT_OPEN, MSGL_WARN, "[ffmpeg] No support for AVIO_FLAG_DIRECT, might cause performance and other issues.\n"
                                 "Please update to and rebuild against an FFmpeg version supporting it.\n");
#endif

    if (stream->url)
        filename = stream->url;
    else {
        mp_msg(MSGT_OPEN, MSGL_ERR, "[ffmpeg] No URL\n");
        goto out;
    }
    if (!strncmp(filename, prefix, strlen(prefix)))
        filename += strlen(prefix);
    dummy = !strncmp(filename, "rtsp:", 5);
    mp_msg(MSGT_OPEN, MSGL_V, "[ffmpeg] Opening %s\n", filename);

    if (!dummy && avio_open(&ctx, filename, flags) < 0)
        goto out;

    stream->priv = ctx;
    size = dummy ? 0 : avio_size(ctx);
    if (size >= 0)
        stream->end_pos = size;
    stream->type = STREAMTYPE_FILE;
    stream->seek = seek;
    if (dummy || !ctx->seekable) {
        stream->type = STREAMTYPE_STREAM;
        stream->seek = NULL;
    }
    if (!dummy) {
        stream->fill_buffer = fill_buffer;
        stream->write_buffer = write_buffer;
        stream->control = control;
        stream->close = close_f;
    }
    res = STREAM_OK;

out:
    return res;
}
예제 #2
0
static int lavf_check_file(demuxer_t *demuxer){
    AVProbeData avpd;
    lavf_priv_t *priv;
    int probe_data_size = 0;
    int read_size = INITIAL_PROBE_SIZE;
    int score;

    if(!demuxer->priv)
        demuxer->priv=calloc(sizeof(lavf_priv_t),1);
    priv= demuxer->priv;

    init_avformat();

    if (opt_format) {
        if (strcmp(opt_format, "help") == 0) {
           list_formats();
           return 0;
        }
        priv->avif= av_find_input_format(opt_format);
        if (!priv->avif) {
            mp_msg(MSGT_DEMUX,MSGL_FATAL,"Unknown lavf format %s\n", opt_format);
            return 0;
        }
        mp_msg(MSGT_DEMUX,MSGL_INFO,"Forced lavf %s demuxer\n", priv->avif->long_name);
        return DEMUXER_TYPE_LAVF;
    }

    avpd.buf = av_mallocz(FFMAX(BIO_BUFFER_SIZE, PROBE_BUF_SIZE) +
                          FF_INPUT_BUFFER_PADDING_SIZE);
    do {
        read_size = stream_read(demuxer->stream, avpd.buf + probe_data_size, read_size);
        if(read_size < 0) {
            av_free(avpd.buf);
            return 0;
        }
        probe_data_size += read_size;
        avpd.filename= demuxer->stream->url;
        if (!avpd.filename) {
            mp_msg(MSGT_DEMUX, MSGL_WARN, "Stream url is not set!\n");
            avpd.filename = "";
        }
        if (!strncmp(avpd.filename, "ffmpeg://", 9))
            avpd.filename += 9;
        avpd.buf_size= probe_data_size;

        score = 0;
        priv->avif= av_probe_input_format2(&avpd, probe_data_size > 0, &score);
        read_size = FFMIN(2*read_size, PROBE_BUF_SIZE - probe_data_size);
    } while ((demuxer->desc->type != DEMUXER_TYPE_LAVF_PREFERRED ||
              probe_data_size < SMALL_MAX_PROBE_SIZE) &&
             score <= AVPROBE_SCORE_MAX / 4 &&
             read_size > 0 && probe_data_size < PROBE_BUF_SIZE);
    av_free(avpd.buf);

    if(!priv->avif){
        mp_msg(MSGT_HEADER,MSGL_V,"LAVF_check: no clue about this gibberish!\n");
        return 0;
    }else
        mp_msg(MSGT_HEADER,MSGL_V,"LAVF_check: %s\n", priv->avif->long_name);

    return DEMUXER_TYPE_LAVF;
}
예제 #3
0
int muxer_init_muxer_lavf(muxer_t *muxer)
{
	muxer_priv_t *priv;
	AVOutputFormat *fmt = NULL;

	init_avformat();

	if (conf_format && strcmp(conf_format, "help") == 0) {
		list_formats();
		return 0;
	}

	mp_msg(MSGT_MUXER, MSGL_WARN, "** MUXER_LAVF *****************************************************************\n");
	mp_msg(MSGT_MUXER, MSGL_WARN,
"REMEMBER: MEncoder's libavformat muxing is presently broken and can generate\n"
"INCORRECT files in the presence of B-frames. Moreover, due to bugs MPlayer\n"
"will play these INCORRECT files as if nothing were wrong!\n"
"*******************************************************************************\n");

	priv = calloc(1, sizeof(muxer_priv_t));
	if(priv == NULL)
		return 0;

	priv->oc = avformat_alloc_context();
	if(!priv->oc)
	{
		mp_msg(MSGT_MUXER, MSGL_FATAL, "Could not get format context.\n");
		goto fail;
	}

	if(conf_format)
		fmt = av_guess_format(conf_format, NULL, NULL);
	if(! fmt)
		fmt = av_guess_format(NULL, out_filename, NULL);
	if(! fmt)
	{
		mp_msg(MSGT_MUXER, MSGL_FATAL, "Cannot get specified format.\n");
		goto fail;
	}
	priv->oc->oformat = fmt;


	priv->oc->packet_size= mux_packet_size;
        priv->oc->max_delay= (int)(mux_max_delay*AV_TIME_BASE);
        if (info_name)
            av_dict_set(&priv->oc->metadata, "title",     info_name,      0);
        if (info_artist)
            av_dict_set(&priv->oc->metadata, "author",    info_artist,    0);
        if (info_genre)
            av_dict_set(&priv->oc->metadata, "genre",     info_genre,     0);
        if (info_copyright)
            av_dict_set(&priv->oc->metadata, "copyright", info_copyright, 0);
        if (info_comment)
            av_dict_set(&priv->oc->metadata, "comment",   info_comment,   0);

        if(mux_avopt){
            if(parse_avopts(priv->oc, mux_avopt) < 0){
                mp_msg(MSGT_MUXER,MSGL_ERR, "Your options /%s/ look like gibberish to me pal.\n", mux_avopt);
                goto fail;
            }
        }

	priv->oc->pb = avio_alloc_context(priv->buffer, BIO_BUFFER_SIZE, 1, muxer, NULL, mp_write, mp_seek);
	if ((muxer->stream->flags & MP_STREAM_SEEK) != MP_STREAM_SEEK)
            priv->oc->pb->seekable = 0;

	muxer->priv = priv;
	muxer->cont_new_stream = &lavf_new_stream;
	muxer->cont_write_chunk = &write_chunk;
	muxer->cont_write_header = &write_header;
	muxer->cont_write_index = &write_trailer;
	muxer->fix_stream_parameters = &fix_parameters;
	mp_msg(MSGT_MUXER, MSGL_INFO, "OK, exit.\n");
	return 1;

fail:
	free(priv);
	return 0;
}
예제 #4
0
static int init(sh_audio_t *sh)
{
    int i, x, in_size, srate, bps, *dtshd_rate;
    unsigned char *start;
    double pts;
    static const struct {
        const char *name; enum AVCodecID id;
    } fmt_id_type[] = {
        { "aac" , AV_CODEC_ID_AAC    },
        { "ac3" , AV_CODEC_ID_AC3    },
        { "dca" , AV_CODEC_ID_DTS    },
        { "eac3", AV_CODEC_ID_EAC3   },
        { "mpa" , AV_CODEC_ID_MP3    },
        { "thd" , AV_CODEC_ID_TRUEHD },
        { NULL  , 0 }
    };
    AVFormatContext     *lavf_ctx  = NULL;
    AVStream            *stream    = NULL;
    const AVOption      *opt       = NULL;
    struct spdifContext *spdif_ctx = NULL;

    spdif_ctx = av_mallocz(sizeof(*spdif_ctx));
    if (!spdif_ctx)
        goto fail;
    spdif_ctx->lavf_ctx = avformat_alloc_context();
    if (!spdif_ctx->lavf_ctx)
        goto fail;

    sh->context = spdif_ctx;
    lavf_ctx    = spdif_ctx->lavf_ctx;

    init_avformat();
    lavf_ctx->oformat = av_guess_format(FILENAME_SPDIFENC, NULL, NULL);
    if (!lavf_ctx->oformat)
        goto fail;
    lavf_ctx->priv_data = av_mallocz(lavf_ctx->oformat->priv_data_size);
    if (!lavf_ctx->priv_data)
        goto fail;
    lavf_ctx->pb = avio_alloc_context(spdif_ctx->pb_buffer, OUTBUF_SIZE, 1, spdif_ctx,
                            read_packet, write_packet, seek);
    if (!lavf_ctx->pb)
        goto fail;
    stream = avformat_new_stream(lavf_ctx, 0);
    if (!stream)
        goto fail;
    lavf_ctx->duration   = AV_NOPTS_VALUE;
    lavf_ctx->start_time = AV_NOPTS_VALUE;
    for (i = 0; fmt_id_type[i].name; i++) {
        if (!strcmp(sh->codec->dll, fmt_id_type[i].name)) {
            lavf_ctx->streams[0]->codec->codec_id = fmt_id_type[i].id;
            break;
        }
    }
    lavf_ctx->internal->raw_packet_buffer_remaining_size = RAW_PACKET_BUFFER_SIZE;
    if (AVERROR_PATCHWELCOME == lavf_ctx->oformat->write_header(lavf_ctx)) {
        mp_msg(MSGT_DECAUDIO,MSGL_INFO,
               "This codec is not supported by spdifenc.\n");
        goto fail;
    }

    // get sample_rate & bitrate from parser
    x = ds_get_packet_pts(sh->ds, &start, &pts);
    in_size = x;
    if (x <= 0) {
        pts = MP_NOPTS_VALUE;
        x = 0;
    }
    ds_parse(sh->ds, &start, &x, pts, 0);
    srate = 48000;    //fake value
    bps   = 768000/8; //fake value
    if (x && sh->avctx) { // we have parser and large enough buffer
        if (sh->avctx->sample_rate < 44100) {
            mp_msg(MSGT_DECAUDIO,MSGL_INFO,
                   "This stream sample_rate[%d Hz] may be broken. "
                   "Force reset 48000Hz.\n",
                   sh->avctx->sample_rate);
            srate = 48000; //fake value
        } else
            srate = sh->avctx->sample_rate;
        bps = sh->avctx->bit_rate/8;
    }
    sh->ds->buffer_pos -= in_size;

    switch (lavf_ctx->streams[0]->codec->codec_id) {
    case AV_CODEC_ID_AAC:
        spdif_ctx->iec61937_packet_size = 16384;
        sh->sample_format               = AF_FORMAT_IEC61937_LE;
        sh->samplerate                  = srate;
        sh->channels                    = 2;
        sh->i_bps                       = bps;
        break;
    case AV_CODEC_ID_AC3:
        spdif_ctx->iec61937_packet_size = 6144;
        sh->sample_format               = AF_FORMAT_AC3_LE;
        sh->samplerate                  = srate;
        sh->channels                    = 2;
        sh->i_bps                       = bps;
        break;
    case AV_CODEC_ID_DTS: // FORCE USE DTS-HD
        opt = av_opt_find(&lavf_ctx->oformat->priv_class,
                          "dtshd_rate", NULL, 0, 0);
        if (!opt)
            goto fail;
        dtshd_rate                      = (int*)(((uint8_t*)lavf_ctx->priv_data) +
                                          opt->offset);
        *dtshd_rate                     = 192000*4;
        spdif_ctx->iec61937_packet_size = 32768;
        sh->sample_format               = AF_FORMAT_IEC61937_LE;
        sh->samplerate                  = 192000; // DTS core require 48000
        sh->channels                    = 2*4;
        sh->i_bps                       = bps;
        break;
    case AV_CODEC_ID_EAC3:
        spdif_ctx->iec61937_packet_size = 24576;
        sh->sample_format               = AF_FORMAT_IEC61937_LE;
        sh->samplerate                  = 192000;
        sh->channels                    = 2;
        sh->i_bps                       = bps;
        break;
    case AV_CODEC_ID_MP3:
        spdif_ctx->iec61937_packet_size = 4608;
        sh->sample_format               = AF_FORMAT_MPEG2;
        sh->samplerate                  = srate;
        sh->channels                    = 2;
        sh->i_bps                       = bps;
        break;
    case AV_CODEC_ID_TRUEHD:
        spdif_ctx->iec61937_packet_size = 61440;
        sh->sample_format               = AF_FORMAT_IEC61937_LE;
        sh->samplerate                  = 192000;
        sh->channels                    = 8;
        sh->i_bps                       = bps;
        break;
    default:
        break;
    }

    return 1;

fail:
    uninit(sh);
    return 0;
}
예제 #5
0
파일: media.c 프로젝트: AmesianX/obs-studio
static inline bool mp_media_thread(mp_media_t *m)
{
	os_set_thread_name("mp_media_thread");

	if (!init_avformat(m)) {
		return false;
	}
	if (!mp_media_reset(m)) {
		return false;
	}

	for (;;) {
		bool reset, kill, is_active;
		bool timeout = false;

		pthread_mutex_lock(&m->mutex);
		is_active = m->active;
		pthread_mutex_unlock(&m->mutex);

		if (!is_active) {
			if (os_sem_wait(m->sem) < 0)
				return false;
		} else {
			timeout = mp_media_sleepto(m);
		}

		pthread_mutex_lock(&m->mutex);

		reset = m->reset;
		kill = m->kill;
		m->reset = false;
		m->kill = false;

		pthread_mutex_unlock(&m->mutex);

		if (kill) {
			break;
		}
		if (reset) {
			mp_media_reset(m);
			continue;
		}

		/* frames are ready */
		if (is_active && !timeout) {
			if (m->has_video)
				mp_media_next_video(m, false);
			if (m->has_audio)
				mp_media_next_audio(m);

			if (!mp_media_prepare_frames(m))
				return false;
			if (mp_media_eof(m))
				continue;

			mp_media_calc_next_ns(m);
		}
	}

	return true;
}