AVFrame* Utility::FilterApplier::applyToFrame(AVFrame &source) { auto frame=av_frame_alloc(); if(av_buffersrc_add_frame_flags(buffersourceContext_, &source, AV_BUFFERSRC_FLAG_KEEP_REF) < 0) { av_frame_unref(frame); av_frame_free(&frame); throw std::runtime_error("Could not feed the frame into the filtergraph."); } if(av_buffersink_get_frame(buffersinkContext_, frame)<0) { av_frame_unref(frame); av_frame_free(&frame); throw std::runtime_error("Could not pull the filtered frame from the filtergraph."); } return frame; }
AVFrame* VideoDecoder::getFrame(int w, int h) { int ret = -1; if (w > 0 && h > 0) { mFilters.setScale(w, h); } if (!mFilters.hasInited() && mFilters.init(this) < 0) { LOGE("Init filters failed"); goto failed; } if (av_buffersrc_add_frame_flags(mFilters.mBufSrcCtxPtr, mFramePtr, AV_BUFFERSRC_FLAG_KEEP_REF) < 0) { LOGE("Buffer src add frame failed"); goto failed; } ret = av_buffersink_get_frame(mFilters.mBufSinkCtxPtr, mFilterFramePtr); if (ret < 0) { LOGE("Get frame failed"); goto failed; } return mFilterFramePtr; failed: return nullptr; }
int CDVDVideoCodecFFmpeg::FilterProcess(AVFrame* frame) { int result; if (frame) { result = av_buffersrc_add_frame(m_pFilterIn, frame); if (result < 0) { CLog::Log(LOGERROR, "CDVDVideoCodecFFmpeg::FilterProcess - av_buffersrc_add_frame"); return VC_ERROR; } } result = av_buffersink_get_frame(m_pFilterOut, m_pFilterFrame); if(result == AVERROR(EAGAIN) || result == AVERROR_EOF) return VC_BUFFER; else if(result < 0) { CLog::Log(LOGERROR, "CDVDVideoCodecFFmpeg::FilterProcess - av_buffersink_get_frame"); return VC_ERROR; } av_frame_unref(m_pFrame); av_frame_move_ref(m_pFrame, m_pFilterFrame); return VC_PICTURE; }
int crop_filter_wrapper::handle(const std::string& input, std::string& output) { frame_in->data[0] = (uint8_t*)input.c_str(); frame_in->data[1] = (uint8_t*)input.c_str() + this->width_ * this->height_; frame_in->data[2] = (uint8_t*)input.c_str() + this->width_ * this->height_ * 5 / 4; if (av_buffersrc_add_frame(buffersrc_ctx, frame_in) < 0) return -1; /* pull filtered pictures from the filtergraph */ int ret = av_buffersink_get_frame(buffersink_ctx, frame_out); if (ret < 0) return -1; //output Y,U,V if (frame_out->format == AV_PIX_FMT_YUV420P){ output = std::string((char*)frame_out->data[0], frame_out->linesize[0] * frame_out->height); output += std::string((char*)frame_out->data[1], frame_out->linesize[1] * frame_out->height / 2); output += std::string((char*)frame_out->data[2], frame_out->linesize[2] * frame_out->height / 2); } av_frame_unref(frame_out); return 0; }
std::shared_ptr<AVFrame> poll() { if (fast_path()) { if (fast_path_.empty()) return nullptr; auto result = fast_path_.front(); fast_path_.pop(); return result; } auto filt_frame = ffmpeg::create_frame(); const auto ret = av_buffersink_get_frame( video_graph_out_, filt_frame.get()); if(ret == AVERROR_EOF || ret == AVERROR(EAGAIN)) return nullptr; FF_RET(ret, "poll"); return filt_frame; }
bool MovieDecoder::processFilterGraph(AVPicture *dst, const AVPicture *src, enum AVPixelFormat pixfmt, int width, int height) { if (!m_filterGraph || width != m_lastWidth || height != m_lastHeight || pixfmt != m_lastPixfmt) { if (!initFilterGraph(pixfmt, width, height)) { return false; } } memcpy(m_filterFrame->data, src->data, sizeof(src->data)); memcpy(m_filterFrame->linesize, src->linesize, sizeof(src->linesize)); m_filterFrame->width = width; m_filterFrame->height = height; m_filterFrame->format = pixfmt; int ret = av_buffersrc_add_frame(m_bufferSourceContext, m_filterFrame); if (ret < 0) { return false; } ret = av_buffersink_get_frame(m_bufferSinkContext, m_filterFrame); if (ret < 0) { return false; } av_picture_copy(dst, (const AVPicture *) m_filterFrame, pixfmt, width, height); av_frame_unref(m_filterFrame); return true; }
static void process(ID3ASFilterContext *context, AVFrame *frame, AVRational timebase) { codec_t *this = context->priv_data; int ret; do_init(this, frame, timebase); if (av_buffersrc_write_frame(this->buffersrc_ctx, frame) < 0) { ERROR("Error while feeding the filtergraph\n"); exit(-1); } while (1) { ret = av_buffersink_get_frame(this->buffersink_ctx, this->output_frame); if (ret == AVERROR(EAGAIN) || ret == AVERROR_EOF) break; if (ret < 0) { ERROR("Error from get_frame"); exit(-1); } send_to_graph(context, this->output_frame, this->output_timebase); av_frame_unref(this->output_frame); } }
void FilterGraph::process(const std::vector<IFrame*>& inputs, IFrame& output) { // Init the filter graph if(!_isInit) init(inputs, output); // Check whether we can bypass the input audio buffers const bool bypassBuffers = _inputAudioFrameBuffers.empty() || (areInputFrameSizesEqual(inputs) && areFrameBuffersEmpty()); size_t minInputFrameSamplesNb = 0; if(!bypassBuffers) { // Fill the frame buffer with inputs for(size_t index = 0; index < inputs.size(); ++index) { if(!inputs.at(index)->getDataSize()) { LOG_DEBUG("Empty frame from filter graph input " << index << ". Remaining audio frames in buffer: " << _inputAudioFrameBuffers.at(index).getBufferSize()); continue; } _inputAudioFrameBuffers.at(index).addFrame(inputs.at(index)); } // Get the minimum input frames size minInputFrameSamplesNb = getMinInputFrameSamplesNb(inputs); } // Setup input frames into the filter graph for(size_t index = 0; index < inputs.size(); ++index) { // Retrieve frame from buffer or directly from input IFrame* inputFrame = (bypassBuffers)? inputs.at(index) : _inputAudioFrameBuffers.at(index).getFrameSampleNb(minInputFrameSamplesNb); const int ret = av_buffersrc_add_frame_flags(_filters.at(index)->getAVFilterContext(), &inputFrame->getAVFrame(), AV_BUFFERSRC_FLAG_PUSH); if(ret < 0) { throw std::runtime_error("Error when adding a frame to the source buffer used to start to process filters: " + getDescriptionFromErrorCode(ret)); } } // Pull filtered data from the filter graph for(;;) { const int ret = av_buffersink_get_frame(_filters.at(_filters.size() - 1)->getAVFilterContext(), &output.getAVFrame()); if(ret == AVERROR_EOF || ret == AVERROR(EAGAIN)) break; if(ret < 0) { throw std::runtime_error("Error reading buffer from buffersink: " + getDescriptionFromErrorCode(ret)); } } }
void MovieDecoder::getScaledVideoFrame(int scaledSize, bool maintainAspectRatio, VideoFrame& videoFrame) { initializeFilterGraph(m_pFormatContext->streams[m_VideoStream]->time_base, scaledSize, maintainAspectRatio); auto del = [] (AVFrame* f) { av_frame_free(&f); }; std::unique_ptr<AVFrame, decltype(del)> res(av_frame_alloc(), del); checkRc(av_buffersrc_write_frame(m_pFilterSource, m_pFrame), "Failed to write frame to filter graph"); int attempts = 0; int rc = av_buffersink_get_frame(m_pFilterSink, res.get()); while (rc == AVERROR(EAGAIN) && attempts++ < 10) { decodeVideoFrame(); checkRc(av_buffersrc_write_frame(m_pFilterSource, m_pFrame), "Failed to write frame to filter graph"); rc = av_buffersink_get_frame(m_pFilterSink, res.get()); } checkRc(rc, "Failed to get buffer from filter"); videoFrame.width = res->width; videoFrame.height = res->height; videoFrame.lineSize = videoFrame.width * 4; if(videoFrame.frameData != nullptr) delete videoFrame.frameData; uint8_t * framedata = res->data[0]; videoFrame.frameData = new uint8_t[videoFrame.width * 4 * videoFrame.height]; for(int y = 0;y < videoFrame.height;y++) { memcpy(videoFrame.frameData + ((videoFrame.height - y - 1) * videoFrame.lineSize), framedata + (y * res->linesize[0]), videoFrame.lineSize); } if (m_pFilterGraph) { avfilter_graph_free(&m_pFilterGraph); } }
static int compat_read(AVFilterContext *ctx, AVFilterBufferRef **pbuf, int nb_samples) { AVFilterBufferRef *buf; AVFrame *frame; int ret; if (!pbuf) return ff_poll_frame(ctx->inputs[0]); frame = av_frame_alloc(); if (!frame) return AVERROR(ENOMEM); if (!nb_samples) ret = av_buffersink_get_frame(ctx, frame); else ret = av_buffersink_get_samples(ctx, frame, nb_samples); if (ret < 0) goto fail; if (ctx->inputs[0]->type == AVMEDIA_TYPE_VIDEO) { buf = avfilter_get_video_buffer_ref_from_arrays(frame->data, frame->linesize, AV_PERM_READ, frame->width, frame->height, frame->format); } else { buf = avfilter_get_audio_buffer_ref_from_arrays(frame->extended_data, frame->linesize[0], AV_PERM_READ, frame->nb_samples, frame->format, frame->channel_layout); } if (!buf) { ret = AVERROR(ENOMEM); goto fail; } avfilter_copy_frame_props(buf, frame); buf->buf->priv = frame; buf->buf->free = compat_free_buffer; *pbuf = buf; return 0; fail: av_frame_free(&frame); return ret; }
bool LibAVFilterPrivate::pull(Frame *f) { AVFrameHolderRef frame_ref(new AVFrameHolder()); int ret = av_buffersink_get_frame(out_filter_ctx, frame_ref->frame()); if (ret < 0) { qWarning("av_buffersink_get_frame error: %s", av_err2str(ret)); return false; } VideoFrame vf(frame_ref->frame()->width, frame_ref->frame()->height, VideoFormat(frame_ref->frame()->format)); vf.setBits(frame_ref->frame()->data); vf.setBytesPerLine(frame_ref->frame()->linesize); vf.setMetaData("avframe_hoder_ref", QVariant::fromValue(frame_ref)); *f = vf; return true; }
int CDVDVideoCodecFFmpeg::FilterProcess(AVFrame* frame) { int result; if (frame || (m_codecControlFlags & DVD_CODEC_CTRL_DRAIN)) { result = av_buffersrc_add_frame(m_pFilterIn, frame); if (result < 0) { CLog::Log(LOGERROR, "CDVDVideoCodecFFmpeg::FilterProcess - av_buffersrc_add_frame"); return VC_ERROR; } } result = av_buffersink_get_frame(m_pFilterOut, m_pFilterFrame); if (result == AVERROR(EAGAIN)) return VC_BUFFER; else if (result == AVERROR_EOF) { result = av_buffersink_get_frame(m_pFilterOut, m_pFilterFrame); m_filterEof = true; if (result < 0) return VC_BUFFER; } else if (result < 0) { CLog::Log(LOGERROR, "CDVDVideoCodecFFmpeg::FilterProcess - av_buffersink_get_frame"); return VC_ERROR; } av_frame_unref(m_pFrame); av_frame_move_ref(m_pFrame, m_pFilterFrame); return VC_PICTURE; }
static int filter_encode_write_frame(AVFrame *frame, unsigned int stream_index) { int ret; AVFrame *filt_frame; av_log(NULL, AV_LOG_INFO, "Pushing decoded frame to filters\n"); /* push the decoded frame into the filtergraph */ ret = av_buffersrc_add_frame_flags(filter_ctx[stream_index].buffersrc_ctx, frame, 0); if (ret < 0) { av_log(NULL, AV_LOG_ERROR, "Error while feeding the filtergraph\n"); return ret; } /* pull filtered frames from the filtergraph */ while (1) { filt_frame = av_frame_alloc(); if (!filt_frame) { ret = AVERROR(ENOMEM); break; } av_log(NULL, AV_LOG_INFO, "Pulling filtered frame from filters\n"); ret = av_buffersink_get_frame(filter_ctx[stream_index].buffersink_ctx, filt_frame); if (ret < 0) { /* if no more frames for output - returns AVERROR(EAGAIN) * if flushed and no more frames for output - returns AVERROR_EOF * rewrite retcode to 0 to show it as normal procedure completion */ if (ret == AVERROR(EAGAIN) || ret == AVERROR_EOF) ret = 0; av_frame_free(&filt_frame); break; } filt_frame->pict_type = AV_PICTURE_TYPE_NONE; ret = encode_write_frame(filt_frame, stream_index, NULL); if (ret < 0) break; } return ret; }
static int filter_out(struct af_instance *af) { struct priv *p = af->priv; if (!p->graph) goto error; AVFrame *frame = av_frame_alloc(); if (!frame) goto error; int err = av_buffersink_get_frame(p->out, frame); if (err == AVERROR(EAGAIN) || err == AVERROR_EOF) { // Not an error situation - no more output buffers in queue. // AVERROR_EOF means we shouldn't even give the filter more // input, but we don't handle that completely correctly. av_frame_free(&frame); p->eof |= err == AVERROR_EOF; return 0; } struct mp_audio *out = mp_audio_from_avframe(frame); if (!out) goto error; mp_audio_copy_config(out, af->data); if (frame->pts != AV_NOPTS_VALUE) { double in_time = p->samples_in / (double)af->fmt_in.rate; double out_time = frame->pts * av_q2d(p->timebase_out); // Need pts past the last output sample. out_time += out->samples / (double)out->rate; af->delay = in_time - out_time; } get_metadata_from_av_frame(af, frame); af_add_output_frame(af, out); av_frame_free(&frame); return 0; error: av_frame_free(&frame); return -1; }
int main(int argc, char **argv) { int ret; AVPacket packet0, packet; AVFrame *frame = av_frame_alloc(); AVFrame *filt_frame = av_frame_alloc(); int got_frame; if (!frame || !filt_frame) { perror("Could not allocate frame"); exit(1); } if (argc != 2) { fprintf(stderr, "Usage: %s file | %s\n", argv[0], player); exit(1); } avcodec_register_all(); av_register_all(); avfilter_register_all(); if ((ret = open_input_file(argv[1])) < 0) goto end; if ((ret = init_filters(filter_descr)) < 0) goto end; /* read all packets */ packet0.data = NULL; packet.data = NULL; while (1) { if (!packet0.data) { if ((ret = av_read_frame(fmt_ctx, &packet)) < 0) break; packet0 = packet; } if (packet.stream_index == audio_stream_index) { got_frame = 0; ret = avcodec_decode_audio4(dec_ctx, frame, &got_frame, &packet); if (ret < 0) { av_log(NULL, AV_LOG_ERROR, "Error decoding audio\n"); continue; } packet.size -= ret; packet.data += ret; if (got_frame) { /* push the audio data from decoded frame into the filtergraph */ if (av_buffersrc_add_frame_flags(buffersrc_ctx, frame, 0) < 0) { av_log(NULL, AV_LOG_ERROR, "Error while feeding the audio filtergraph\n"); break; } /* pull filtered audio from the filtergraph */ while (1) { ret = av_buffersink_get_frame(buffersink_ctx, filt_frame); if (ret == AVERROR(EAGAIN) || ret == AVERROR_EOF) break; if (ret < 0) goto end; print_frame(filt_frame); av_frame_unref(filt_frame); } } if (packet.size <= 0) av_free_packet(&packet0); } else { /* discard non-wanted packets */ av_free_packet(&packet0); } } end: avfilter_graph_free(&filter_graph); avcodec_close(dec_ctx); avformat_close_input(&fmt_ctx); av_frame_free(&frame); av_frame_free(&filt_frame); if (ret < 0 && ret != AVERROR_EOF) { fprintf(stderr, "Error occurred: %s\n", av_err2str(ret)); exit(1); } exit(0); }
int main(int argc, char **argv) { int ret; AVPacket packet; AVFrame *frame = av_frame_alloc(); AVFrame *filt_frame = av_frame_alloc(); if (!frame || !filt_frame) { perror("Could not allocate frame"); exit(1); } if (argc != 2) { fprintf(stderr, "Usage: %s file | %s\n", argv[0], player); exit(1); } if ((ret = open_input_file(argv[1])) < 0) goto end; if ((ret = init_filters(filter_descr)) < 0) goto end; /* read all packets */ while (1) { if ((ret = av_read_frame(fmt_ctx, &packet)) < 0) break; if (packet.stream_index == audio_stream_index) { ret = avcodec_send_packet(dec_ctx, &packet); if (ret < 0) { av_log(NULL, AV_LOG_ERROR, "Error while sending a packet to the decoder\n"); break; } while (ret >= 0) { ret = avcodec_receive_frame(dec_ctx, frame); if (ret == AVERROR(EAGAIN) || ret == AVERROR_EOF) { break; } else if (ret < 0) { av_log(NULL, AV_LOG_ERROR, "Error while receiving a frame from the decoder\n"); goto end; } if (ret >= 0) { /* push the audio data from decoded frame into the filtergraph */ if (av_buffersrc_add_frame_flags(buffersrc_ctx, frame, AV_BUFFERSRC_FLAG_KEEP_REF) < 0) { av_log(NULL, AV_LOG_ERROR, "Error while feeding the audio filtergraph\n"); break; } /* pull filtered audio from the filtergraph */ while (1) { ret = av_buffersink_get_frame(buffersink_ctx, filt_frame); if (ret == AVERROR(EAGAIN) || ret == AVERROR_EOF) break; if (ret < 0) goto end; print_frame(filt_frame); av_frame_unref(filt_frame); } av_frame_unref(frame); } } } av_packet_unref(&packet); } end: avfilter_graph_free(&filter_graph); avcodec_free_context(&dec_ctx); avformat_close_input(&fmt_ctx); av_frame_free(&frame); av_frame_free(&filt_frame); if (ret < 0 && ret != AVERROR_EOF) { fprintf(stderr, "Error occurred: %s\n", av_err2str(ret)); exit(1); } exit(0); }
int main(int argc, char *argv[]) { struct AVMD5 *md5; AVFilterGraph *graph; AVFilterContext *src, *sink; AVFrame *frame; uint8_t errstr[1024]; float duration; int err, nb_frames, i; if (argc < 2) { fprintf(stderr, "Usage: %s <duration>\n", argv[0]); return 1; } duration = atof(argv[1]); nb_frames = duration * INPUT_SAMPLERATE / FRAME_SIZE; if (nb_frames <= 0) { fprintf(stderr, "Invalid duration: %s\n", argv[1]); return 1; } avfilter_register_all(); /* Allocate the frame we will be using to store the data. */ frame = av_frame_alloc(); if (!frame) { fprintf(stderr, "Error allocating the frame\n"); return 1; } md5 = av_md5_alloc(); if (!md5) { fprintf(stderr, "Error allocating the MD5 context\n"); return 1; } /* Set up the filtergraph. */ err = init_filter_graph(&graph, &src, &sink); if (err < 0) { fprintf(stderr, "Unable to init filter graph:"); goto fail; } /* the main filtering loop */ for (i = 0; i < nb_frames; i++) { /* get an input frame to be filtered */ err = get_input(frame, i); if (err < 0) { fprintf(stderr, "Error generating input frame:"); goto fail; } /* Send the frame to the input of the filtergraph. */ err = av_buffersrc_add_frame(src, frame); if (err < 0) { av_frame_unref(frame); fprintf(stderr, "Error submitting the frame to the filtergraph:"); goto fail; } /* Get all the filtered output that is available. */ while ((err = av_buffersink_get_frame(sink, frame)) >= 0) { /* now do something with our filtered frame */ err = process_output(md5, frame); if (err < 0) { fprintf(stderr, "Error processing the filtered frame:"); goto fail; } av_frame_unref(frame); } if (err == AVERROR(EAGAIN)) { /* Need to feed more frames in. */ continue; } else if (err == AVERROR_EOF) { /* Nothing more to do, finish. */ break; } else if (err < 0) { /* An error occurred. */ fprintf(stderr, "Error filtering the data:"); goto fail; } } avfilter_graph_free(&graph); av_frame_free(&frame); av_freep(&md5); return 0; fail: av_strerror(err, errstr, sizeof(errstr)); fprintf(stderr, "%s\n", errstr); return 1; }
JNIEXPORT jint JNICALL Java_com_frank_ffmpeg_VideoPlayer_filter (JNIEnv * env, jclass clazz, jstring filePath, jobject surface, jstring filterDescr){ int ret; const char * file_name = (*env)->GetStringUTFChars(env, filePath, JNI_FALSE); const char *filter_descr = (*env)->GetStringUTFChars(env, filterDescr, JNI_FALSE); //打开输入文件 if(!is_playing){ LOGI("open_input..."); if((ret = open_input(env, file_name, surface)) < 0){ LOGE("Couldn't allocate video frame."); goto end; } //注册滤波器 avfilter_register_all(); filter_frame = av_frame_alloc(); if(filter_frame == NULL) { LOGE("Couldn't allocate filter frame."); ret = -1; goto end; } //初始化音频解码器 if ((ret = init_audio(env, clazz)) < 0){ LOGE("Couldn't init_audio."); goto end; } } //初始化滤波器 if ((ret = init_filters(filter_descr)) < 0){ LOGE("init_filter error, ret=%d\n", ret); goto end; } is_playing = 1; int frameFinished; AVPacket packet; while(av_read_frame(pFormatCtx, &packet)>=0 && !release) { //切换滤波器,退出当初播放 if(again){ goto again; } //判断是否为视频流 if(packet.stream_index == video_stream_index) { //对该帧进行解码 avcodec_decode_video2(pCodecCtx, pFrame, &frameFinished, &packet); if (frameFinished) { //把解码后视频帧添加到filter_graph if (av_buffersrc_add_frame_flags(buffersrc_ctx, pFrame, AV_BUFFERSRC_FLAG_KEEP_REF) < 0) { LOGE("Error while feeding the filter_graph\n"); break; } //把滤波后的视频帧从filter graph取出来 ret = av_buffersink_get_frame(buffersink_ctx, filter_frame); if (ret >= 0){ // lock native window ANativeWindow_lock(nativeWindow, &windowBuffer, 0); // 格式转换 sws_scale(sws_ctx, (uint8_t const * const *)filter_frame->data, filter_frame->linesize, 0, pCodecCtx->height, pFrameRGBA->data, pFrameRGBA->linesize); // 获取stride uint8_t * dst = windowBuffer.bits; int dstStride = windowBuffer.stride * 4; uint8_t * src = pFrameRGBA->data[0]; int srcStride = pFrameRGBA->linesize[0]; // 由于window的stride和帧的stride不同,因此需要逐行复制 int h; for (h = 0; h < pCodecCtx->height; h++) { memcpy(dst + h * dstStride, src + h * srcStride, (size_t) srcStride); } ANativeWindow_unlockAndPost(nativeWindow); } av_frame_unref(filter_frame); } //延迟等待 if (!playAudio){ usleep((unsigned long) (1000 * 40));//1000 * 40 } } else if(packet.stream_index == audio_stream_index){//音频帧 if (playAudio){ play_audio(env, &packet, pFrame); } } av_packet_unref(&packet); } end: is_playing = 0; //释放内存以及关闭文件 av_free(buffer); av_free(pFrameRGBA); av_free(filter_frame); av_free(pFrame); avcodec_close(pCodecCtx); avformat_close_input(&pFormatCtx); avfilter_free(buffersrc_ctx); avfilter_free(buffersink_ctx); avfilter_graph_free(&filter_graph); avcodec_close(audioCodecCtx); free(buffer); free(sws_ctx); free(&windowBuffer); free(out_buffer); free(audio_swr_ctx); free(audio_track); free(audio_track_write_mid); ANativeWindow_release(nativeWindow); (*env)->ReleaseStringUTFChars(env, filePath, file_name); (*env)->ReleaseStringUTFChars(env, filterDescr, filter_descr); LOGE("do release..."); again: again = 0; LOGE("play again..."); return ret; }
int mix_add(mix_t *mix, AVFrame *frame, unsigned int idx, output_t *output) { const char *err; err = "index out of range"; if (idx >= NUM_INPUTS) goto err; err = "mixer not initialized"; if (!mix->src_ctxs[idx]) goto err; dbg("stream %i pts_off %llu in pts %llu in frame pts %llu samples %u mix out pts %llu", idx, (unsigned long long) mix->pts_offs[idx], (unsigned long long) mix->in_pts[idx], (unsigned long long) frame->pts, frame->nb_samples, (unsigned long long) mix->out_pts); // adjust for media started late if (G_UNLIKELY(mix->pts_offs[idx] == (uint64_t) -1LL)) mix->pts_offs[idx] = mix->out_pts - frame->pts; frame->pts += mix->pts_offs[idx]; // fill missing time mix_silence_fill_idx_upto(mix, idx, frame->pts); uint64_t next_pts = frame->pts + frame->nb_samples; err = "failed to add frame to mixer"; if (av_buffersrc_add_frame(mix->src_ctxs[idx], frame)) goto err; // update running counters if (next_pts > mix->out_pts) mix->out_pts = next_pts; if (next_pts > mix->in_pts[idx]) mix->in_pts[idx] = next_pts; av_frame_free(&frame); mix_silence_fill(mix); while (1) { int ret = av_buffersink_get_frame(mix->sink_ctx, mix->sink_frame); err = "failed to get frame from mixer"; if (ret < 0) { if (ret == AVERROR(EAGAIN)) break; else goto err; } frame = resample_frame(&mix->resample, mix->sink_frame, &mix->format); ret = output_add(output, frame); av_frame_unref(mix->sink_frame); av_frame_free(&frame); if (ret) return -1; } return 0; err: ilog(LOG_ERR, "Failed to add frame to mixer: %s", err); av_frame_free(&frame); return -1; }
// decode one audio packet and return its uncompressed size static int audio_decode_frame(struct GroovePlaylist *playlist, struct GrooveFile *file) { struct GroovePlaylistPrivate *p = (struct GroovePlaylistPrivate *) playlist; struct GrooveFilePrivate *f = (struct GrooveFilePrivate *) file; AVPacket *pkt = &f->audio_pkt; AVCodecContext *dec = f->audio_st->codec; AVPacket *pkt_temp = &p->audio_pkt_temp; *pkt_temp = *pkt; // update the audio clock with the pts if we can if (pkt->pts != AV_NOPTS_VALUE) f->audio_clock = av_q2d(f->audio_st->time_base) * pkt->pts; int max_data_size = 0; int len1, got_frame; int new_packet = 1; AVFrame *in_frame = p->in_frame; // NOTE: the audio packet can contain several frames while (pkt_temp->size > 0 || (!pkt_temp->data && new_packet)) { new_packet = 0; len1 = avcodec_decode_audio4(dec, in_frame, &got_frame, pkt_temp); if (len1 < 0) { // if error, we skip the frame pkt_temp->size = 0; return -1; } pkt_temp->data += len1; pkt_temp->size -= len1; if (!got_frame) { // stop sending empty packets if the decoder is finished if (!pkt_temp->data && dec->codec->capabilities & CODEC_CAP_DELAY) return 0; continue; } // push the audio data from decoded frame into the filtergraph int err = av_buffersrc_write_frame(p->abuffer_ctx, in_frame); if (err < 0) { av_strerror(err, p->strbuf, sizeof(p->strbuf)); av_log(NULL, AV_LOG_ERROR, "error writing frame to buffersrc: %s\n", p->strbuf); return -1; } // for each data format in the sink map, pull filtered audio from its // buffersink, turn it into a GrooveBuffer and then increment the ref // count for each sink in that stack. struct SinkMap *map_item = p->sink_map; double clock_adjustment = 0; while (map_item) { struct GrooveSink *example_sink = map_item->stack_head->sink; int data_size = 0; for (;;) { AVFrame *oframe = av_frame_alloc(); int err = example_sink->buffer_sample_count == 0 ? av_buffersink_get_frame(map_item->abuffersink_ctx, oframe) : av_buffersink_get_samples(map_item->abuffersink_ctx, oframe, example_sink->buffer_sample_count); if (err == AVERROR_EOF || err == AVERROR(EAGAIN)) { av_frame_free(&oframe); break; } if (err < 0) { av_frame_free(&oframe); av_log(NULL, AV_LOG_ERROR, "error reading buffer from buffersink\n"); return -1; } struct GrooveBuffer *buffer = frame_to_groove_buffer(playlist, example_sink, oframe); if (!buffer) { av_frame_free(&oframe); return -1; } data_size += buffer->size; struct SinkStack *stack_item = map_item->stack_head; // we hold this reference to avoid cleanups until at least this loop // is done and we call unref after it. groove_buffer_ref(buffer); while (stack_item) { struct GrooveSink *sink = stack_item->sink; struct GrooveSinkPrivate *s = (struct GrooveSinkPrivate *) sink; // as soon as we call groove_queue_put, this buffer could be unref'd. // so we ref before putting it in the queue, and unref if it failed. groove_buffer_ref(buffer); if (groove_queue_put(s->audioq, buffer) < 0) { av_log(NULL, AV_LOG_ERROR, "unable to put buffer in queue\n"); groove_buffer_unref(buffer); } stack_item = stack_item->next; } groove_buffer_unref(buffer); } if (data_size > max_data_size) { max_data_size = data_size; clock_adjustment = data_size / (double)example_sink->bytes_per_sec; } map_item = map_item->next; } // if no pts, then estimate it if (pkt->pts == AV_NOPTS_VALUE) f->audio_clock += clock_adjustment; return max_data_size; } return max_data_size; }
static int filter(struct af_instance *af, struct mp_audio *data, int flags) { struct priv *p = af->priv; struct mp_audio *r = af->data; bool eof = data->samples == 0 && (flags & AF_FILTER_FLAG_EOF); AVFilterLink *l_in = p->in->outputs[0]; AVFrame *frame = av_frame_alloc(); frame->nb_samples = data->samples; frame->format = l_in->format; // Timebase is 1/sample_rate frame->pts = p->samples_in; frame->channel_layout = l_in->channel_layout; frame->sample_rate = l_in->sample_rate; #if LIBAVFILTER_VERSION_MICRO >= 100 // FFmpeg being a stupid POS frame->channels = l_in->channels; #endif frame->extended_data = frame->data; for (int n = 0; n < data->num_planes; n++) frame->data[n] = data->planes[n]; frame->linesize[0] = frame->nb_samples * data->sstride; if (av_buffersrc_add_frame(p->in, eof ? NULL : frame) < 0) { av_frame_free(&frame); return -1; } av_frame_free(&frame); int64_t out_pts = AV_NOPTS_VALUE; r->samples = 0; for (;;) { frame = av_frame_alloc(); if (av_buffersink_get_frame(p->out, frame) < 0) { // Not an error situation - no more output buffers in queue. av_frame_free(&frame); break; } mp_audio_realloc_min(r, r->samples + frame->nb_samples); for (int n = 0; n < r->num_planes; n++) { memcpy((char *)r->planes[n] + r->samples * r->sstride, frame->extended_data[n], frame->nb_samples * r->sstride); } r->samples += frame->nb_samples; if (out_pts == AV_NOPTS_VALUE) out_pts = frame->pts; av_frame_free(&frame); } p->samples_in += data->samples; if (out_pts != AV_NOPTS_VALUE) { double in_time = p->samples_in / (double)data->rate; double out_time = out_pts * av_q2d(p->timebase_out); // Need pts past the last output sample. out_time += r->samples / (double)r->rate; af->delay = in_time - out_time; } *data = *r; return 0; }
int main(int argc, char* argv[]) { int ret; AVFrame *frame_in; AVFrame *frame_out; unsigned char *frame_buffer_in; unsigned char *frame_buffer_out; AVFilterContext *buffersink_ctx; AVFilterContext *buffersrc_ctx; AVFilterGraph *filter_graph; static int video_stream_index = -1; //Input YUV FILE *fp_in=fopen("sintel_480x272_yuv420p.yuv","rb+"); if(fp_in==NULL){ printf("Error open input file.\n"); return -1; } int in_width=480; int in_height=272; //Output YUV FILE *fp_out=fopen("output.yuv","wb+"); if(fp_out==NULL){ printf("Error open output file.\n"); return -1; } //const char *filter_descr = "lutyuv='u=128:v=128'"; const char *filter_descr = "boxblur"; //const char *filter_descr = "hflip"; //const char *filter_descr = "hue='h=60:s=-3'"; //const char *filter_descr = "crop=2/3*in_w:2/3*in_h"; //const char *filter_descr = "drawbox=x=100:y=100:w=100:h=100:[email protected]"; //const char *filter_descr = "drawtext=fontfile=arial.ttf:fontcolor=green:fontsize=30:text='Lei Xiaohua'"; avfilter_register_all(); char args[512]; AVFilter *buffersrc = avfilter_get_by_name("buffer"); AVFilter *buffersink = avfilter_get_by_name("ffbuffersink"); AVFilterInOut *outputs = avfilter_inout_alloc(); AVFilterInOut *inputs = avfilter_inout_alloc(); enum PixelFormat pix_fmts[] = { AV_PIX_FMT_YUV420P, PIX_FMT_NONE }; AVBufferSinkParams *buffersink_params; filter_graph = avfilter_graph_alloc(); /* buffer video source: the decoded frames from the decoder will be inserted here. */ snprintf(args, sizeof(args), "video_size=%dx%d:pix_fmt=%d:time_base=%d/%d:pixel_aspect=%d/%d", in_width,in_height,AV_PIX_FMT_YUV420P, 1, 25,1,1); ret = avfilter_graph_create_filter(&buffersrc_ctx, buffersrc, "in", args, NULL, filter_graph); if (ret < 0) { printf("Cannot create buffer source\n"); return ret; } /* buffer video sink: to terminate the filter chain. */ buffersink_params = av_buffersink_params_alloc(); buffersink_params->pixel_fmts = pix_fmts; ret = avfilter_graph_create_filter(&buffersink_ctx, buffersink, "out", NULL, buffersink_params, filter_graph); av_free(buffersink_params); if (ret < 0) { printf("Cannot create buffer sink\n"); return ret; } /* Endpoints for the filter graph. */ outputs->name = av_strdup("in"); outputs->filter_ctx = buffersrc_ctx; outputs->pad_idx = 0; outputs->next = NULL; inputs->name = av_strdup("out"); inputs->filter_ctx = buffersink_ctx; inputs->pad_idx = 0; inputs->next = NULL; if ((ret = avfilter_graph_parse_ptr(filter_graph, filter_descr, &inputs, &outputs, NULL)) < 0) return ret; if ((ret = avfilter_graph_config(filter_graph, NULL)) < 0) return ret; frame_in=av_frame_alloc(); frame_buffer_in=(unsigned char *)av_malloc(av_image_get_buffer_size(AV_PIX_FMT_YUV420P, in_width,in_height,1)); av_image_fill_arrays(frame_in->data, frame_in->linesize,frame_buffer_in, AV_PIX_FMT_YUV420P,in_width, in_height,1); frame_out=av_frame_alloc(); frame_buffer_out=(unsigned char *)av_malloc(av_image_get_buffer_size(AV_PIX_FMT_YUV420P, in_width,in_height,1)); av_image_fill_arrays(frame_out->data, frame_out->linesize,frame_buffer_out, AV_PIX_FMT_YUV420P,in_width, in_height,1); frame_in->width=in_width; frame_in->height=in_height; frame_in->format=AV_PIX_FMT_YUV420P; while (1) { if(fread(frame_buffer_in, 1, in_width*in_height*3/2, fp_in)!= in_width*in_height*3/2){ break; } //input Y,U,V frame_in->data[0]=frame_buffer_in; frame_in->data[1]=frame_buffer_in+in_width*in_height; frame_in->data[2]=frame_buffer_in+in_width*in_height*5/4; if (av_buffersrc_add_frame(buffersrc_ctx, frame_in) < 0) { printf( "Error while add frame.\n"); break; } /* pull filtered pictures from the filtergraph */ ret = av_buffersink_get_frame(buffersink_ctx, frame_out); if (ret < 0) break; //output Y,U,V if(frame_out->format==AV_PIX_FMT_YUV420P){ for(int i=0;i<frame_out->height;i++){ fwrite(frame_out->data[0]+frame_out->linesize[0]*i,1,frame_out->width,fp_out); } for(int i=0;i<frame_out->height/2;i++){ fwrite(frame_out->data[1]+frame_out->linesize[1]*i,1,frame_out->width/2,fp_out); } for(int i=0;i<frame_out->height/2;i++){ fwrite(frame_out->data[2]+frame_out->linesize[2]*i,1,frame_out->width/2,fp_out); } } printf("Process 1 frame!\n"); av_frame_unref(frame_out); } fclose(fp_in); fclose(fp_out); av_frame_free(&frame_in); av_frame_free(&frame_out); avfilter_graph_free(&filter_graph); return 0; }
int main(int argc, char **argv) { int ret; AVPacket packet; AVFrame *frame = av_frame_alloc(); AVFrame *filt_frame = av_frame_alloc(); int got_frame; if (!frame || !filt_frame) { perror("Could not allocate frame"); exit(1); } if (argc != 2) { fprintf(stderr, "Usage: %s file\n", argv[0]); exit(1); } avcodec_register_all(); av_register_all(); avfilter_register_all(); if ((ret = open_input_file(argv[1])) < 0) goto end; if ((ret = init_filters(filter_descr)) < 0) goto end; /* read all packets */ while (1) { if ((ret = av_read_frame(fmt_ctx, &packet)) < 0) break; if (packet.stream_index == video_stream_index) { avcodec_get_frame_defaults(frame); got_frame = 0; ret = avcodec_decode_video2(dec_ctx, frame, &got_frame, &packet); if (ret < 0) { av_log(NULL, AV_LOG_ERROR, "Error decoding video\n"); break; } if (got_frame) { frame->pts = av_frame_get_best_effort_timestamp(frame); /* push the decoded frame into the filtergraph */ if (av_buffersrc_add_frame_flags(buffersrc_ctx, frame, AV_BUFFERSRC_FLAG_KEEP_REF) < 0) { av_log(NULL, AV_LOG_ERROR, "Error while feeding the filtergraph\n"); break; } /* pull filtered frames from the filtergraph */ while (1) { ret = av_buffersink_get_frame(buffersink_ctx, filt_frame); if (ret == AVERROR(EAGAIN) || ret == AVERROR_EOF) break; if (ret < 0) goto end; display_frame(filt_frame, buffersink_ctx->inputs[0]->time_base); av_frame_unref(filt_frame); } av_frame_unref(frame); } } av_free_packet(&packet); } end: avfilter_graph_free(&filter_graph); if (dec_ctx) avcodec_close(dec_ctx); avformat_close_input(&fmt_ctx); av_frame_free(&frame); av_frame_free(&filt_frame); if (ret < 0 && ret != AVERROR_EOF) { char buf[1024]; av_strerror(ret, buf, sizeof(buf)); fprintf(stderr, "Error occurred: %s\n", buf); exit(1); } exit(0); }
/* decode and play stream. returns 0 or av error code. */ static int play (player_t * const player) { assert (player != NULL); AVPacket pkt; av_init_packet (&pkt); pkt.data = NULL; pkt.size = 0; AVFrame *frame = NULL, *filteredFrame = NULL; frame = av_frame_alloc (); assert (frame != NULL); filteredFrame = av_frame_alloc (); assert (filteredFrame != NULL); while (!player->doQuit) { int ret = av_read_frame (player->fctx, &pkt); if (ret < 0) { av_free_packet (&pkt); return ret; } else if (pkt.stream_index != player->streamIdx) { av_free_packet (&pkt); continue; } AVPacket pkt_orig = pkt; /* pausing */ pthread_mutex_lock (&player->pauseMutex); if (player->doPause) { av_read_pause (player->fctx); do { pthread_cond_wait (&player->pauseCond, &player->pauseMutex); } while (player->doPause); av_read_play (player->fctx); } pthread_mutex_unlock (&player->pauseMutex); while (pkt.size > 0 && !player->doQuit) { int got_frame = 0; const int decoded = avcodec_decode_audio4 (player->st->codec, frame, &got_frame, &pkt); if (decoded < 0) { /* skip this one */ break; } if (got_frame != 0) { /* XXX: suppresses warning from resample filter */ if (frame->pts == (int64_t) AV_NOPTS_VALUE) { frame->pts = 0; } ret = av_buffersrc_write_frame (player->fabuf, frame); assert (ret >= 0); while (true) { if (av_buffersink_get_frame (player->fbufsink, filteredFrame) < 0) { /* try again next frame */ break; } const int numChannels = av_get_channel_layout_nb_channels ( filteredFrame->channel_layout); const int bps = av_get_bytes_per_sample(filteredFrame->format); ao_play (player->aoDev, (char *) filteredFrame->data[0], filteredFrame->nb_samples * numChannels * bps); av_frame_unref (filteredFrame); } } pkt.data += decoded; pkt.size -= decoded; }; av_free_packet (&pkt_orig); player->songPlayed = av_q2d (player->st->time_base) * (double) pkt.pts; player->lastTimestamp = pkt.pts; } av_frame_free (&filteredFrame); av_frame_free (&frame); return 0; }