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; }
bool ExportFFmpeg::EncodeAudioFrame(int16_t *pFrame, int frameSize) { AVPacket pkt; int nBytesToWrite = 0; uint8_t *pRawSamples = NULL; int nAudioFrameSizeOut = default_frame_size * mEncAudioCodecCtx->channels * sizeof(int16_t); int ret; nBytesToWrite = frameSize; pRawSamples = (uint8_t*)pFrame; av_fifo_realloc2(mEncAudioFifo, av_fifo_size(mEncAudioFifo) + frameSize); // Put the raw audio samples into the FIFO. ret = av_fifo_generic_write(mEncAudioFifo, pRawSamples, nBytesToWrite,NULL); wxASSERT(ret == nBytesToWrite); if (nAudioFrameSizeOut > mEncAudioFifoOutBufSiz) { wxLogError(wxT("FFmpeg : ERROR - nAudioFrameSizeOut too large.")); return false; } // Read raw audio samples out of the FIFO in nAudioFrameSizeOut byte-sized groups to encode. while ((ret = av_fifo_size(mEncAudioFifo)) >= nAudioFrameSizeOut) { ret = av_fifo_generic_read(mEncAudioFifo, mEncAudioFifoOutBuf, nAudioFrameSizeOut, NULL); av_init_packet(&pkt); int ret= encode_audio(mEncAudioCodecCtx, &pkt, // out (int16_t*)mEncAudioFifoOutBuf, // in default_frame_size); if (ret < 0) { wxLogError(wxT("FFmpeg : ERROR - Can't encode audio frame.")); return false; } if (ret == 0) continue; // Rescale from the codec time_base to the AVStream time_base. if (pkt.pts != int64_t(AV_NOPTS_VALUE)) pkt.pts = av_rescale_q(pkt.pts, mEncAudioCodecCtx->time_base, mEncAudioStream->time_base); if (pkt.dts != int64_t(AV_NOPTS_VALUE)) pkt.dts = av_rescale_q(pkt.dts, mEncAudioCodecCtx->time_base, mEncAudioStream->time_base); //wxLogDebug(wxT("FFmpeg : (%d) Writing audio frame with PTS: %lld."), mEncAudioCodecCtx->frame_number, (long long) pkt.pts); pkt.stream_index = mEncAudioStream->index; // Write the encoded audio frame to the output file. if ((ret = av_interleaved_write_frame(mEncFormatCtx, &pkt)) < 0) { wxLogError(wxT("FFmpeg : ERROR - Failed to write audio frame to file.")); return false; } av_free_packet(&pkt); } return true; }
status_t AVCodecEncoder::_EncodeAudio(const void* _buffer, int64 frameCount, media_encode_info* info) { TRACE("AVCodecEncoder::_EncodeAudio(%p, %lld, %p)\n", _buffer, frameCount, info); if (fChunkBuffer == NULL) return B_NO_MEMORY; status_t ret = B_OK; const uint8* buffer = reinterpret_cast<const uint8*>(_buffer); size_t inputSampleSize = fInputFormat.u.raw_audio.format & media_raw_audio_format::B_AUDIO_SIZE_MASK; size_t inputFrameSize = inputSampleSize * fInputFormat.u.raw_audio.channel_count; size_t bufferSize = frameCount * inputFrameSize; bufferSize = min_c(bufferSize, kDefaultChunkBufferSize); if (fContext->frame_size > 1) { // Encoded audio. Things work differently from raw audio. We need // the fAudioFifo to pipe data. if (av_fifo_realloc2(fAudioFifo, av_fifo_size(fAudioFifo) + bufferSize) < 0) { TRACE(" av_fifo_realloc2() failed\n"); return B_NO_MEMORY; } av_fifo_generic_write(fAudioFifo, const_cast<uint8*>(buffer), bufferSize, NULL); int frameBytes = fContext->frame_size * inputFrameSize; uint8* tempBuffer = new(std::nothrow) uint8[frameBytes]; if (tempBuffer == NULL) return B_NO_MEMORY; // Encode as many chunks as can be read from the FIFO. while (av_fifo_size(fAudioFifo) >= frameBytes) { av_fifo_generic_read(fAudioFifo, tempBuffer, frameBytes, NULL); ret = _EncodeAudio(tempBuffer, frameBytes, fContext->frame_size, info); if (ret != B_OK) break; } delete[] tempBuffer; } else { // Raw audio. The number of bytes returned from avcodec_encode_audio() // is always the same as the number of input bytes. return _EncodeAudio(buffer, bufferSize, frameCount, info); } return ret; }
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 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); }
int av_fifo_grow(AVFifoBuffer *f, unsigned int size) { unsigned int old_size = f->end - f->buffer; if(size + (unsigned)av_fifo_size(f) < size) return AVERROR(EINVAL); size += av_fifo_size(f); if (old_size < size) return av_fifo_realloc2(f, FFMAX(size, 2*size)); 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; }
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; }
int av_audio_fifo_realloc(AVAudioFifo *af, int nb_samples) { int i, ret, buf_size; if ((ret = av_samples_get_buffer_size(&buf_size, af->channels, nb_samples, af->sample_fmt, 1)) < 0) return ret; for (i = 0; i < af->nb_buffers; i++) { if ((ret = av_fifo_realloc2(af->buf[i], buf_size)) < 0) return ret; } af->allocated_samples = nb_samples; return 0; }
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 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); }
int ff_audio_rechunk_interleave(AVFormatContext *s, AVPacket *out, AVPacket *pkt, int flush, int (*get_packet)(AVFormatContext *, AVPacket *, AVPacket *, int), int (*compare_ts)(AVFormatContext *, AVPacket *, AVPacket *)) { int i, ret; if (pkt) { AVStream *st = s->streams[pkt->stream_index]; AudioInterleaveContext *aic = st->priv_data; if (st->codec->codec_type == AVMEDIA_TYPE_AUDIO) { unsigned new_size = av_fifo_size(aic->fifo) + pkt->size; if (new_size > aic->fifo_size) { if (av_fifo_realloc2(aic->fifo, new_size) < 0) return AVERROR(ENOMEM); aic->fifo_size = new_size; } av_fifo_generic_write(aic->fifo, pkt->data, pkt->size, NULL); } else { // rewrite pts and dts to be decoded time line position pkt->pts = pkt->dts = aic->dts; aic->dts += pkt->duration; if ((ret = ff_interleave_add_packet(s, pkt, compare_ts)) < 0) return ret; } pkt = NULL; } for (i = 0; i < s->nb_streams; i++) { AVStream *st = s->streams[i]; if (st->codec->codec_type == AVMEDIA_TYPE_AUDIO) { AVPacket new_pkt = { 0 }; while ((ret = interleave_new_audio_packet(s, &new_pkt, i, flush)) > 0) { if ((ret = ff_interleave_add_packet(s, &new_pkt, compare_ts)) < 0) return ret; } if (ret < 0) return ret; } } return get_packet(s, out, NULL, flush); }
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; }
static void *start_smoothing( void *ptr ) { obe_t *h = ptr; int num_muxed_data = 0, buffer_complete = 0; int64_t start_clock = -1, start_pcr, end_pcr, temporal_vbv_size = 0, cur_pcr; obe_muxed_data_t **muxed_data = NULL, *start_data, *end_data; AVFifoBuffer *fifo_data = NULL, *fifo_pcr = NULL; uint8_t *output_buf; struct sched_param param = {0}; param.sched_priority = 99; pthread_setschedparam( pthread_self(), SCHED_FIFO, ¶m ); /* This thread buffers one VBV worth of frames */ fifo_data = av_fifo_alloc( TS_PACKETS_SIZE ); if( !fifo_data ) { fprintf( stderr, "[mux-smoothing] Could not allocate data fifo" ); return NULL; } fifo_pcr = av_fifo_alloc( 7 * sizeof(int64_t) ); if( !fifo_pcr ) { fprintf( stderr, "[mux-smoothing] Could not allocate pcr fifo" ); return NULL; } if( h->obe_system == OBE_SYSTEM_TYPE_GENERIC ) { for( int i = 0; i < h->num_encoders; i++ ) { if( h->encoders[i]->is_video ) { pthread_mutex_lock( &h->encoders[i]->queue.mutex ); while( !h->encoders[i]->is_ready ) pthread_cond_wait( &h->encoders[i]->queue.in_cv, &h->encoders[i]->queue.mutex ); x264_param_t *params = h->encoders[i]->encoder_params; temporal_vbv_size = av_rescale_q_rnd( (int64_t)params->rc.i_vbv_buffer_size * params->rc.f_vbv_buffer_init, (AVRational){1, params->rc.i_vbv_max_bitrate }, (AVRational){ 1, OBE_CLOCK }, AV_ROUND_UP ); pthread_mutex_unlock( &h->encoders[i]->queue.mutex ); break; } } } while( 1 ) { pthread_mutex_lock( &h->mux_smoothing_queue.mutex ); while( h->mux_smoothing_queue.size == num_muxed_data && !h->cancel_mux_smoothing_thread ) pthread_cond_wait( &h->mux_smoothing_queue.in_cv, &h->mux_smoothing_queue.mutex ); if( h->cancel_mux_smoothing_thread ) { pthread_mutex_unlock( &h->mux_smoothing_queue.mutex ); break; } num_muxed_data = h->mux_smoothing_queue.size; /* Refill the buffer after a drop */ pthread_mutex_lock( &h->drop_mutex ); if( h->mux_drop ) { syslog( LOG_INFO, "Mux smoothing buffer reset\n" ); h->mux_drop = 0; av_fifo_reset( fifo_data ); av_fifo_reset( fifo_pcr ); buffer_complete = 0; start_clock = -1; } pthread_mutex_unlock( &h->drop_mutex ); if( !buffer_complete ) { start_data = h->mux_smoothing_queue.queue[0]; end_data = h->mux_smoothing_queue.queue[num_muxed_data-1]; start_pcr = start_data->pcr_list[0]; end_pcr = end_data->pcr_list[(end_data->len / 188)-1]; if( end_pcr - start_pcr >= temporal_vbv_size ) { buffer_complete = 1; start_clock = -1; } else { pthread_mutex_unlock( &h->mux_smoothing_queue.mutex ); continue; } } //printf("\n mux smoothed frames %i \n", num_muxed_data ); muxed_data = malloc( num_muxed_data * sizeof(*muxed_data) ); if( !muxed_data ) { pthread_mutex_unlock( &h->output_queue.mutex ); syslog( LOG_ERR, "Malloc failed\n" ); return NULL; } memcpy( muxed_data, h->mux_smoothing_queue.queue, num_muxed_data * sizeof(*muxed_data) ); pthread_mutex_unlock( &h->mux_smoothing_queue.mutex ); for( int i = 0; i < num_muxed_data; i++ ) { if( av_fifo_realloc2( fifo_data, av_fifo_size( fifo_data ) + muxed_data[i]->len ) < 0 ) { syslog( LOG_ERR, "Malloc failed\n" ); return NULL; } av_fifo_generic_write( fifo_data, muxed_data[i]->data, muxed_data[i]->len, NULL ); if( av_fifo_realloc2( fifo_pcr, av_fifo_size( fifo_pcr ) + ((muxed_data[i]->len * sizeof(int64_t)) / 188) ) < 0 ) { syslog( LOG_ERR, "Malloc failed\n" ); return NULL; } av_fifo_generic_write( fifo_pcr, muxed_data[i]->pcr_list, (muxed_data[i]->len * sizeof(int64_t)) / 188, NULL ); remove_from_queue( &h->mux_smoothing_queue ); destroy_muxed_data( muxed_data[i] ); } free( muxed_data ); muxed_data = NULL; num_muxed_data = 0; while( av_fifo_size( fifo_data ) >= TS_PACKETS_SIZE ) { output_buf = malloc( TS_PACKETS_SIZE + 7 * sizeof(int64_t) ); if( !output_buf ) { syslog( LOG_ERR, "Malloc failed\n" ); return NULL; } av_fifo_generic_read( fifo_pcr, output_buf, 7 * sizeof(int64_t), NULL ); av_fifo_generic_read( fifo_data, &output_buf[7 * sizeof(int64_t)], TS_PACKETS_SIZE, NULL ); cur_pcr = AV_RN64( output_buf ); if( start_clock != -1 ) { sleep_input_clock( h, cur_pcr - start_pcr + start_clock ); } if( start_clock == -1 ) { start_clock = get_input_clock_in_mpeg_ticks( h ); start_pcr = cur_pcr; } if( add_to_queue( &h->output_queue, output_buf ) < 0 ) return NULL; output_buf = NULL; } } av_fifo_free( fifo_data ); av_fifo_free( fifo_pcr ); return NULL; }
static int mediacodec_decode_frame(AVCodecContext *avctx, void *data, int *got_frame, AVPacket *avpkt) { MediaCodecH264DecContext *s = avctx->priv_data; AVFrame *frame = data; int ret; /* buffer the input packet */ if (avpkt->size) { AVPacket input_pkt = { 0 }; if (av_fifo_space(s->fifo) < sizeof(input_pkt)) { ret = av_fifo_realloc2(s->fifo, av_fifo_size(s->fifo) + sizeof(input_pkt)); if (ret < 0) return ret; } ret = av_packet_ref(&input_pkt, avpkt); if (ret < 0) return ret; av_fifo_generic_write(s->fifo, &input_pkt, sizeof(input_pkt), NULL); } /* process buffered data */ while (!*got_frame) { /* prepare the input data -- convert to Annex B if needed */ if (s->filtered_pkt.size <= 0) { AVPacket input_pkt = { 0 }; av_packet_unref(&s->filtered_pkt); /* no more data */ if (av_fifo_size(s->fifo) < sizeof(AVPacket)) { return avpkt->size ? avpkt->size : ff_mediacodec_dec_decode(avctx, &s->ctx, frame, got_frame, avpkt); } av_fifo_generic_read(s->fifo, &input_pkt, sizeof(input_pkt), NULL); ret = av_bsf_send_packet(s->bsf, &input_pkt); if (ret < 0) { return ret; } ret = av_bsf_receive_packet(s->bsf, &s->filtered_pkt); if (ret == AVERROR(EAGAIN)) { goto done; } /* h264_mp4toannexb is used here and does not requires flushing */ av_assert0(ret != AVERROR_EOF); if (ret < 0) { return ret; } } ret = mediacodec_process_data(avctx, frame, got_frame, &s->filtered_pkt); if (ret < 0) return ret; s->filtered_pkt.size -= ret; s->filtered_pkt.data += ret; } done: return avpkt->size; }
void av_fifo_realloc(AVFifoBuffer *f, unsigned int new_size) { av_fifo_realloc2(f, new_size); }
int av_vsrc_buffer_add_video_buffer_ref(AVFilterContext *buffer_filter, AVFilterBufferRef *picref, int flags) { BufferSourceContext *c = buffer_filter->priv; AVFilterLink *outlink = buffer_filter->outputs[0]; AVFilterBufferRef *buf; int ret; if (!picref) { c->eof = 1; return 0; } else if (c->eof) return AVERROR(EINVAL); if (!av_fifo_space(c->fifo) && (ret = av_fifo_realloc2(c->fifo, av_fifo_size(c->fifo) + sizeof(buf))) < 0) return ret; if (picref->video->w != c->w || picref->video->h != c->h || picref->format != c->pix_fmt) { AVFilterContext *scale = buffer_filter->outputs[0]->dst; AVFilterLink *link; char scale_param[1024]; av_log(buffer_filter, AV_LOG_INFO, "Buffer video input changed from size:%dx%d fmt:%s to size:%dx%d fmt:%s\n", c->w, c->h, av_pix_fmt_descriptors[c->pix_fmt].name, picref->video->w, picref->video->h, av_pix_fmt_descriptors[picref->format].name); if (!scale || strcmp(scale->filter->name, "scale")) { AVFilter *f = avfilter_get_by_name("scale"); av_log(buffer_filter, AV_LOG_INFO, "Inserting scaler filter\n"); if ((ret = avfilter_open(&scale, f, "Input equalizer")) < 0) return ret; c->scale = scale; snprintf(scale_param, sizeof(scale_param)-1, "%d:%d:%s", c->w, c->h, c->sws_param); if ((ret = avfilter_init_filter(scale, scale_param, NULL)) < 0) { return ret; } if ((ret = avfilter_insert_filter(buffer_filter->outputs[0], scale, 0, 0)) < 0) { return ret; } scale->outputs[0]->time_base = scale->inputs[0]->time_base; scale->outputs[0]->format= c->pix_fmt; } else if (!strcmp(scale->filter->name, "scale")) { snprintf(scale_param, sizeof(scale_param)-1, "%d:%d:%s", scale->outputs[0]->w, scale->outputs[0]->h, c->sws_param); scale->filter->init(scale, scale_param, NULL); } c->pix_fmt = scale->inputs[0]->format = picref->format; c->w = scale->inputs[0]->w = picref->video->w; c->h = scale->inputs[0]->h = picref->video->h; link = scale->outputs[0]; if ((ret = link->srcpad->config_props(link)) < 0) return ret; } buf = avfilter_get_video_buffer(outlink, AV_PERM_WRITE, picref->video->w, picref->video->h); av_image_copy(buf->data, buf->linesize, (void*)picref->data, picref->linesize, picref->format, picref->video->w, picref->video->h); avfilter_copy_buffer_ref_props(buf, picref); if ((ret = av_fifo_generic_write(c->fifo, &buf, sizeof(buf), NULL)) < 0) { avfilter_unref_buffer(buf); return ret; } return 0; }
static int av_buffersrc_add_frame_internal(AVFilterContext *ctx, AVFrame *frame, int flags) { BufferSourceContext *s = ctx->priv; AVFrame *copy; int refcounted, ret; s->nb_failed_requests = 0; if (!frame) { s->eof = 1; return 0; } else if (s->eof) return AVERROR(EINVAL); refcounted = !!frame->buf[0]; if (!(flags & AV_BUFFERSRC_FLAG_NO_CHECK_FORMAT)) { 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: /* For layouts unknown on input but known on link after negotiation. */ if (!frame->channel_layout) frame->channel_layout = s->channel_layout; CHECK_AUDIO_PARAM_CHANGE(ctx, s, frame->sample_rate, frame->channel_layout, av_frame_get_channels(frame), 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; } if ((flags & AV_BUFFERSRC_FLAG_PUSH)) if ((ret = ctx->output_pads[0].request_frame(ctx->outputs[0])) < 0) return ret; return 0; }
static void *start_encoder( void *ptr ) { obe_aud_enc_params_t *enc_params = ptr; obe_t *h = enc_params->h; obe_encoder_t *encoder = enc_params->encoder; obe_output_stream_t *stream = enc_params->stream; obe_raw_frame_t *raw_frame; obe_coded_frame_t *coded_frame; void *audio_buf = NULL; int64_t cur_pts = -1, pts_increment; int i, frame_size, ret, got_pkt, num_frames = 0, total_size = 0, audio_buf_len; AVFifoBuffer *out_fifo = NULL; AVAudioResampleContext *avr = NULL; AVPacket pkt; AVCodecContext *codec = NULL; AVFrame *frame = NULL; AVDictionary *opts = NULL; char is_latm[2]; avcodec_register_all(); codec = avcodec_alloc_context3( NULL ); if( !codec ) { fprintf( stderr, "Malloc failed\n" ); goto finish; } for( i = 0; lavc_encoders[i].obe_name != -1; i++ ) { if( lavc_encoders[i].obe_name == stream->stream_format ) break; } if( lavc_encoders[i].obe_name == -1 ) { fprintf( stderr, "[lavc] Could not find encoder1\n" ); goto finish; } AVCodec *enc = avcodec_find_encoder( lavc_encoders[i].lavc_name ); if( !enc ) { fprintf( stderr, "[lavc] Could not find encoder2\n" ); goto finish; } if( enc->sample_fmts[0] == -1 ) { fprintf( stderr, "[lavc] No valid sample formats\n" ); goto finish; } codec->sample_rate = enc_params->sample_rate; codec->bit_rate = stream->bitrate * 1000; codec->sample_fmt = enc->sample_fmts[0]; codec->channels = av_get_channel_layout_nb_channels( stream->channel_layout ); codec->channel_layout = stream->channel_layout; codec->time_base.num = 1; codec->time_base.den = OBE_CLOCK; codec->profile = stream->aac_opts.aac_profile == AAC_HE_V2 ? FF_PROFILE_AAC_HE_V2 : stream->aac_opts.aac_profile == AAC_HE_V1 ? FF_PROFILE_AAC_HE : FF_PROFILE_AAC_LOW; snprintf( is_latm, sizeof(is_latm), "%i", stream->aac_opts.latm_output ); av_dict_set( &opts, "latm", is_latm, 0 ); av_dict_set( &opts, "header_period", "2", 0 ); if( avcodec_open2( codec, enc, &opts ) < 0 ) { fprintf( stderr, "[lavc] Could not open encoder\n" ); goto finish; } avr = avresample_alloc_context(); if( !avr ) { fprintf( stderr, "Malloc failed\n" ); goto finish; } av_opt_set_int( avr, "in_channel_layout", codec->channel_layout, 0 ); av_opt_set_int( avr, "in_sample_fmt", enc_params->input_sample_format, 0 ); av_opt_set_int( avr, "in_sample_rate", enc_params->sample_rate, 0 ); av_opt_set_int( avr, "out_channel_layout", codec->channel_layout, 0 ); av_opt_set_int( avr, "out_sample_fmt", codec->sample_fmt, 0 ); av_opt_set_int( avr, "dither_method", AV_RESAMPLE_DITHER_TRIANGULAR_NS, 0 ); if( avresample_open( avr ) < 0 ) { fprintf( stderr, "Could not open AVResample\n" ); goto finish; } /* The number of samples per E-AC3 frame is unknown until the encoder is ready */ if( stream->stream_format == AUDIO_E_AC_3 || stream->stream_format == AUDIO_AAC ) { pthread_mutex_lock( &encoder->queue.mutex ); encoder->is_ready = 1; encoder->num_samples = codec->frame_size; /* Broadcast because input and muxer can be stuck waiting for encoder */ pthread_cond_broadcast( &encoder->queue.in_cv ); pthread_mutex_unlock( &encoder->queue.mutex ); } frame_size = (double)codec->frame_size * 125 * stream->bitrate * enc_params->frames_per_pes / enc_params->sample_rate; /* NB: libfdk-aac already doubles the frame size appropriately */ pts_increment = (double)codec->frame_size * OBE_CLOCK * enc_params->frames_per_pes / enc_params->sample_rate; out_fifo = av_fifo_alloc( frame_size ); if( !out_fifo ) { fprintf( stderr, "Malloc failed\n" ); goto finish; } audio_buf_len = codec->frame_size * av_get_bytes_per_sample( codec->sample_fmt ) * codec->channels; audio_buf = av_malloc( audio_buf_len ); if( !audio_buf ) { fprintf( stderr, "Malloc failed\n" ); goto finish; } frame = avcodec_alloc_frame(); if( !frame ) { fprintf( stderr, "Could not allocate frame\n" ); goto finish; } while( 1 ) { /* TODO: detect bitrate or channel reconfig */ pthread_mutex_lock( &encoder->queue.mutex ); while( !encoder->queue.size && !encoder->cancel_thread ) pthread_cond_wait( &encoder->queue.in_cv, &encoder->queue.mutex ); if( encoder->cancel_thread ) { pthread_mutex_unlock( &encoder->queue.mutex ); goto finish; } raw_frame = encoder->queue.queue[0]; pthread_mutex_unlock( &encoder->queue.mutex ); if( cur_pts == -1 ) cur_pts = raw_frame->pts; if( avresample_convert( avr, NULL, 0, raw_frame->audio_frame.num_samples, raw_frame->audio_frame.audio_data, raw_frame->audio_frame.linesize, raw_frame->audio_frame.num_samples ) < 0 ) { syslog( LOG_ERR, "[lavc] Sample format conversion failed\n" ); break; } raw_frame->release_data( raw_frame ); raw_frame->release_frame( raw_frame ); remove_from_queue( &encoder->queue ); while( avresample_available( avr ) >= codec->frame_size ) { got_pkt = 0; avcodec_get_frame_defaults( frame ); frame->nb_samples = codec->frame_size; avresample_read( avr, &audio_buf, codec->frame_size ); if( avcodec_fill_audio_frame( frame, codec->channels, codec->sample_fmt, audio_buf, audio_buf_len, 0 ) < 0 ) { syslog( LOG_ERR, "[lavc] Could not fill audio frame\n" ); break; } av_init_packet( &pkt ); pkt.data = NULL; pkt.size = 0; ret = avcodec_encode_audio2( codec, &pkt, frame, &got_pkt ); if( ret < 0 ) { syslog( LOG_ERR, "[lavc] Audio encoding failed\n" ); goto finish; } if( !got_pkt ) continue; total_size += pkt.size; num_frames++; if( av_fifo_realloc2( out_fifo, av_fifo_size( out_fifo ) + pkt.size ) < 0 ) { syslog( LOG_ERR, "Malloc failed\n" ); break; } av_fifo_generic_write( out_fifo, pkt.data, pkt.size, NULL ); obe_free_packet( &pkt ); if( num_frames == enc_params->frames_per_pes ) { coded_frame = new_coded_frame( encoder->output_stream_id, total_size ); if( !coded_frame ) { syslog( LOG_ERR, "Malloc failed\n" ); goto finish; } av_fifo_generic_read( out_fifo, coded_frame->data, total_size, NULL ); coded_frame->pts = cur_pts; coded_frame->random_access = 1; /* Every frame output is a random access point */ add_to_queue( &h->mux_queue, coded_frame ); /* We need to generate PTS because frame sizes have changed */ cur_pts += pts_increment; total_size = num_frames = 0; } } } finish: if( frame ) avcodec_free_frame( &frame ); if( audio_buf ) av_free( audio_buf ); if( out_fifo ) av_fifo_free( out_fifo ); if( avr ) avresample_free( &avr ); if( codec ) { avcodec_close( codec ); av_free( codec ); } free( enc_params ); return NULL; }