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 libschroedinger_decode_frame(AVCodecContext *avctx, void *data, int *got_frame, AVPacket *avpkt) { const uint8_t *buf = avpkt->data; int buf_size = avpkt->size; int64_t pts = avpkt->pts; SchroTag *tag; SchroDecoderParams *p_schro_params = avctx->priv_data; SchroDecoder *decoder = p_schro_params->decoder; SchroBuffer *enc_buf; SchroFrame* frame; AVFrame *avframe = data; int state; int go = 1; int outer = 1; SchroParseUnitContext parse_ctx; LibSchroFrameContext *framewithpts = NULL; *got_frame = 0; parse_context_init(&parse_ctx, buf, buf_size); if (!buf_size) { if (!p_schro_params->eos_signalled) { state = schro_decoder_push_end_of_stream(decoder); p_schro_params->eos_signalled = 1; } } /* Loop through all the individual parse units in the input buffer */ do { if ((enc_buf = find_next_parse_unit(&parse_ctx))) { /* Set Schrotag with the pts to be recovered after decoding*/ enc_buf->tag = schro_tag_new(av_malloc(sizeof(int64_t)), av_free); if (!enc_buf->tag->value) { av_log(avctx, AV_LOG_ERROR, "Unable to allocate SchroTag\n"); return AVERROR(ENOMEM); } AV_WN(64, enc_buf->tag->value, pts); /* Push buffer into decoder. */ if (SCHRO_PARSE_CODE_IS_PICTURE(enc_buf->data[4]) && SCHRO_PARSE_CODE_NUM_REFS(enc_buf->data[4]) > 0) avctx->has_b_frames = 1; state = schro_decoder_push(decoder, enc_buf); if (state == SCHRO_DECODER_FIRST_ACCESS_UNIT) libschroedinger_handle_first_access_unit(avctx); go = 1; } else outer = 0; while (go) { /* Parse data and process result. */ state = schro_decoder_wait(decoder); switch (state) { case SCHRO_DECODER_FIRST_ACCESS_UNIT: libschroedinger_handle_first_access_unit(avctx); break; case SCHRO_DECODER_NEED_BITS: /* Need more input data - stop iterating over what we have. */ go = 0; break; case SCHRO_DECODER_NEED_FRAME: /* Decoder needs a frame - create one and push it in. */ frame = ff_create_schro_frame(avctx, p_schro_params->frame_format); if (!frame) return AVERROR(ENOMEM); schro_decoder_add_output_picture(decoder, frame); break; case SCHRO_DECODER_OK: /* Pull a frame out of the decoder. */ tag = schro_decoder_get_picture_tag(decoder); frame = schro_decoder_pull(decoder); if (frame) { /* Add relation between schroframe and pts. */ framewithpts = av_malloc(sizeof(LibSchroFrameContext)); if (!framewithpts) { av_log(avctx, AV_LOG_ERROR, "Unable to allocate FrameWithPts\n"); return AVERROR(ENOMEM); } framewithpts->frame = frame; framewithpts->pts = AV_RN64(tag->value); ff_schro_queue_push_back(&p_schro_params->dec_frame_queue, framewithpts); } break; case SCHRO_DECODER_EOS: go = 0; p_schro_params->eos_pulled = 1; schro_decoder_reset(decoder); outer = 0; break; case SCHRO_DECODER_ERROR: return -1; break; } } } while (outer); /* Grab next frame to be returned from the top of the queue. */ framewithpts = ff_schro_queue_pop(&p_schro_params->dec_frame_queue); if (framewithpts && framewithpts->frame) { int ret; if ((ret = ff_get_buffer(avctx, avframe, 0)) < 0) return ret; memcpy(avframe->data[0], framewithpts->frame->components[0].data, framewithpts->frame->components[0].length); memcpy(avframe->data[1], framewithpts->frame->components[1].data, framewithpts->frame->components[1].length); memcpy(avframe->data[2], framewithpts->frame->components[2].data, framewithpts->frame->components[2].length); /* Fill frame with current buffer data from Schroedinger. */ avframe->pkt_pts = framewithpts->pts; avframe->linesize[0] = framewithpts->frame->components[0].stride; avframe->linesize[1] = framewithpts->frame->components[1].stride; avframe->linesize[2] = framewithpts->frame->components[2].stride; *got_frame = 1; /* Now free the frame resources. */ libschroedinger_decode_frame_free(framewithpts->frame); av_free(framewithpts); } else { data = NULL; *got_frame = 0; } return buf_size; }
static void *open_output( void *ptr ) { obe_output_params_t *output_params = ptr; obe_t *h = output_params->h; struct ip_status status; hnd_t ip_handle = NULL; int num_muxed_data = 0; uint8_t **muxed_data; obe_udp_opts_t udp_opts; struct sched_param param = {0}; param.sched_priority = 99; pthread_setschedparam( pthread_self(), SCHED_FIFO, ¶m ); status.output_params = output_params; status.ip_handle = &ip_handle; pthread_cleanup_push( close_output, (void*)&status ); udp_populate_opts( &udp_opts, output_params->output_opts.target ); if( output_params->output_opts.output == OUTPUT_RTP ) { if( rtp_open( &ip_handle, &udp_opts ) < 0 ) return NULL; } else { if( udp_open( &ip_handle, &udp_opts ) < 0 ) { fprintf( stderr, "[udp] Could not create udp output" ); return NULL; } } while( 1 ) { pthread_mutex_lock( &h->output_queue.mutex ); while( !h->output_queue.size && !h->cancel_output_thread ) { /* Often this cond_wait is not because of an underflow */ pthread_cond_wait( &h->output_queue.in_cv, &h->output_queue.mutex ); } if( h->cancel_output_thread ) { pthread_mutex_unlock( &h->output_queue.mutex ); break; } num_muxed_data = h->output_queue.size; 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->output_queue.queue, num_muxed_data * sizeof(*muxed_data) ); pthread_mutex_unlock( &h->output_queue.mutex ); // printf("\n START %i \n", num_muxed_data ); for( int i = 0; i < num_muxed_data; i++ ) { if( output_params->output_opts.output == OUTPUT_RTP ) { if( write_rtp_pkt( ip_handle, &muxed_data[i][7*sizeof(int64_t)], TS_PACKETS_SIZE, AV_RN64( muxed_data[i] ) ) < 0 ) syslog( LOG_ERR, "[rtp] Failed to write RTP packet\n" ); } else { if( udp_write( ip_handle, &muxed_data[i][7*sizeof(int64_t)], TS_PACKETS_SIZE ) < 0 ) syslog( LOG_ERR, "[udp] Failed to write UDP packet\n" ); } remove_from_queue( &h->output_queue ); free( muxed_data[i] ); } free( muxed_data ); muxed_data = NULL; } pthread_cleanup_pop( 1 ); return NULL; }
int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) { const uint64_t fuzz_tag = FUZZ_TAG; FuzzDataBuffer buffer; const uint8_t *last = data; const uint8_t *end = data + size; uint32_t it = 0; if (!c) c = AVCodecInitialize(FFMPEG_CODEC); // Done once. AVCodecContext* ctx = avcodec_alloc_context3(NULL); if (!ctx) error("Failed memory allocation"); ctx->max_pixels = 4096 * 4096; //To reduce false positive OOM and hangs int res = avcodec_open2(ctx, c, NULL); if (res < 0) return res; FDBCreate(&buffer); int got_frame; AVFrame *frame = av_frame_alloc(); if (!frame) error("Failed memory allocation"); // Read very simple container AVPacket avpkt; while (data < end && it < maxiteration) { // Search for the TAG while (data + sizeof(fuzz_tag) < end) { if (data[0] == (fuzz_tag & 0xFF) && AV_RN64(data) == fuzz_tag) break; data++; } if (data + sizeof(fuzz_tag) > end) data = end; FDBPrepare(&buffer, &avpkt, last, data - last); data += sizeof(fuzz_tag); last = data; // Iterate through all data while (avpkt.size > 0 && it++ < maxiteration) { av_frame_unref(frame); int ret = decode_handler(ctx, frame, &got_frame, &avpkt); if (it > 20) ctx->error_concealment = 0; if (ret <= 0 || ret > avpkt.size) break; if (ctx->codec_type != AVMEDIA_TYPE_AUDIO) ret = avpkt.size; avpkt.data += ret; avpkt.size -= ret; } } av_init_packet(&avpkt); avpkt.data = NULL; avpkt.size = 0; do { got_frame = 0; decode_handler(ctx, frame, &got_frame, &avpkt); } while (got_frame == 1 && it++ < maxiteration); av_frame_free(&frame); avcodec_free_context(&ctx); av_freep(&ctx); FDBDesroy(&buffer); return 0; }
int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) { const uint64_t fuzz_tag = FUZZ_TAG; FuzzDataBuffer buffer; const uint8_t *last = data; const uint8_t *end = data + size; uint32_t it = 0; int (*decode_handler)(AVCodecContext *avctx, AVFrame *picture, int *got_picture_ptr, const AVPacket *avpkt) = NULL; if (!c) { #ifdef FFMPEG_DECODER #define DECODER_SYMBOL0(CODEC) ff_##CODEC##_decoder #define DECODER_SYMBOL(CODEC) DECODER_SYMBOL0(CODEC) extern AVCodec DECODER_SYMBOL(FFMPEG_DECODER); avcodec_register(&DECODER_SYMBOL(FFMPEG_DECODER)); c = &DECODER_SYMBOL(FFMPEG_DECODER); #else avcodec_register_all(); c = AVCodecInitialize(FFMPEG_CODEC); // Done once. #endif av_log_set_level(AV_LOG_PANIC); } // Unsupported if (c->capabilities & AV_CODEC_CAP_HWACCEL_VDPAU) return 0; switch (c->type) { case AVMEDIA_TYPE_AUDIO : decode_handler = avcodec_decode_audio4; break; case AVMEDIA_TYPE_VIDEO : decode_handler = avcodec_decode_video2; break; case AVMEDIA_TYPE_SUBTITLE: decode_handler = subtitle_handler ; break; } AVCodecContext* ctx = avcodec_alloc_context3(NULL); if (!ctx) error("Failed memory allocation"); ctx->max_pixels = 4096 * 4096; //To reduce false positive OOM and hangs if (size > 1024) { GetByteContext gbc; bytestream2_init(&gbc, data + size - 1024, 1024); ctx->width = bytestream2_get_le32(&gbc); ctx->height = bytestream2_get_le32(&gbc); ctx->bit_rate = bytestream2_get_le64(&gbc); ctx->bits_per_coded_sample = bytestream2_get_le32(&gbc); if (av_image_check_size(ctx->width, ctx->height, 0, ctx)) ctx->width = ctx->height = 0; size -= 1024; } int res = avcodec_open2(ctx, c, NULL); if (res < 0) { av_free(ctx); return 0; // Failure of avcodec_open2() does not imply that a issue was found } FDBCreate(&buffer); int got_frame; AVFrame *frame = av_frame_alloc(); if (!frame) error("Failed memory allocation"); // Read very simple container AVPacket avpkt; while (data < end && it < maxiteration) { // Search for the TAG while (data + sizeof(fuzz_tag) < end) { if (data[0] == (fuzz_tag & 0xFF) && AV_RN64(data) == fuzz_tag) break; data++; } if (data + sizeof(fuzz_tag) > end) data = end; FDBPrepare(&buffer, &avpkt, last, data - last); data += sizeof(fuzz_tag); last = data; // Iterate through all data while (avpkt.size > 0 && it++ < maxiteration) { av_frame_unref(frame); int ret = decode_handler(ctx, frame, &got_frame, &avpkt); if (it > 20) ctx->error_concealment = 0; if (ret <= 0 || ret > avpkt.size) break; if (ctx->codec_type != AVMEDIA_TYPE_AUDIO) ret = avpkt.size; avpkt.data += ret; avpkt.size -= ret; } } av_init_packet(&avpkt); avpkt.data = NULL; avpkt.size = 0; do { got_frame = 0; decode_handler(ctx, frame, &got_frame, &avpkt); } while (got_frame == 1 && it++ < maxiteration); av_frame_free(&frame); avcodec_free_context(&ctx); av_freep(&ctx); FDBDesroy(&buffer); return 0; }