Beispiel #1
0
static int bsf_list_init(AVBSFContext *bsf)
{
    BSFListContext *lst = bsf->priv_data;
    int ret, i;
    const AVCodecParameters *cod_par = bsf->par_in;
    AVRational tb = bsf->time_base_in;

    for (i = 0; i < lst->nb_bsfs; ++i) {
        ret = avcodec_parameters_copy(lst->bsfs[i]->par_in, cod_par);
        if (ret < 0)
            goto fail;

        lst->bsfs[i]->time_base_in = tb;

        ret = av_bsf_init(lst->bsfs[i]);
        if (ret < 0)
            goto fail;

        cod_par = lst->bsfs[i]->par_out;
        tb = lst->bsfs[i]->time_base_out;
    }

    bsf->time_base_out = tb;
    ret = avcodec_parameters_copy(bsf->par_out, cod_par);

fail:
    return ret;
}
Beispiel #2
0
static int ffat_decode(AVCodecContext *avctx, void *data,
                       int *got_frame_ptr, AVPacket *avpkt)
{
    ATDecodeContext *at = avctx->priv_data;
    AVFrame *frame = data;
    int pkt_size = avpkt->size;
    AVPacket filtered_packet = {0};
    OSStatus ret;
    AudioBufferList out_buffers;

    if (avctx->codec_id == AV_CODEC_ID_AAC && avpkt->size > 2 &&
        (AV_RB16(avpkt->data) & 0xfff0) == 0xfff0) {
        AVPacket filter_pkt = {0};
        if (!at->bsf) {
            const AVBitStreamFilter *bsf = av_bsf_get_by_name("aac_adtstoasc");
            if(!bsf)
                return AVERROR_BSF_NOT_FOUND;
            if ((ret = av_bsf_alloc(bsf, &at->bsf)))
                return ret;
            if (((ret = avcodec_parameters_from_context(at->bsf->par_in, avctx)) < 0) ||
                ((ret = av_bsf_init(at->bsf)) < 0)) {
                av_bsf_free(&at->bsf);
                return ret;
            }
        }

        if ((ret = av_packet_ref(&filter_pkt, avpkt)) < 0)
            return ret;

        if ((ret = av_bsf_send_packet(at->bsf, &filter_pkt)) < 0) {
            av_packet_unref(&filter_pkt);
            return ret;
        }

        if ((ret = av_bsf_receive_packet(at->bsf, &filtered_packet)) < 0)
            return ret;

        at->extradata = at->bsf->par_out->extradata;
        at->extradata_size = at->bsf->par_out->extradata_size;

        avpkt = &filtered_packet;
    }

    if (!at->converter) {
        if ((ret = ffat_create_decoder(avctx, avpkt)) < 0) {
            av_packet_unref(&filtered_packet);
            return ret;
        }
    }

    out_buffers = (AudioBufferList){
        .mNumberBuffers = 1,
        .mBuffers = {
            {
                .mNumberChannels = avctx->channels,
                .mDataByteSize = av_get_bytes_per_sample(avctx->sample_fmt) * avctx->frame_size
                                 * avctx->channels,
            }
        }
    };
Beispiel #3
0
bool FFmpegEncoderOpen(struct FFmpegEncoder* encoder, const char* outfile) {
	AVCodec* acodec = avcodec_find_encoder_by_name(encoder->audioCodec);
	AVCodec* vcodec = avcodec_find_encoder_by_name(encoder->videoCodec);
	if ((encoder->audioCodec && !acodec) || !vcodec || !FFmpegEncoderVerifyContainer(encoder)) {
		return false;
	}

	encoder->currentAudioSample = 0;
	encoder->currentAudioFrame = 0;
	encoder->currentVideoFrame = 0;
	encoder->nextAudioPts = 0;

	AVOutputFormat* oformat = av_guess_format(encoder->containerFormat, 0, 0);
#ifndef USE_LIBAV
	avformat_alloc_output_context2(&encoder->context, oformat, 0, outfile);
#else
	encoder->context = avformat_alloc_context();
	strncpy(encoder->context->filename, outfile, sizeof(encoder->context->filename) - 1);
	encoder->context->filename[sizeof(encoder->context->filename) - 1] = '\0';
	encoder->context->oformat = oformat;
#endif

	if (acodec) {
#ifdef FFMPEG_USE_CODECPAR
		encoder->audioStream = avformat_new_stream(encoder->context, NULL);
		encoder->audio = avcodec_alloc_context3(acodec);
#else
		encoder->audioStream = avformat_new_stream(encoder->context, acodec);
		encoder->audio = encoder->audioStream->codec;
#endif
		encoder->audio->bit_rate = encoder->audioBitrate;
		encoder->audio->channels = 2;
		encoder->audio->channel_layout = AV_CH_LAYOUT_STEREO;
		encoder->audio->sample_rate = encoder->sampleRate;
		encoder->audio->sample_fmt = encoder->sampleFormat;
		AVDictionary* opts = 0;
		av_dict_set(&opts, "strict", "-2", 0);
		if (encoder->context->oformat->flags & AVFMT_GLOBALHEADER) {
#ifdef AV_CODEC_FLAG_GLOBAL_HEADER
			encoder->audio->flags |= AV_CODEC_FLAG_GLOBAL_HEADER;
#else
			encoder->audio->flags |= CODEC_FLAG_GLOBAL_HEADER;
#endif
		}
		avcodec_open2(encoder->audio, acodec, &opts);
		av_dict_free(&opts);
#if LIBAVCODEC_VERSION_MAJOR >= 55
		encoder->audioFrame = av_frame_alloc();
#else
		encoder->audioFrame = avcodec_alloc_frame();
#endif
		if (!encoder->audio->frame_size) {
			encoder->audio->frame_size = 1;
		}
		encoder->audioFrame->nb_samples = encoder->audio->frame_size;
		encoder->audioFrame->format = encoder->audio->sample_fmt;
		encoder->audioFrame->pts = 0;
#ifdef USE_LIBAVRESAMPLE
		encoder->resampleContext = avresample_alloc_context();
		av_opt_set_int(encoder->resampleContext, "in_channel_layout", AV_CH_LAYOUT_STEREO, 0);
		av_opt_set_int(encoder->resampleContext, "out_channel_layout", AV_CH_LAYOUT_STEREO, 0);
		av_opt_set_int(encoder->resampleContext, "in_sample_rate", PREFERRED_SAMPLE_RATE, 0);
		av_opt_set_int(encoder->resampleContext, "out_sample_rate", encoder->sampleRate, 0);
		av_opt_set_int(encoder->resampleContext, "in_sample_fmt", AV_SAMPLE_FMT_S16, 0);
		av_opt_set_int(encoder->resampleContext, "out_sample_fmt", encoder->sampleFormat, 0);
		avresample_open(encoder->resampleContext);
#else
		encoder->resampleContext = swr_alloc_set_opts(NULL, AV_CH_LAYOUT_STEREO, encoder->sampleFormat, encoder->sampleRate,
		                                              AV_CH_LAYOUT_STEREO, AV_SAMPLE_FMT_S16, PREFERRED_SAMPLE_RATE, 0, NULL);
		swr_init(encoder->resampleContext);
#endif
		encoder->audioBufferSize = (encoder->audioFrame->nb_samples * PREFERRED_SAMPLE_RATE / encoder->sampleRate) * 4;
		encoder->audioBuffer = av_malloc(encoder->audioBufferSize);
		encoder->postaudioBufferSize = av_samples_get_buffer_size(0, encoder->audio->channels, encoder->audio->frame_size, encoder->audio->sample_fmt, 0);
		encoder->postaudioBuffer = av_malloc(encoder->postaudioBufferSize);
		avcodec_fill_audio_frame(encoder->audioFrame, encoder->audio->channels, encoder->audio->sample_fmt, (const uint8_t*) encoder->postaudioBuffer, encoder->postaudioBufferSize, 0);

		if (encoder->audio->codec->id == AV_CODEC_ID_AAC &&
		    (strcasecmp(encoder->containerFormat, "mp4") ||
		        strcasecmp(encoder->containerFormat, "m4v") ||
		        strcasecmp(encoder->containerFormat, "mov"))) {
			// MP4 container doesn't support the raw ADTS AAC format that the encoder spits out
#ifdef FFMPEG_USE_NEW_BSF
			av_bsf_alloc(av_bsf_get_by_name("aac_adtstoasc"), &encoder->absf);
			avcodec_parameters_from_context(encoder->absf->par_in, encoder->audio);
			av_bsf_init(encoder->absf);
#else
			encoder->absf = av_bitstream_filter_init("aac_adtstoasc");
#endif
		}
#ifdef FFMPEG_USE_CODECPAR
		avcodec_parameters_from_context(encoder->audioStream->codecpar, encoder->audio);
#endif
	}

#ifdef FFMPEG_USE_CODECPAR
	encoder->videoStream = avformat_new_stream(encoder->context, NULL);
	encoder->video = avcodec_alloc_context3(vcodec);
#else
	encoder->videoStream = avformat_new_stream(encoder->context, vcodec);
	encoder->video = encoder->videoStream->codec;
#endif
	encoder->video->bit_rate = encoder->videoBitrate;
	encoder->video->width = encoder->width;
	encoder->video->height = encoder->height;
	encoder->video->time_base = (AVRational) { VIDEO_TOTAL_LENGTH, GBA_ARM7TDMI_FREQUENCY };
	encoder->video->pix_fmt = encoder->pixFormat;
	encoder->video->gop_size = 60;
	encoder->video->max_b_frames = 3;
	if (encoder->context->oformat->flags & AVFMT_GLOBALHEADER) {
#ifdef AV_CODEC_FLAG_GLOBAL_HEADER
		encoder->video->flags |= AV_CODEC_FLAG_GLOBAL_HEADER;
#else
		encoder->video->flags |= CODEC_FLAG_GLOBAL_HEADER;
#endif
	}

	if (encoder->video->codec->id == AV_CODEC_ID_H264 &&
	    (strcasecmp(encoder->containerFormat, "mp4") ||
	        strcasecmp(encoder->containerFormat, "m4v") ||
	        strcasecmp(encoder->containerFormat, "mov"))) {
		// QuickTime and a few other things require YUV420
		encoder->video->pix_fmt = AV_PIX_FMT_YUV420P;
	}

	if (strcmp(vcodec->name, "libx264") == 0) {
		// Try to adaptively figure out when you can use a slower encoder
		if (encoder->width * encoder->height > 1000000) {
			av_opt_set(encoder->video->priv_data, "preset", "superfast", 0);
		} else if (encoder->width * encoder->height > 500000) {
			av_opt_set(encoder->video->priv_data, "preset", "veryfast", 0);
		} else {
			av_opt_set(encoder->video->priv_data, "preset", "faster", 0);
		}
		if (encoder->videoBitrate == 0) {
			av_opt_set(encoder->video->priv_data, "crf", "0", 0);
			encoder->video->pix_fmt = AV_PIX_FMT_YUV444P;
		}
	}

	avcodec_open2(encoder->video, vcodec, 0);
#if LIBAVCODEC_VERSION_MAJOR >= 55
	encoder->videoFrame = av_frame_alloc();
#else
	encoder->videoFrame = avcodec_alloc_frame();
#endif
	encoder->videoFrame->format = encoder->video->pix_fmt;
	encoder->videoFrame->width = encoder->video->width;
	encoder->videoFrame->height = encoder->video->height;
	encoder->videoFrame->pts = 0;
	_ffmpegSetVideoDimensions(&encoder->d, encoder->iwidth, encoder->iheight);
	av_image_alloc(encoder->videoFrame->data, encoder->videoFrame->linesize, encoder->video->width, encoder->video->height, encoder->video->pix_fmt, 32);
#ifdef FFMPEG_USE_CODECPAR
	avcodec_parameters_from_context(encoder->videoStream->codecpar, encoder->video);
#endif

	if (avio_open(&encoder->context->pb, outfile, AVIO_FLAG_WRITE) < 0) {
		return false;
	}
	return avformat_write_header(encoder->context, 0) >= 0;
}
Beispiel #4
0
static int open_slave(AVFormatContext *avf, char *slave, TeeSlave *tee_slave)
{
    int i, ret;
    AVDictionary *options = NULL;
    AVDictionaryEntry *entry;
    char *filename;
    char *format = NULL, *select = NULL, *on_fail = NULL;
    char *use_fifo = NULL, *fifo_options_str = NULL;
    AVFormatContext *avf2 = NULL;
    AVStream *st, *st2;
    int stream_count;
    int fullret;
    char *subselect = NULL, *next_subselect = NULL, *first_subselect = NULL, *tmp_select = NULL;

    if ((ret = ff_tee_parse_slave_options(avf, slave, &options, &filename)) < 0)
        return ret;

#define STEAL_OPTION(option, field) do {                                \
        if ((entry = av_dict_get(options, option, NULL, 0))) {          \
            field = entry->value;                                       \
            entry->value = NULL; /* prevent it from being freed */      \
            av_dict_set(&options, option, NULL, 0);                     \
        }                                                               \
    } while (0)

    STEAL_OPTION("f", format);
    STEAL_OPTION("select", select);
    STEAL_OPTION("onfail", on_fail);
    STEAL_OPTION("use_fifo", use_fifo);
    STEAL_OPTION("fifo_options", fifo_options_str);

    ret = parse_slave_failure_policy_option(on_fail, tee_slave);
    if (ret < 0) {
        av_log(avf, AV_LOG_ERROR,
               "Invalid onfail option value, valid options are 'abort' and 'ignore'\n");
        goto end;
    }

    ret = parse_slave_fifo_options(use_fifo, fifo_options_str, tee_slave);
    if (ret < 0) {
        av_log(avf, AV_LOG_ERROR, "Error parsing fifo options: %s\n", av_err2str(ret));
        goto end;
    }

    if (tee_slave->use_fifo) {

        if (options) {
            char *format_options_str = NULL;
            ret = av_dict_get_string(options, &format_options_str, '=', ':');
            if (ret < 0)
                goto end;

            ret = av_dict_set(&tee_slave->fifo_options, "format_options", format_options_str,
                              AV_DICT_DONT_STRDUP_VAL);
            if (ret < 0)
                goto end;
        }

        if (format) {
            ret = av_dict_set(&tee_slave->fifo_options, "fifo_format", format,
                              AV_DICT_DONT_STRDUP_VAL);
            format = NULL;
            if (ret < 0)
                goto end;
        }

        av_dict_free(&options);
        options = tee_slave->fifo_options;
    }
    ret = avformat_alloc_output_context2(&avf2, NULL,
                                         tee_slave->use_fifo ? "fifo" :format, filename);
    if (ret < 0)
        goto end;
    tee_slave->avf = avf2;
    av_dict_copy(&avf2->metadata, avf->metadata, 0);
    avf2->opaque   = avf->opaque;
    avf2->io_open  = avf->io_open;
    avf2->io_close = avf->io_close;
    avf2->interrupt_callback = avf->interrupt_callback;
    avf2->flags = avf->flags;

    tee_slave->stream_map = av_calloc(avf->nb_streams, sizeof(*tee_slave->stream_map));
    if (!tee_slave->stream_map) {
        ret = AVERROR(ENOMEM);
        goto end;
    }

    stream_count = 0;
    for (i = 0; i < avf->nb_streams; i++) {
        st = avf->streams[i];
        if (select) {
            tmp_select = av_strdup(select);  // av_strtok is destructive so we regenerate it in each loop
            if (!tmp_select) {
                ret = AVERROR(ENOMEM);
                goto end;
            }
            fullret = 0;
            first_subselect = tmp_select;
            next_subselect = NULL;
            while (subselect = av_strtok(first_subselect, slave_select_sep, &next_subselect)) {
                first_subselect = NULL;

                ret = avformat_match_stream_specifier(avf, avf->streams[i], subselect);
                if (ret < 0) {
                    av_log(avf, AV_LOG_ERROR,
                           "Invalid stream specifier '%s' for output '%s'\n",
                           subselect, slave);
                    goto end;
                }
                if (ret != 0) {
                    fullret = 1; // match
                    break;
                }
            }
            av_freep(&tmp_select);

            if (fullret == 0) { /* no match */
                tee_slave->stream_map[i] = -1;
                continue;
            }
        }
        tee_slave->stream_map[i] = stream_count++;

        if (!(st2 = avformat_new_stream(avf2, NULL))) {
            ret = AVERROR(ENOMEM);
            goto end;
        }

        ret = ff_stream_encode_params_copy(st2, st);
        if (ret < 0)
            goto end;
    }

    ret = ff_format_output_open(avf2, filename, NULL);
    if (ret < 0) {
        av_log(avf, AV_LOG_ERROR, "Slave '%s': error opening: %s\n", slave,
               av_err2str(ret));
        goto end;
    }

    if ((ret = avformat_write_header(avf2, &options)) < 0) {
        av_log(avf, AV_LOG_ERROR, "Slave '%s': error writing header: %s\n",
               slave, av_err2str(ret));
        goto end;
    }
    tee_slave->header_written = 1;

    tee_slave->bsfs = av_calloc(avf2->nb_streams, sizeof(*tee_slave->bsfs));
    if (!tee_slave->bsfs) {
        ret = AVERROR(ENOMEM);
        goto end;
    }

    entry = NULL;
    while (entry = av_dict_get(options, "bsfs", NULL, AV_DICT_IGNORE_SUFFIX)) {
        const char *spec = entry->key + strlen("bsfs");
        if (*spec) {
            if (strspn(spec, slave_bsfs_spec_sep) != 1) {
                av_log(avf, AV_LOG_ERROR,
                       "Specifier separator in '%s' is '%c', but only characters '%s' "
                       "are allowed\n", entry->key, *spec, slave_bsfs_spec_sep);
                ret = AVERROR(EINVAL);
                goto end;
            }
            spec++; /* consume separator */
        }

        for (i = 0; i < avf2->nb_streams; i++) {
            ret = avformat_match_stream_specifier(avf2, avf2->streams[i], spec);
            if (ret < 0) {
                av_log(avf, AV_LOG_ERROR,
                       "Invalid stream specifier '%s' in bsfs option '%s' for slave "
                       "output '%s'\n", spec, entry->key, filename);
                goto end;
            }

            if (ret > 0) {
                av_log(avf, AV_LOG_DEBUG, "spec:%s bsfs:%s matches stream %d of slave "
                       "output '%s'\n", spec, entry->value, i, filename);
                if (tee_slave->bsfs[i]) {
                    av_log(avf, AV_LOG_WARNING,
                           "Duplicate bsfs specification associated to stream %d of slave "
                           "output '%s', filters will be ignored\n", i, filename);
                    continue;
                }
                ret = av_bsf_list_parse_str(entry->value, &tee_slave->bsfs[i]);
                if (ret < 0) {
                    av_log(avf, AV_LOG_ERROR,
                           "Error parsing bitstream filter sequence '%s' associated to "
                           "stream %d of slave output '%s'\n", entry->value, i, filename);
                    goto end;
                }
            }
        }

        av_dict_set(&options, entry->key, NULL, 0);
    }

    for (i = 0; i < avf->nb_streams; i++){
        int target_stream = tee_slave->stream_map[i];
        if (target_stream < 0)
            continue;

        if (!tee_slave->bsfs[target_stream]) {
            /* Add pass-through bitstream filter */
            ret = av_bsf_get_null_filter(&tee_slave->bsfs[target_stream]);
            if (ret < 0) {
                av_log(avf, AV_LOG_ERROR,
                       "Failed to create pass-through bitstream filter: %s\n",
                       av_err2str(ret));
                goto end;
            }
        }

        tee_slave->bsfs[target_stream]->time_base_in = avf->streams[i]->time_base;
        ret = avcodec_parameters_copy(tee_slave->bsfs[target_stream]->par_in,
                                      avf->streams[i]->codecpar);
        if (ret < 0)
            goto end;

        ret = av_bsf_init(tee_slave->bsfs[target_stream]);
        if (ret < 0) {
            av_log(avf, AV_LOG_ERROR,
            "Failed to initialize bitstream filter(s): %s\n",
            av_err2str(ret));
            goto end;
        }
    }

    if (options) {
        entry = NULL;
        while ((entry = av_dict_get(options, "", entry, AV_DICT_IGNORE_SUFFIX)))
            av_log(avf2, AV_LOG_ERROR, "Unknown option '%s'\n", entry->key);
        ret = AVERROR_OPTION_NOT_FOUND;
        goto end;
    }

end:
    av_free(format);
    av_free(select);
    av_free(on_fail);
    av_dict_free(&options);
    av_freep(&tmp_select);
    return ret;
}
Beispiel #5
0
static int bsfs_init(AVCodecContext *avctx)
{
    AVCodecInternal *avci = avctx->internal;
    DecodeFilterContext *s = &avci->filter;
    const char *bsfs_str;
    int ret;

    if (s->nb_bsfs)
        return 0;

    bsfs_str = avctx->codec->bsfs ? avctx->codec->bsfs : "null";
    while (bsfs_str && *bsfs_str) {
        AVBSFContext **tmp;
        const AVBitStreamFilter *filter;
        char *bsf;

        bsf = av_get_token(&bsfs_str, ",");
        if (!bsf) {
            ret = AVERROR(ENOMEM);
            goto fail;
        }

        filter = av_bsf_get_by_name(bsf);
        if (!filter) {
            av_log(avctx, AV_LOG_ERROR, "A non-existing bitstream filter %s "
                   "requested by a decoder. This is a bug, please report it.\n",
                   bsf);
            ret = AVERROR_BUG;
            av_freep(&bsf);
            goto fail;
        }
        av_freep(&bsf);

        tmp = av_realloc_array(s->bsfs, s->nb_bsfs + 1, sizeof(*s->bsfs));
        if (!tmp) {
            ret = AVERROR(ENOMEM);
            goto fail;
        }
        s->bsfs = tmp;
        s->nb_bsfs++;

        ret = av_bsf_alloc(filter, &s->bsfs[s->nb_bsfs - 1]);
        if (ret < 0)
            goto fail;

        if (s->nb_bsfs == 1) {
            /* We do not currently have an API for passing the input timebase into decoders,
             * but no filters used here should actually need it.
             * So we make up some plausible-looking number (the MPEG 90kHz timebase) */
            s->bsfs[s->nb_bsfs - 1]->time_base_in = (AVRational){ 1, 90000 };
            ret = avcodec_parameters_from_context(s->bsfs[s->nb_bsfs - 1]->par_in,
                                                  avctx);
        } else {
            s->bsfs[s->nb_bsfs - 1]->time_base_in = s->bsfs[s->nb_bsfs - 2]->time_base_out;
            ret = avcodec_parameters_copy(s->bsfs[s->nb_bsfs - 1]->par_in,
                                          s->bsfs[s->nb_bsfs - 2]->par_out);
        }
        if (ret < 0)
            goto fail;

        ret = av_bsf_init(s->bsfs[s->nb_bsfs - 1]);
        if (ret < 0)
            goto fail;
    }

    return 0;
fail:
    ff_decode_bsfs_uninit(avctx);
    return ret;
}
Beispiel #6
0
STATUS DemuxerLibAV::selectVideoStream() {
	if (!_initialized) {
		log->printf("DemuxerLibAV::selectVideoStream(): demuxer not opened!\n");
		return S_FAIL;
	}

	for (U32 i = 0; i < _afc->nb_streams; i++) {
		AVStream *stream = _afc->streams[i];
		AVCodec *codec = avcodec_find_decoder(stream->codecpar->codec_id);
		if (codec == NULL) {
			log->printf("DemuxerLibAV::selectVideoStream(): avcodec_find_decoder failed!\n");
			return S_FAIL;
		}
		AVCodecContext *cc = avcodec_alloc_context3(codec);
		if (cc == NULL) {
			log->printf("DemuxerLibAV::selectVideoStream(): avcodec_alloc_context3 failed!\n");
			return S_FAIL;
		}
		if (avcodec_parameters_to_context(cc, stream->codecpar) < 0) {
			log->printf("DemuxerLibAV::selectVideoStream(): avcodec_parameters_to_context failed!\n");
			avcodec_free_context(&cc);
			return S_FAIL;
		}
		if (cc->codec_type == AVMEDIA_TYPE_VIDEO) {
			_videoStream = stream;
			if (cc->codec_id == AV_CODEC_ID_H264) {
				if (cc->extradata && cc->extradata_size >= 8 && cc->extradata[0] == 1) {
					const AVBitStreamFilter *bsf = av_bsf_get_by_name("h264_mp4toannexb");
					if (bsf == nullptr) {
						log->printf("DemuxerLibAV::selectVideoStream(): av_bsf_get_by_name failed!\n");
						avcodec_free_context(&cc);
						return S_FAIL;
					}
				    if (av_bsf_alloc(bsf, &_bsf) < 0) {
						log->printf("DemuxerLibAV::selectVideoStream(): av_bsf_alloc failed!\n");
						avcodec_free_context(&cc);
						return S_FAIL;
					}
				    if (avcodec_parameters_from_context(_bsf->par_in, cc) < 0)
				    {
						log->printf("DemuxerLibAV::selectVideoStream(): avcodec_parameters_from_context failed!\n");
						av_bsf_free(&_bsf);
						avcodec_free_context(&cc);
						return S_FAIL;
				    }
				    _bsf->time_base_in = cc->time_base;
					if (av_bsf_init(_bsf) < 0) {
						log->printf("DemuxerLibAV::selectVideoStream(): av_bsf_init failed!\n");
						av_bsf_free(&_bsf);
						avcodec_free_context(&cc);
						return S_FAIL;
					}
				}
			} else if (cc->codec_id == AV_CODEC_ID_MPEG4) {
				const AVBitStreamFilter *bsf = av_bsf_get_by_name("mpeg4_unpack_bframes");
				if (bsf == nullptr) {
					log->printf("DemuxerLibAV::selectVideoStream(): av_bsf_get_by_name failed!\n");
					avcodec_free_context(&cc);
					return S_FAIL;
				}
			    if (av_bsf_alloc(bsf, &_bsf) < 0) {
					log->printf("DemuxerLibAV::selectVideoStream(): av_bsf_alloc failed!\n");
					avcodec_free_context(&cc);
					return S_FAIL;
				}
			    if (avcodec_parameters_from_context(_bsf->par_in, cc) < 0)
			    {
					log->printf("DemuxerLibAV::selectVideoStream(): avcodec_parameters_from_context failed!\n");
					av_bsf_free(&_bsf);
					avcodec_free_context(&cc);
					return S_FAIL;
			    }
			    _bsf->time_base_in = cc->time_base;
				if (av_bsf_init(_bsf) < 0) {
					log->printf("DemuxerLibAV::selectVideoStream(): av_bsf_init failed!\n");
					av_bsf_free(&_bsf);
					avcodec_free_context(&cc);
					return S_FAIL;
				}
			} else if (cc->codec_id == AV_CODEC_ID_HEVC) {
				if (cc->extradata && cc->extradata_size >= 8 && cc->extradata[0] == 1) {
					const AVBitStreamFilter *bsf = av_bsf_get_by_name("hevc_mp4toannexb");
					if (bsf == nullptr) {
						log->printf("DemuxerLibAV::selectVideoStream(): av_bitstream_filter_init failed!\n");
						avcodec_free_context(&cc);
						return S_FAIL;
					}
				    if (av_bsf_alloc(bsf, &_bsf) < 0) {
						log->printf("DemuxerLibAV::selectVideoStream(): av_bsf_alloc failed!\n");
						avcodec_free_context(&cc);
						return S_FAIL;
					}
				    if (avcodec_parameters_from_context(_bsf->par_in, cc) < 0)
				    {
						log->printf("DemuxerLibAV::selectVideoStream(): avcodec_parameters_from_context failed!\n");
						av_bsf_free(&_bsf);
						avcodec_free_context(&cc);
						return S_FAIL;
				    }
				    _bsf->time_base_in = cc->time_base;
					if (av_bsf_init(_bsf) < 0) {
						log->printf("DemuxerLibAV::selectVideoStream(): av_bsf_init failed!\n");
						av_bsf_free(&_bsf);
						avcodec_free_context(&cc);
						return S_FAIL;
					}
				}
			}

			_videoStreamInfo.width = (U32)cc->width;
			_videoStreamInfo.height = (U32)cc->height;
			_videoStreamInfo.timeBaseScale = (U32)cc->time_base.num;
			_videoStreamInfo.timeBaseRate = (U32)cc->time_base.den;
			_videoStreamInfo.priv = cc;

			switch (cc->codec_id) {
			case AV_CODEC_ID_MPEG1VIDEO:
				_videoStreamInfo.codecId = CODEC_ID_MPEG1VIDEO;
				break;
			case AV_CODEC_ID_MPEG2VIDEO:
				_videoStreamInfo.codecId = CODEC_ID_MPEG2VIDEO;
				break;
			case AV_CODEC_ID_H261:
				_videoStreamInfo.codecId = CODEC_ID_H261;
				break;
			case AV_CODEC_ID_H263:
				_videoStreamInfo.codecId = CODEC_ID_H263;
				break;
			case AV_CODEC_ID_MPEG4:
				_videoStreamInfo.codecId = CODEC_ID_MPEG4;
				break;
			case AV_CODEC_ID_MSMPEG4V1:
				_videoStreamInfo.codecId = CODEC_ID_MSMPEG4V1;
				break;
			case AV_CODEC_ID_MSMPEG4V2:
				_videoStreamInfo.codecId = CODEC_ID_MSMPEG4V2;
				break;
			case AV_CODEC_ID_MSMPEG4V3:
				_videoStreamInfo.codecId = CODEC_ID_MSMPEG4V3;
				break;
			case AV_CODEC_ID_H263P:
				_videoStreamInfo.codecId = CODEC_ID_H263P;
				break;
			case AV_CODEC_ID_H263I:
				_videoStreamInfo.codecId = CODEC_ID_H263I;
				break;
			case AV_CODEC_ID_FLV1:
				_videoStreamInfo.codecId = CODEC_ID_FLV1;
				break;
			case AV_CODEC_ID_SVQ1:
				_videoStreamInfo.codecId = CODEC_ID_SVQ1;
				break;
			case AV_CODEC_ID_SVQ3:
				_videoStreamInfo.codecId = CODEC_ID_SVQ3;
				break;
			case AV_CODEC_ID_AIC:
				_videoStreamInfo.codecId = CODEC_ID_AIC;
				break;
			case AV_CODEC_ID_DVVIDEO:
				_videoStreamInfo.codecId = CODEC_ID_DVVIDEO;
				break;
			case AV_CODEC_ID_VP3:
				_videoStreamInfo.codecId = CODEC_ID_VP3;
				break;
			case AV_CODEC_ID_VP5:
				_videoStreamInfo.codecId = CODEC_ID_VP5;
				break;
			case AV_CODEC_ID_VP6:
				_videoStreamInfo.codecId = CODEC_ID_VP6;
				break;
			case AV_CODEC_ID_VP6A:
				_videoStreamInfo.codecId = CODEC_ID_VP6A;
				break;
			case AV_CODEC_ID_VP6F:
				_videoStreamInfo.codecId = CODEC_ID_VP6F;
				break;
			case AV_CODEC_ID_VP7:
				_videoStreamInfo.codecId = CODEC_ID_VP7;
				break;
			case AV_CODEC_ID_VP8:
				_videoStreamInfo.codecId = CODEC_ID_VP8;
				break;
			case AV_CODEC_ID_VP9:
				_videoStreamInfo.codecId = CODEC_ID_VP9;
				break;
			case AV_CODEC_ID_WEBP:
				_videoStreamInfo.codecId = CODEC_ID_WEBP;
				break;
			case AV_CODEC_ID_THEORA:
				_videoStreamInfo.codecId = CODEC_ID_THEORA;
				break;
			case AV_CODEC_ID_RV10:
				_videoStreamInfo.codecId = CODEC_ID_RV10;
				break;
			case AV_CODEC_ID_RV20:
				_videoStreamInfo.codecId = CODEC_ID_RV20;
				break;
			case AV_CODEC_ID_RV30:
				_videoStreamInfo.codecId = CODEC_ID_RV30;
				break;
			case AV_CODEC_ID_RV40:
				_videoStreamInfo.codecId = CODEC_ID_RV40;
				break;
			case AV_CODEC_ID_WMV1:
				_videoStreamInfo.codecId = CODEC_ID_WMV1;
				break;
			case AV_CODEC_ID_WMV2:
				_videoStreamInfo.codecId = CODEC_ID_WMV2;
				break;
			case AV_CODEC_ID_WMV3:
				_videoStreamInfo.codecId = CODEC_ID_WMV3;
				break;
			case AV_CODEC_ID_VC1:
				_videoStreamInfo.codecId = CODEC_ID_VC1;
				break;
			case AV_CODEC_ID_H264:
				_videoStreamInfo.codecId = CODEC_ID_H264;
				break;
			case AV_CODEC_ID_HEVC:
				_videoStreamInfo.codecId = CODEC_ID_HEVC;
				break;
			default:
				_videoStreamInfo.codecId = CODEC_ID_NONE;
				log->printf("DemuxerLibAV::selectVideoStream(): Unknown codec: 0x%08x!\n",
						cc->codec_id);
				avcodec_free_context(&cc);
				return S_FAIL;
			}

			switch (cc->pix_fmt) {
			case AV_PIX_FMT_RGB24:
				_videoStreamInfo.pixelfmt = FMT_RGB24;
				break;
			case AV_PIX_FMT_ARGB:
				_videoStreamInfo.pixelfmt = FMT_ARGB;
				break;
			case AV_PIX_FMT_YUV420P:
				_videoStreamInfo.pixelfmt = FMT_YUV420P;
				break;
			case AV_PIX_FMT_YUV422P:
				_videoStreamInfo.pixelfmt = FMT_YUV422P;
				break;
			case AV_PIX_FMT_YUV444P:
				_videoStreamInfo.pixelfmt = FMT_YUV444P;
				break;
			case AV_PIX_FMT_NV12:
				_videoStreamInfo.pixelfmt = FMT_NV12;
				break;
			default:
				_videoStreamInfo.pixelfmt = FMT_NONE;
				log->printf("DemuxerLibAV::selectVideoStream(): Unknown pixel format: 0x%08x!\n", cc->pix_fmt);
				avcodec_free_context(&cc);
				return S_FAIL;
			}
			return S_OK;
		}
	}

	return S_FAIL;
}
static av_cold int mediacodec_decode_init(AVCodecContext *avctx)
{
    int ret;
    FFAMediaFormat *format = NULL;
    MediaCodecH264DecContext *s = avctx->priv_data;

    format = ff_AMediaFormat_new();
    if (!format) {
        av_log(avctx, AV_LOG_ERROR, "Failed to create media format\n");
        ret = AVERROR_EXTERNAL;
        goto done;
    }

    ff_AMediaFormat_setString(format, "mime", CODEC_MIME);
    ff_AMediaFormat_setInt32(format, "width", avctx->width);
    ff_AMediaFormat_setInt32(format, "height", avctx->height);

    if (avctx->extradata[0] == 1) {
        uint8_t *extradata = NULL;
        int extradata_size = 0;

        int sps_offset, sps_size;
        int pps_offset, pps_size;

        if ((ret = h264_extradata_to_annexb_sps_pps(avctx, &extradata, &extradata_size,
                &sps_offset, &sps_size, &pps_offset, &pps_size)) < 0) {
            goto done;
        }

        ff_AMediaFormat_setBuffer(format, "csd-0", extradata + sps_offset, sps_size);
        ff_AMediaFormat_setBuffer(format, "csd-1", extradata + pps_offset, pps_size);

        av_freep(&extradata);
    } else {
        ff_AMediaFormat_setBuffer(format, "csd-0", avctx->extradata, avctx->extradata_size);
    }

    if ((ret = ff_mediacodec_dec_init(avctx, &s->ctx, CODEC_MIME, format)) < 0) {
        goto done;
    }

    av_log(avctx, AV_LOG_INFO, "MediaCodec started successfully, ret = %d\n", ret);

    s->fifo = av_fifo_alloc(sizeof(AVPacket));
    if (!s->fifo) {
        ret = AVERROR(ENOMEM);
        goto done;
    }

    const AVBitStreamFilter *bsf = av_bsf_get_by_name("h264_mp4toannexb");
    if(!bsf) {
        ret = AVERROR_BSF_NOT_FOUND;
        goto done;
    }

    if ((ret = av_bsf_alloc(bsf, &s->bsf))) {
        goto done;
    }

    if (((ret = avcodec_parameters_from_context(s->bsf->par_in, avctx)) < 0) ||
        ((ret = av_bsf_init(s->bsf)) < 0)) {
          goto done;
    }

    av_init_packet(&s->filtered_pkt);

done:
    if (format) {
        ff_AMediaFormat_delete(format);
    }

    if (ret < 0) {
        mediacodec_decode_close(avctx);
    }
    return ret;
}
Beispiel #8
0
int av_bitstream_filter_filter(AVBitStreamFilterContext *bsfc,
                               AVCodecContext *avctx, const char *args,
                               uint8_t **poutbuf, int *poutbuf_size,
                               const uint8_t *buf, int buf_size, int keyframe)
{
    BSFCompatContext *priv = bsfc->priv_data;
    AVPacket pkt = { 0 };
    int ret;

    if (!priv->ctx) {
        ret = av_bsf_alloc(bsfc->filter, &priv->ctx);
        if (ret < 0)
            return ret;

        ret = avcodec_parameters_from_context(priv->ctx->par_in, avctx);
        if (ret < 0)
            return ret;

        priv->ctx->time_base_in = avctx->time_base;

        if (bsfc->args && bsfc->filter->priv_class) {
            const AVOption *opt = av_opt_next(priv->ctx->priv_data, NULL);
            const char * shorthand[2] = {NULL};

            if (opt)
                shorthand[0] = opt->name;

            ret = av_opt_set_from_string(priv->ctx->priv_data, bsfc->args, shorthand, "=", ":");
        }

        ret = av_bsf_init(priv->ctx);
        if (ret < 0)
            return ret;
    }

    pkt.data = buf;
    pkt.size = buf_size;

    ret = av_bsf_send_packet(priv->ctx, &pkt);
    if (ret < 0)
        return ret;

    *poutbuf      = NULL;
    *poutbuf_size = 0;

    ret = av_bsf_receive_packet(priv->ctx, &pkt);
    if (ret == AVERROR(EAGAIN) || ret == AVERROR_EOF)
        return 0;
    else if (ret < 0)
        return ret;

    *poutbuf = av_malloc(pkt.size + AV_INPUT_BUFFER_PADDING_SIZE);
    if (!*poutbuf) {
        av_packet_unref(&pkt);
        return AVERROR(ENOMEM);
    }

    *poutbuf_size = pkt.size;
    memcpy(*poutbuf, pkt.data, pkt.size);

    av_packet_unref(&pkt);

    /* drain all the remaining packets we cannot return */
    while (ret >= 0) {
        ret = av_bsf_receive_packet(priv->ctx, &pkt);
        av_packet_unref(&pkt);
    }

    if (!priv->extradata_updated) {
        /* update extradata in avctx from the output codec parameters */
        if (priv->ctx->par_out->extradata_size && (!args || !strstr(args, "private_spspps_buf"))) {
            av_freep(&avctx->extradata);
            avctx->extradata_size = 0;
            avctx->extradata = av_mallocz(priv->ctx->par_out->extradata_size + AV_INPUT_BUFFER_PADDING_SIZE);
            if (!avctx->extradata)
                return AVERROR(ENOMEM);
            memcpy(avctx->extradata, priv->ctx->par_out->extradata, priv->ctx->par_out->extradata_size);
            avctx->extradata_size = priv->ctx->par_out->extradata_size;
        }

        priv->extradata_updated = 1;
    }

    return 1;
}