int FFMpegFifo::getSpace() { //SDL_LockMutex(mutex); int ret = av_fifo_space(fifo); //SDL_UnlockMutex(mutex); return ret; }
int main(void) { /* create a FIFO buffer */ AVFifoBuffer *fifo = av_fifo_alloc(13 * sizeof(int)); int i, j, n; /* fill data */ for (i = 0; av_fifo_space(fifo) >= sizeof(int); i++) av_fifo_generic_write(fifo, &i, sizeof(int), NULL); /* peek at FIFO */ n = av_fifo_size(fifo)/sizeof(int); for (i = -n+1; i < n; i++) { int *v = (int *)av_fifo_peek2(fifo, i*sizeof(int)); printf("%d: %d\n", i, *v); } printf("\n"); /* read data */ for (i = 0; av_fifo_size(fifo) >= sizeof(int); i++) { av_fifo_generic_read(fifo, &j, sizeof(int), NULL); printf("%d ", j); } printf("\n"); av_fifo_free(fifo); return 0; }
static int end_frame(AVFilterLink *inlink) { AVFilterContext *ctx = inlink->dst; BufferSinkContext *buf = inlink->dst->priv; av_assert1(inlink->cur_buf); if (av_fifo_space(buf->fifo) < sizeof(AVFilterBufferRef *)) { /* realloc fifo size */ if (av_fifo_realloc2(buf->fifo, av_fifo_size(buf->fifo) * 2) < 0) { av_log(ctx, AV_LOG_ERROR, "Cannot buffer more frames. Consume some available frames " "before adding new ones.\n"); return AVERROR(ENOMEM); } } /* cache frame */ av_fifo_generic_write(buf->fifo, &inlink->cur_buf, sizeof(AVFilterBufferRef *), NULL); inlink->cur_buf = NULL; if (buf->warning_limit && av_fifo_size(buf->fifo) / sizeof(AVFilterBufferRef *) >= buf->warning_limit) { av_log(ctx, AV_LOG_WARNING, "%d buffers queued in %s, something may be wrong.\n", buf->warning_limit, (char *)av_x_if_null(ctx->name, ctx->filter->name)); buf->warning_limit *= 10; } return 0; }
static void *circular_buffer_task( void *_URLContext) { URLContext *h = _URLContext; UDPContext *s = h->priv_data; fd_set rfds; struct timeval tv; for(;;) { int left; int ret; int len; if (url_interrupt_cb()) { s->circular_buffer_error = EINTR; return NULL; } FD_ZERO(&rfds); FD_SET(s->udp_fd, &rfds); tv.tv_sec = 1; tv.tv_usec = 0; ret = select(s->udp_fd + 1, &rfds, NULL, NULL, &tv); if (ret < 0) { if (ff_neterrno() == AVERROR(EINTR)) continue; s->circular_buffer_error = EIO; return NULL; } if (!(ret > 0 && FD_ISSET(s->udp_fd, &rfds))) continue; /* How much do we have left to the end of the buffer */ /* Whats the minimum we can read so that we dont comletely fill the buffer */ left = av_fifo_space(s->fifo); left = FFMIN(left, s->fifo->end - s->fifo->wptr); /* No Space left, error, what do we do now */ if( !left) { av_log(h, AV_LOG_ERROR, "circular_buffer: OVERRUN\n"); s->circular_buffer_error = EIO; return NULL; } len = recv(s->udp_fd, s->fifo->wptr, left, 0); if (len < 0) { if (ff_neterrno() != AVERROR(EAGAIN) && ff_neterrno() != AVERROR(EINTR)) { s->circular_buffer_error = EIO; return NULL; } } s->fifo->wptr += len; if (s->fifo->wptr >= s->fifo->end) s->fifo->wptr = s->fifo->buffer; s->fifo->wndx += len; } return NULL; }
static int get_space(struct ao *ao) { struct priv *priv = ao->priv; SDL_LockMutex(priv->buffer_mutex); int space = av_fifo_space(priv->buffer); SDL_UnlockMutex(priv->buffer_mutex); return space; }
static void *circular_buffer_task( void *_URLContext) { URLContext *h = _URLContext; UDPContext *s = h->priv_data; int old_cancelstate; pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, &old_cancelstate); pthread_mutex_lock(&s->mutex); if (ff_socket_nonblock(s->udp_fd, 0) < 0) { av_log(h, AV_LOG_ERROR, "Failed to set blocking mode"); s->circular_buffer_error = AVERROR(EIO); goto end; } while(1) { int len; pthread_mutex_unlock(&s->mutex); /* Blocking operations are always cancellation points; see "General Information" / "Thread Cancelation Overview" in Single Unix. */ pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, &old_cancelstate); len = recv(s->udp_fd, s->tmp+4, sizeof(s->tmp)-4, 0); pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, &old_cancelstate); pthread_mutex_lock(&s->mutex); if (len < 0) { if (ff_neterrno() != AVERROR(EAGAIN) && ff_neterrno() != AVERROR(EINTR)) { s->circular_buffer_error = ff_neterrno(); goto end; } continue; } AV_WL32(s->tmp, len); if(av_fifo_space(s->fifo) < len + 4) { /* No Space left */ if (s->overrun_nonfatal) { av_log(h, AV_LOG_WARNING, "Circular buffer overrun. " "Surviving due to overrun_nonfatal option\n"); continue; } else { av_log(h, AV_LOG_ERROR, "Circular buffer overrun. " "To avoid, increase fifo_size URL option. " "To survive in such case, use overrun_nonfatal option\n"); s->circular_buffer_error = AVERROR(EIO); goto end; } } av_fifo_generic_write(s->fifo, s->tmp, len+4, NULL); pthread_cond_signal(&s->cond); } end: pthread_cond_signal(&s->cond); pthread_mutex_unlock(&s->mutex); return NULL; }
int attribute_align_arg av_buffersrc_add_frame(AVFilterContext *ctx, AVFrame *frame) { BufferSourceContext *s = ctx->priv; AVFrame *copy; int refcounted, ret; if (!frame) { s->eof = 1; return 0; } else if (s->eof) return AVERROR(EINVAL); refcounted = !!frame->buf[0]; switch (ctx->outputs[0]->type) { case AVMEDIA_TYPE_VIDEO: CHECK_VIDEO_PARAM_CHANGE(ctx, s, frame->width, frame->height, frame->format); break; case AVMEDIA_TYPE_AUDIO: CHECK_AUDIO_PARAM_CHANGE(ctx, s, frame->sample_rate, frame->channel_layout, frame->format); break; default: return AVERROR(EINVAL); } if (!av_fifo_space(s->fifo) && (ret = av_fifo_realloc2(s->fifo, av_fifo_size(s->fifo) + sizeof(copy))) < 0) return ret; if (!(copy = av_frame_alloc())) return AVERROR(ENOMEM); if (refcounted) { av_frame_move_ref(copy, frame); } else { ret = av_frame_ref(copy, frame); if (ret < 0) { av_frame_free(©); return ret; } } if ((ret = av_fifo_generic_write(s->fifo, ©, sizeof(copy), NULL)) < 0) { if (refcounted) av_frame_move_ref(frame, copy); av_frame_free(©); return ret; } return 0; }
static void resume(struct ao *ao) { struct priv *priv = ao->priv; SDL_LockMutex(priv->buffer_mutex); int free = av_fifo_space(priv->buffer); SDL_UnlockMutex(priv->buffer_mutex); if (free) priv->unpause = 1; else do_resume(ao); }
static void write_buf(AVFilterContext *ctx, AVFilterBufferRef *buf) { BufferSinkContext *sink = ctx->priv; if (av_fifo_space(sink->fifo) < sizeof(AVFilterBufferRef *) && (av_fifo_realloc2(sink->fifo, av_fifo_size(sink->fifo) * 2) < 0)) { av_log(ctx, AV_LOG_ERROR, "Error reallocating the FIFO.\n"); return; } av_fifo_generic_write(sink->fifo, &buf, sizeof(buf), NULL); }
static int process_callback(jack_nframes_t nframes, void *arg) { /* Warning: this function runs in realtime. One mustn't allocate memory here * or do any other thing that could block. */ int i, j; JackData *self = arg; float * buffer; jack_nframes_t latency, cycle_delay; AVPacket pkt; float *pkt_data; double cycle_time; if (!self->client) return 0; /* The approximate delay since the hardware interrupt as a number of frames */ cycle_delay = jack_frames_since_cycle_start(self->client); /* Retrieve filtered cycle time */ cycle_time = ff_timefilter_update(self->timefilter, av_gettime() / 1000000.0 - (double) cycle_delay / self->sample_rate, self->buffer_size); /* Check if an empty packet is available, and if there's enough space to send it back once filled */ if ((av_fifo_size(self->new_pkts) < sizeof(pkt)) || (av_fifo_space(self->filled_pkts) < sizeof(pkt))) { self->pkt_xrun = 1; return 0; } /* Retrieve empty (but allocated) packet */ av_fifo_generic_read(self->new_pkts, &pkt, sizeof(pkt), NULL); pkt_data = (float *) pkt.data; latency = 0; /* Copy and interleave audio data from the JACK buffer into the packet */ for (i = 0; i < self->nports; i++) { latency += jack_port_get_total_latency(self->client, self->ports[i]); buffer = jack_port_get_buffer(self->ports[i], self->buffer_size); for (j = 0; j < self->buffer_size; j++) pkt_data[j * self->nports + i] = buffer[j]; } /* Timestamp the packet with the cycle start time minus the average latency */ pkt.pts = (cycle_time - (double) latency / (self->nports * self->sample_rate)) * 1000000.0; /* Send the now filled packet back, and increase packet counter */ av_fifo_generic_write(self->filled_pkts, &pkt, sizeof(pkt), NULL); sem_post(&self->packet_count); return 0; }
static int write_to_fifo(AVFifoBuffer *fifo, AVFrame *buf) { int ret; if (!av_fifo_space(fifo) && (ret = av_fifo_realloc2(fifo, 2*av_fifo_size(fifo)))) { av_frame_free(&buf); return ret; } av_fifo_generic_write(fifo, &buf, sizeof(buf), NULL); return 0; }
int FFMpegFifo::read(unsigned char* dst,int readSize) { //SDL_LockMutex(mutex); if (av_fifo_size(fifo) < readSize) { waitReadBytes = readSize; //SDL_CondWait(condRead,mutex); } int ret = av_fifo_generic_read(fifo,dst,readSize,NULL); if (av_fifo_space(fifo) >= waitWriteBytes) //SDL_CondSignal(condWrite); //SDL_UnlockMutex(mutex); return readSize; }
static void end_frame(AVFilterLink *link) { AVFilterContext *ctx = link->dst; BufferSinkContext *sink = ctx->priv; if (av_fifo_space(sink->fifo) < sizeof(AVFilterBufferRef *) && (av_fifo_realloc2(sink->fifo, av_fifo_size(sink->fifo) * 2) < 0)) { av_log(ctx, AV_LOG_ERROR, "Error reallocating the FIFO.\n"); return; } av_fifo_generic_write(sink->fifo, &link->cur_buf, sizeof(link->cur_buf), NULL); link->cur_buf = NULL; }
static int av_thread_message_queue_send_locked(AVThreadMessageQueue *mq, void *msg, unsigned flags) { while (!mq->err_send && av_fifo_space(mq->fifo) < mq->elsize) { if ((flags & AV_THREAD_MESSAGE_NONBLOCK)) return AVERROR(EAGAIN); pthread_cond_wait(&mq->cond, &mq->lock); } if (mq->err_send) return mq->err_send; av_fifo_generic_write(mq->fifo, msg, mq->elsize, NULL); pthread_cond_signal(&mq->cond); return 0; }
static int play(struct ao *ao, void *data, int len, int flags) { struct priv *priv = ao->priv; SDL_LockMutex(priv->buffer_mutex); int free = av_fifo_space(priv->buffer); if (len > free) len = free; av_fifo_generic_write(priv->buffer, data, len, NULL); SDL_CondSignal(priv->underrun_cond); SDL_UnlockMutex(priv->buffer_mutex); if (priv->unpause) { priv->unpause = 0; do_resume(ao); } return len; }
int FFMpegFifo::write(unsigned char* src,int writeSize) { //SDL_LockMutex(mutex); if (av_fifo_space(fifo) < writeSize) { waitWriteBytes = writeSize; //SDL_CondWait(condWrite,mutex); } int ret = av_fifo_generic_write(fifo,src,writeSize,NULL); /* if (av_fifo_size(fifo) >= waitReadBytes) SDL_CondSignal(condRead); */ //SDL_UnlockMutex(mutex); return ret; }
int av_buffersrc_buffer(AVFilterContext *s, AVFilterBufferRef *buf) { BufferSourceContext *c = s->priv; int ret; if (!av_fifo_space(c->fifo) && (ret = av_fifo_realloc2(c->fifo, av_fifo_size(c->fifo) + sizeof(buf))) < 0) return ret; // CHECK_PARAM_CHANGE(s, c, buf->video->w, buf->video->h, buf->format); if ((ret = av_fifo_generic_write(c->fifo, &buf, sizeof(buf), NULL)) < 0) return ret; return 0; }
static int supply_new_packets(JackData *self, AVFormatContext *context) { AVPacket pkt; int test, pkt_size = self->buffer_size * self->nports * sizeof(float); /* Supply the process callback with new empty packets, by filling the new * packets FIFO buffer with as many packets as possible. process_callback() * can't do this by itself, because it can't allocate memory in realtime. */ while (av_fifo_space(self->new_pkts) >= sizeof(pkt)) { if ((test = av_new_packet(&pkt, pkt_size)) < 0) { av_log(context, AV_LOG_ERROR, "Could not create packet of size %d\n", pkt_size); return test; } av_fifo_generic_write(self->new_pkts, &pkt, sizeof(pkt), NULL); } return 0; }
static int add_buffer_ref(AVFilterContext *ctx, AVFrame *ref) { BufferSinkContext *buf = ctx->priv; if (av_fifo_space(buf->fifo) < sizeof(AVFilterBufferRef *)) { /* realloc fifo size */ if (av_fifo_realloc2(buf->fifo, av_fifo_size(buf->fifo) * 2) < 0) { av_log(ctx, AV_LOG_ERROR, "Cannot buffer more frames. Consume some available frames " "before adding new ones.\n"); return AVERROR(ENOMEM); } } /* cache frame */ av_fifo_generic_write(buf->fifo, &ref, sizeof(AVFilterBufferRef *), NULL); return 0; }
static void end_frame(AVFilterLink *inlink) { AVFilterContext *ctx = inlink->dst; BufferSinkContext *buf = inlink->dst->priv; if (av_fifo_space(buf->fifo) < sizeof(AVFilterBufferRef *)) { /* realloc fifo size */ if (av_fifo_realloc2(buf->fifo, av_fifo_size(buf->fifo) * 2) < 0) { av_log(ctx, AV_LOG_ERROR, "Cannot buffer more frames. Consume some available frames " "before adding new ones.\n"); return; } } /* cache frame */ av_fifo_generic_write(buf->fifo, &inlink->cur_buf, sizeof(AVFilterBufferRef *), NULL); }
static void start_frame(AVFilterLink *inlink, AVFilterBufferRef *picref) { SelectContext *select = inlink->dst->priv; select->select = select_frame(inlink->dst, picref); if (select->select) { /* frame was requested through poll_frame */ if (select->cache_frames) { if (!av_fifo_space(select->pending_frames)) av_log(inlink->dst, AV_LOG_ERROR, "Buffering limit reached, cannot cache more frames\n"); else av_fifo_generic_write(select->pending_frames, &picref, sizeof(picref), NULL); return; } avfilter_start_frame(inlink->dst->outputs[0], avfilter_ref_buffer(picref, ~0)); } }
/* This function inserts a packet at fifo front. */ static void qsv_packet_push_front(QSVContext *q, AVPacket *avpkt) { int fifo_size = av_fifo_size(q->pkt_fifo); if (!fifo_size) { /* easy case fifo is empty */ av_fifo_generic_write(q->pkt_fifo, avpkt, sizeof(*avpkt), NULL); } else { /* realloc necessary */ AVPacket pkt; AVFifoBuffer *fifo = av_fifo_alloc(fifo_size+av_fifo_space(q->pkt_fifo)); av_fifo_generic_write(fifo, avpkt, sizeof(*avpkt), NULL); while (av_fifo_size(q->pkt_fifo)) { av_fifo_generic_read(q->pkt_fifo, &pkt, sizeof(pkt), NULL); av_fifo_generic_write(fifo, &pkt, sizeof(pkt), NULL); } av_fifo_free(q->pkt_fifo); q->pkt_fifo = fifo; } }
static int poll_frame(AVFilterLink *outlink) { SelectContext *select = outlink->src->priv; AVFilterLink *inlink = outlink->src->inputs[0]; int count, ret; if (!av_fifo_size(select->pending_frames)) { if ((count = ff_poll_frame(inlink)) <= 0) return count; /* request frame from input, and apply select condition to it */ select->cache_frames = 1; while (count-- && av_fifo_space(select->pending_frames)) { ret = ff_request_frame(inlink); if (ret < 0) break; } select->cache_frames = 0; } return av_fifo_size(select->pending_frames)/sizeof(AVFrame*); }
static int filter_frame(AVFilterLink *inlink, AVFrame *frame) { SelectContext *select = inlink->dst->priv; select->select = select_frame(inlink->dst, frame); if (select->select) { /* frame was requested through poll_frame */ if (select->cache_frames) { if (!av_fifo_space(select->pending_frames)) { av_log(inlink->dst, AV_LOG_ERROR, "Buffering limit reached, cannot cache more frames\n"); av_frame_free(&frame); } else av_fifo_generic_write(select->pending_frames, &frame, sizeof(frame), NULL); return 0; } return ff_filter_frame(inlink->dst->outputs[0], frame); } av_frame_free(&frame); return 0; }
static void *circular_buffer_task( void *_handle) { CacheHttpContext * s = (CacheHttpContext *)_handle; URLContext *h = NULL; float config_value = 0.0; void * fp = NULL; int config_ret = 0; while(!s->EXIT) { av_log(h, AV_LOG_ERROR, "----------circular_buffer_task item "); s->reset_flag = 1; if (url_interrupt_cb()) { s->circular_buffer_error = EINTR; goto FAIL; } if(h) { CacheHttp_ffurl_close(h); config_ret = am_getconfig_float("libplayer.hls.dump",&config_value); if(config_ret >= 0 && (int)config_value == 2) CacheHttp_dump_close(fp); h = NULL; } list_item_t * item = getCurrentSegment(NULL); if(!item||(!item->file&&!item->flags&ENDLIST_FLAG)) { usleep(WAIT_TIME); continue; } s->reset_flag = 0; s->item_starttime = item->start_time; s->item_duration = item->duration; s->have_list_end = item->have_list_end; s->ktype = item->ktype; if(item->key_ctx!=NULL&& s->ktype==KEY_AES_128) { ff_data_to_hex(s->iv, item->key_ctx->iv, sizeof(item->key_ctx->iv), 0); ff_data_to_hex(s->key, item->key_ctx->key, sizeof(item->key_ctx->key), 0); s->iv[32] = s->key[32] = '\0'; } if(item&&item->flags&ENDLIST_FLAG) { s->finish_flag =1; } else { s->finish_flag =0; } if(s->finish_flag) { av_log(NULL, AV_LOG_INFO, "ENDLIST_FLAG, return 0\n"); //break; usleep(500*1000); continue; } int err, http_code; char* filename = NULL; if(s->ktype == KEY_NONE) { filename = av_strdup(item->file); } else { char url[MAX_URL_SIZE]; if (strstr(item->file, "://")) snprintf(url, sizeof(url), "crypto+%s", item->file); else snprintf(url, sizeof(url), "crypto:%s", item->file); filename = av_strdup(url); } int retry_num = 0; OPEN_RETRY: if(s->RESET) goto SKIP; err = CacheHttp_advanced_ffurl_open_h(&h, filename,AVIO_FLAG_READ|AVIO_FLAG_NONBLOCK, s->headers, &http_code,s); if (err) { if(url_interrupt_cb()) { if(filename) { av_free(filename); filename = NULL; } break; } if(1 == http_code && !s->have_list_end) { av_log(h, AV_LOG_ERROR, "----------CacheHttpContext : ffurl_open_h 404\n"); if(retry_num++ < LIVE_HTTP_RETRY_TIMES) { usleep(WAIT_TIME); goto OPEN_RETRY; } else { goto SKIP; } } else if(s->have_list_end || ((2 == http_code || 3 == http_code)&& !s->have_list_end)) { usleep(1000*20); goto OPEN_RETRY; } else if(!s->have_list_end&&err ==AVERROR(EIO)) { if(retry_num++ < LIVE_HTTP_RETRY_TIMES) {//if live streaming,just keep on 2s. usleep(WAIT_TIME); goto OPEN_RETRY; } else { av_log(h, AV_LOG_ERROR, "----------CacheHttpContext : ffurl_open_h failed ,%d\n",err); if(filename) { av_free(filename); filename = NULL; } break; } } else { av_log(h, AV_LOG_ERROR, "----------CacheHttpContext : ffurl_open_h failed ,%d\n",err); if(filename) { av_free(filename); filename = NULL; } break; } } if(h && s->seek_flag) { int64_t cur_pos = CacheHttp_ffurl_seek(h, 0, SEEK_CUR); int64_t pos_ret = CacheHttp_ffurl_seek(h, s->seek_pos-cur_pos, SEEK_CUR); av_log(NULL,AV_LOG_INFO,"--------------> cachehttp_seek seek_pos=%lld, pos_ret=%lld", s->seek_pos, pos_ret); s->seek_flag = 0; } s->hd = h; s->item_pos = 0; s->item_size = CacheHttp_ffurl_seek(s->hd, 0, AVSEEK_SIZE); item->item_size = s->item_size; char tmpbuf[TMP_BUFFER_SIZE]; int left = 0; int tmpdatasize = 0; config_ret = am_getconfig_float("libplayer.hls.dump",&config_value); if(config_ret >= 0 && config_value > 0) CacheHttp_dump_open(&fp, filename, (int)config_value); while(!s->EXIT) { if(s->RESET) break; if (url_interrupt_cb()) { s->circular_buffer_error = EINTR; break; } if(!s->hd) break; if(s->hd && tmpdatasize <= 0) { bandwidth_measure_start_read(s->bandwidth_measure); tmpdatasize = CacheHttp_ffurl_read(s->hd, tmpbuf, TMP_BUFFER_SIZE); bandwidth_measure_finish_read(s->bandwidth_measure,tmpdatasize); } //if(tmpdatasize > 0) { pthread_mutex_lock(&s->read_mutex); left = av_fifo_space(s->fifo); left = FFMIN(left, s->fifo->end - s->fifo->wptr); if( !left) { pthread_mutex_unlock(&s->read_mutex); usleep(WAIT_TIME); continue; } left = FFMIN(left, tmpdatasize); if(left >0) { memcpy(s->fifo->wptr, tmpbuf , left); tmpdatasize-=left; } if(tmpdatasize>0) { memmove(tmpbuf, tmpbuf+left , tmpdatasize); } if (left > 0) { config_ret = am_getconfig_float("libplayer.hls.dump",&config_value); if(config_ret >= 0 && config_value > 0) CacheHttp_dump_write(fp, s->fifo->wptr, left); s->fifo->wptr += left; if (s->fifo->wptr >= s->fifo->end) s->fifo->wptr = s->fifo->buffer; s->fifo->wndx += left; s->item_pos += left; } else if(left == AVERROR(EAGAIN) || (left < 0 && s->have_list_end&& left != AVERROR_EOF)) { pthread_mutex_unlock(&s->read_mutex); continue; } else { pthread_mutex_unlock(&s->read_mutex); av_log(h, AV_LOG_ERROR, "---------- circular_buffer_task read left = %d\n", left); break; } pthread_mutex_unlock(&s->read_mutex); //} //usleep(WAIT_TIME); } SKIP: if(filename) { av_free(filename); filename = NULL; } if(!s->RESET) switchNextSegment(NULL); } FAIL: if(h) CacheHttp_ffurl_close(h); s->hd = NULL; s->EXITED = 1; config_ret = am_getconfig_float("libplayer.hls.dump",&config_value); if(config_ret >= 0 && config_value > 0) CacheHttp_dump_close(fp); av_log(NULL, AV_LOG_ERROR, "---------> CacheHttp thread quit !"); return NULL; }
int ff_qsv_encode(AVCodecContext *avctx, QSVEncContext *q, AVPacket *pkt, const AVFrame *frame, int *got_packet) { AVPacket new_pkt = { 0 }; mfxBitstream *bs; mfxFrameSurface1 *surf = NULL; mfxSyncPoint sync = NULL; int ret; if (frame) { ret = submit_frame(q, frame, &surf); if (ret < 0) { av_log(avctx, AV_LOG_ERROR, "Error submitting the frame for encoding.\n"); return ret; } } ret = av_new_packet(&new_pkt, q->packet_size); if (ret < 0) { av_log(avctx, AV_LOG_ERROR, "Error allocating the output packet\n"); return ret; } bs = av_mallocz(sizeof(*bs)); if (!bs) { av_packet_unref(&new_pkt); return AVERROR(ENOMEM); } bs->Data = new_pkt.data; bs->MaxLength = new_pkt.size; do { ret = MFXVideoENCODE_EncodeFrameAsync(q->session, NULL, surf, bs, &sync); if (ret == MFX_WRN_DEVICE_BUSY) { av_usleep(500); continue; } break; } while ( 1 ); if (ret < 0) { av_packet_unref(&new_pkt); av_freep(&bs); if (ret == MFX_ERR_MORE_DATA) return 0; av_log(avctx, AV_LOG_ERROR, "EncodeFrameAsync returned %d\n", ret); return ff_qsv_error(ret); } if (ret == MFX_WRN_INCOMPATIBLE_VIDEO_PARAM) { if (frame->interlaced_frame) print_interlace_msg(avctx, q); else av_log(avctx, AV_LOG_WARNING, "EncodeFrameAsync returned 'incompatible param' code\n"); } if (sync) { av_fifo_generic_write(q->async_fifo, &new_pkt, sizeof(new_pkt), NULL); av_fifo_generic_write(q->async_fifo, &sync, sizeof(sync), NULL); av_fifo_generic_write(q->async_fifo, &bs, sizeof(bs), NULL); } else { av_packet_unref(&new_pkt); av_freep(&bs); } if (!av_fifo_space(q->async_fifo) || (!frame && av_fifo_size(q->async_fifo))) { av_fifo_generic_read(q->async_fifo, &new_pkt, sizeof(new_pkt), NULL); av_fifo_generic_read(q->async_fifo, &sync, sizeof(sync), NULL); av_fifo_generic_read(q->async_fifo, &bs, sizeof(bs), NULL); MFXVideoCORE_SyncOperation(q->session, sync, 60000); new_pkt.dts = av_rescale_q(bs->DecodeTimeStamp, (AVRational){1, 90000}, avctx->time_base); new_pkt.pts = av_rescale_q(bs->TimeStamp, (AVRational){1, 90000}, avctx->time_base); new_pkt.size = bs->DataLength; if (bs->FrameType & MFX_FRAMETYPE_IDR || bs->FrameType & MFX_FRAMETYPE_xIDR) new_pkt.flags |= AV_PKT_FLAG_KEY; #if FF_API_CODED_FRAME FF_DISABLE_DEPRECATION_WARNINGS if (bs->FrameType & MFX_FRAMETYPE_I || bs->FrameType & MFX_FRAMETYPE_xI) avctx->coded_frame->pict_type = AV_PICTURE_TYPE_I; else if (bs->FrameType & MFX_FRAMETYPE_P || bs->FrameType & MFX_FRAMETYPE_xP) avctx->coded_frame->pict_type = AV_PICTURE_TYPE_P; else if (bs->FrameType & MFX_FRAMETYPE_B || bs->FrameType & MFX_FRAMETYPE_xB) avctx->coded_frame->pict_type = AV_PICTURE_TYPE_B; FF_ENABLE_DEPRECATION_WARNINGS #endif av_freep(&bs); if (pkt->data) { if (pkt->size < new_pkt.size) { av_log(avctx, AV_LOG_ERROR, "Submitted buffer not large enough: %d < %d\n", pkt->size, new_pkt.size); av_packet_unref(&new_pkt); return AVERROR(EINVAL); } memcpy(pkt->data, new_pkt.data, new_pkt.size); pkt->size = new_pkt.size; ret = av_packet_copy_props(pkt, &new_pkt); av_packet_unref(&new_pkt); if (ret < 0) return ret; } else *pkt = new_pkt; *got_packet = 1; }
static int qsv_decode(AVCodecContext *avctx, QSVContext *q, AVFrame *frame, int *got_frame, AVPacket *avpkt) { QSVFrame *out_frame; mfxFrameSurface1 *insurf; mfxFrameSurface1 *outsurf; mfxSyncPoint *sync; mfxBitstream bs = { { { 0 } } }; int ret; if (avpkt->size) { bs.Data = avpkt->data; bs.DataLength = avpkt->size; bs.MaxLength = bs.DataLength; bs.TimeStamp = avpkt->pts; } sync = av_mallocz(sizeof(*sync)); if (!sync) { av_freep(&sync); return AVERROR(ENOMEM); } do { ret = get_surface(avctx, q, &insurf); if (ret < 0) return ret; ret = MFXVideoDECODE_DecodeFrameAsync(q->session, avpkt->size ? &bs : NULL, insurf, &outsurf, sync); if (ret == MFX_WRN_DEVICE_BUSY) av_usleep(1); } while (ret == MFX_WRN_DEVICE_BUSY || ret == MFX_ERR_MORE_SURFACE); if (ret != MFX_ERR_NONE && ret != MFX_ERR_MORE_DATA && ret != MFX_WRN_VIDEO_PARAM_CHANGED && ret != MFX_ERR_MORE_SURFACE) { av_freep(&sync); return ff_qsv_print_error(avctx, ret, "Error during QSV decoding."); } /* make sure we do not enter an infinite loop if the SDK * did not consume any data and did not return anything */ if (!*sync && !bs.DataOffset) { ff_qsv_print_warning(avctx, ret, "A decode call did not consume any data"); bs.DataOffset = avpkt->size; } if (*sync) { QSVFrame *out_frame = find_frame(q, outsurf); if (!out_frame) { av_log(avctx, AV_LOG_ERROR, "The returned surface does not correspond to any frame\n"); av_freep(&sync); return AVERROR_BUG; } out_frame->queued = 1; av_fifo_generic_write(q->async_fifo, &out_frame, sizeof(out_frame), NULL); av_fifo_generic_write(q->async_fifo, &sync, sizeof(sync), NULL); } else { av_freep(&sync); } if (!av_fifo_space(q->async_fifo) || (!avpkt->size && av_fifo_size(q->async_fifo))) { AVFrame *src_frame; av_fifo_generic_read(q->async_fifo, &out_frame, sizeof(out_frame), NULL); av_fifo_generic_read(q->async_fifo, &sync, sizeof(sync), NULL); out_frame->queued = 0; do { ret = MFXVideoCORE_SyncOperation(q->session, *sync, 1000); } while (ret == MFX_WRN_IN_EXECUTION); av_freep(&sync); src_frame = out_frame->frame; ret = av_frame_ref(frame, src_frame); if (ret < 0) return ret; outsurf = &out_frame->surface; #if FF_API_PKT_PTS FF_DISABLE_DEPRECATION_WARNINGS frame->pkt_pts = outsurf->Data.TimeStamp; FF_ENABLE_DEPRECATION_WARNINGS #endif frame->pts = outsurf->Data.TimeStamp; frame->repeat_pict = outsurf->Info.PicStruct & MFX_PICSTRUCT_FRAME_TRIPLING ? 4 : outsurf->Info.PicStruct & MFX_PICSTRUCT_FRAME_DOUBLING ? 2 : outsurf->Info.PicStruct & MFX_PICSTRUCT_FIELD_REPEATED ? 1 : 0; frame->top_field_first = outsurf->Info.PicStruct & MFX_PICSTRUCT_FIELD_TFF; frame->interlaced_frame = !(outsurf->Info.PicStruct & MFX_PICSTRUCT_PROGRESSIVE); /* update the surface properties */ if (avctx->pix_fmt == AV_PIX_FMT_QSV) ((mfxFrameSurface1*)frame->data[3])->Info = outsurf->Info; *got_frame = 1; } return bs.DataOffset; }
static int get_space(void) { return av_fifo_space(buffer); }
static int flac_parse(AVCodecParserContext *s, AVCodecContext *avctx, const uint8_t **poutbuf, int *poutbuf_size, const uint8_t *buf, int buf_size) { FLACParseContext *fpc = s->priv_data; FLACHeaderMarker *curr; int nb_headers; const uint8_t *read_end = buf; const uint8_t *read_start = buf; if (s->flags & PARSER_FLAG_COMPLETE_FRAMES) { FLACFrameInfo fi; if (frame_header_is_valid(avctx, buf, &fi)) s->duration = fi.blocksize; *poutbuf = buf; *poutbuf_size = buf_size; return buf_size; } fpc->avctx = avctx; if (fpc->best_header_valid) return get_best_header(fpc, poutbuf, poutbuf_size); /* If a best_header was found last call remove it with the buffer data. */ if (fpc->best_header && fpc->best_header->best_child) { FLACHeaderMarker *temp; FLACHeaderMarker *best_child = fpc->best_header->best_child; /* Remove headers in list until the end of the best_header. */ for (curr = fpc->headers; curr != best_child; curr = temp) { if (curr != fpc->best_header) { av_log(avctx, AV_LOG_DEBUG, "dropping low score %i frame header from offset %i to %i\n", curr->max_score, curr->offset, curr->next->offset); } temp = curr->next; av_freep(&curr->link_penalty); av_free(curr); fpc->nb_headers_buffered--; } /* Release returned data from ring buffer. */ av_fifo_drain(fpc->fifo_buf, best_child->offset); /* Fix the offset for the headers remaining to match the new buffer. */ for (curr = best_child->next; curr; curr = curr->next) curr->offset -= best_child->offset; fpc->nb_headers_buffered--; best_child->offset = 0; fpc->headers = best_child; if (fpc->nb_headers_buffered >= FLAC_MIN_HEADERS) { fpc->best_header = best_child; return get_best_header(fpc, poutbuf, poutbuf_size); } fpc->best_header = NULL; } else if (fpc->best_header) { /* No end frame no need to delete the buffer; probably eof */ FLACHeaderMarker *temp; for (curr = fpc->headers; curr != fpc->best_header; curr = temp) { temp = curr->next; av_freep(&curr->link_penalty); av_free(curr); } fpc->headers = fpc->best_header->next; av_freep(&fpc->best_header->link_penalty); av_freep(&fpc->best_header); } /* Find and score new headers. */ while ((buf && read_end < buf + buf_size && fpc->nb_headers_buffered < FLAC_MIN_HEADERS) || (!buf && !fpc->end_padded)) { int start_offset; /* Pad the end once if EOF, to check the final region for headers. */ if (!buf) { fpc->end_padded = 1; buf_size = MAX_FRAME_HEADER_SIZE; read_end = read_start + MAX_FRAME_HEADER_SIZE; } else { /* The maximum read size is the upper-bound of what the parser needs to have the required number of frames buffered */ int nb_desired = FLAC_MIN_HEADERS - fpc->nb_headers_buffered + 1; read_end = read_end + FFMIN(buf + buf_size - read_end, nb_desired * FLAC_AVG_FRAME_SIZE); } if (!av_fifo_space(fpc->fifo_buf) && av_fifo_size(fpc->fifo_buf) / FLAC_AVG_FRAME_SIZE > fpc->nb_headers_buffered * 10) { /* There is less than one valid flac header buffered for 10 headers * buffered. Therefore the fifo is most likely filled with invalid * data and the input is not a flac file. */ goto handle_error; } /* Fill the buffer. */ if (av_fifo_realloc2(fpc->fifo_buf, (read_end - read_start) + av_fifo_size(fpc->fifo_buf)) < 0) { av_log(avctx, AV_LOG_ERROR, "couldn't reallocate buffer of size %td\n", (read_end - read_start) + av_fifo_size(fpc->fifo_buf)); goto handle_error; } if (buf) { av_fifo_generic_write(fpc->fifo_buf, (void*) read_start, read_end - read_start, NULL); } else { int8_t pad[MAX_FRAME_HEADER_SIZE] = { 0 }; av_fifo_generic_write(fpc->fifo_buf, pad, sizeof(pad), NULL); } /* Tag headers and update sequences. */ start_offset = av_fifo_size(fpc->fifo_buf) - ((read_end - read_start) + (MAX_FRAME_HEADER_SIZE - 1)); start_offset = FFMAX(0, start_offset); nb_headers = find_new_headers(fpc, start_offset); if (nb_headers < 0) { av_log(avctx, AV_LOG_ERROR, "find_new_headers couldn't allocate FLAC header\n"); goto handle_error; } fpc->nb_headers_buffered = nb_headers; /* Wait till FLAC_MIN_HEADERS to output a valid frame. */ if (!fpc->end_padded && fpc->nb_headers_buffered < FLAC_MIN_HEADERS) { if (buf && read_end < buf + buf_size) { read_start = read_end; continue; } else { goto handle_error; } } /* If headers found, update the scores since we have longer chains. */ if (fpc->end_padded || fpc->nb_headers_found) score_sequences(fpc); /* restore the state pre-padding */ if (fpc->end_padded) { /* HACK: drain the tail of the fifo */ fpc->fifo_buf->wptr -= MAX_FRAME_HEADER_SIZE; fpc->fifo_buf->wndx -= MAX_FRAME_HEADER_SIZE; if (fpc->fifo_buf->wptr < 0) { fpc->fifo_buf->wptr += fpc->fifo_buf->end - fpc->fifo_buf->buffer; } buf_size = 0; read_start = read_end = NULL; } } curr = fpc->headers; for (curr = fpc->headers; curr; curr = curr->next) if (!fpc->best_header || curr->max_score > fpc->best_header->max_score) fpc->best_header = curr; if (fpc->best_header) { fpc->best_header_valid = 1; if (fpc->best_header->offset > 0) { /* Output a junk frame. */ av_log(avctx, AV_LOG_DEBUG, "Junk frame till offset %i\n", fpc->best_header->offset); /* Set duration to 0. It is unknown or invalid in a junk frame. */ s->duration = 0; *poutbuf_size = fpc->best_header->offset; *poutbuf = flac_fifo_read_wrap(fpc, 0, *poutbuf_size, &fpc->wrap_buf, &fpc->wrap_buf_allocated_size); return buf_size ? (read_end - buf) : (fpc->best_header->offset - av_fifo_size(fpc->fifo_buf)); } if (!buf_size) return get_best_header(fpc, poutbuf, poutbuf_size); } handle_error: *poutbuf = NULL; *poutbuf_size = 0; return read_end - buf; }
/** * \brief insert len bytes into buffer * \param data data to insert * \param len length of data * \return number of bytes inserted into buffer * * If there is not enough room, the buffer is filled up */ static int write_buffer(unsigned char* data, int len) { int free = av_fifo_space(buffer); if (len > free) len = free; return av_fifo_generic_write(buffer, data, len, NULL); }