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; }
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, } } };
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; }
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; }
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; }
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; }
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; }