static double get_clock(Clock *c) { //if (*c->queue_serial != c->serial) // return NAN; if (c->paused) { return c->pts; } else { double time = av_gettime_relative() / 1000000.0; return c->pts; // return c->pts_drift + time - (time - c->last_updated) * (1.0 - c->speed); } }
static int sap_write_packet(AVFormatContext *s, AVPacket *pkt) { AVFormatContext *rtpctx; struct SAPState *sap = s->priv_data; int64_t now = av_gettime_relative(); if (!sap->last_time || now - sap->last_time > 5000000) { int ret = ffurl_write(sap->ann_fd, sap->ann, sap->ann_size); /* Don't abort even if we get "Destination unreachable" */ if (ret < 0 && ret != AVERROR(ECONNREFUSED)) return ret; sap->last_time = now; } rtpctx = s->streams[pkt->stream_index]->priv_data; return ff_write_chained(rtpctx, 0, pkt, s); }
int VideoDecoder::video_thread(void *arg) { VideoState *is = (VideoState *) arg; AVStreamsParser* ps = is->getAVStreamsParser(); AVFrame *frame = av_frame_alloc(); double pts; double duration; int ret; AVRational tb = ps->video_st->time_base; AVRational frame_rate = av_guess_frame_rate(ps->ic, ps->video_st, NULL); #if CONFIG_AVFILTER AVFilterGraph *graph = avfilter_graph_alloc(); AVFilterContext *filt_out = NULL, *filt_in = NULL; int last_w = 0; int last_h = 0; enum AVPixelFormat last_format = (AVPixelFormat) (-2); int last_serial = -1; int last_vfilter_idx = 0; if (!graph) { av_frame_free(&frame); return AVERROR(ENOMEM); } #endif if (!frame) { #if CONFIG_AVFILTER avfilter_graph_free(&graph); #endif return AVERROR(ENOMEM); } for (;;) { ret = is->viddec().get_video_frame(is, frame); if (ret < 0) goto the_end; if (!ret) continue; #if CONFIG_AVFILTER if ( last_w != frame->width || last_h != frame->height || last_format != frame->format || last_serial != is->viddec().pkt_serial || last_vfilter_idx != is->vfilter_idx) { av_log(NULL, AV_LOG_DEBUG, "Video frame changed from size:%dx%d format:%s serial:%d to size:%dx%d format:%s serial:%d\n", last_w, last_h, (const char *)av_x_if_null(av_get_pix_fmt_name(last_format), "none"), last_serial, frame->width, frame->height, (const char *)av_x_if_null(av_get_pix_fmt_name((AVPixelFormat)frame->format), "none"), is->viddec().pkt_serial); avfilter_graph_free(&graph); graph = avfilter_graph_alloc(); if ((ret = configure_video_filters(graph, is,gOptions.vfilters_list ? gOptions.vfilters_list[is->vfilter_idx] : NULL, frame)) < 0) { SDL_Event event; event.type = FF_QUIT_EVENT; event.user.data1 = is; SDL_PushEvent(&event); goto the_end; } filt_in = is->in_video_filter; filt_out = is->out_video_filter; last_w = frame->width; last_h = frame->height; last_format = (AVPixelFormat) frame->format; last_serial = is->viddec().pkt_serial; last_vfilter_idx = is->vfilter_idx; frame_rate = filt_out->inputs[0]->frame_rate; } ret = av_buffersrc_add_frame(filt_in, frame); if (ret < 0) goto the_end; while (ret >= 0) { is->frame_last_returned_time = av_gettime_relative() / 1000000.0; ret = av_buffersink_get_frame_flags(filt_out, frame, 0); if (ret < 0) { if (ret == AVERROR_EOF) is->viddec().finished = is->viddec().pkt_serial; ret = 0; break; } is->frame_last_filter_delay = av_gettime_relative() / 1000000.0 - is->frame_last_returned_time; if (fabs(is->frame_last_filter_delay) > AV_NOSYNC_THRESHOLD / 10.0) is->frame_last_filter_delay = 0; tb = filt_out->inputs[0]->time_base; #endif duration = (frame_rate.num && frame_rate.den ? av_q2d((AVRational){frame_rate.den, frame_rate.num}) : 0); pts = (frame->pts == AV_NOPTS_VALUE) ? NAN : frame->pts * av_q2d(tb); ret = queue_picture(is, frame, pts, duration, av_frame_get_pkt_pos(frame), is->viddec().pkt_serial); av_frame_unref(frame); #if CONFIG_AVFILTER } #endif if (ret < 0) goto the_end; } the_end: #if CONFIG_AVFILTER avfilter_graph_free(&graph); #endif av_frame_free(&frame); return 0; }
static int read_data(void *opaque, uint8_t *buf, int buf_size) { struct variant *v = opaque; HLSContext *c = v->parent->priv_data; int ret, i; restart: if (!v->input) { /* If this is a live stream and the reload interval has elapsed since * the last playlist reload, reload the variant playlists now. */ int64_t reload_interval = v->n_segments > 0 ? v->segments[v->n_segments - 1]->duration : v->target_duration; reload: if (!v->finished && av_gettime_relative() - v->last_load_time >= reload_interval) { if ((ret = parse_playlist(c, v->url, v, NULL)) < 0) return ret; /* If we need to reload the playlist again below (if * there's still no more segments), switch to a reload * interval of half the target duration. */ reload_interval = v->target_duration / 2; } if (v->cur_seq_no < v->start_seq_no) { av_log(NULL, AV_LOG_WARNING, "skipping %d segments ahead, expired from playlists\n", v->start_seq_no - v->cur_seq_no); v->cur_seq_no = v->start_seq_no; } if (v->cur_seq_no >= v->start_seq_no + v->n_segments) { if (v->finished) return AVERROR_EOF; while (av_gettime_relative() - v->last_load_time < reload_interval) { if (ff_check_interrupt(c->interrupt_callback)) return AVERROR_EXIT; av_usleep(100*1000); } /* Enough time has elapsed since the last reload */ goto reload; } ret = open_input(v); if (ret < 0) return ret; } ret = ffurl_read(v->input, buf, buf_size); if (ret > 0) return ret; ffurl_close(v->input); v->input = NULL; v->cur_seq_no++; c->end_of_segment = 1; c->cur_seq_no = v->cur_seq_no; if (v->ctx && v->ctx->nb_streams && v->parent->nb_streams >= v->stream_offset + v->ctx->nb_streams) { v->needed = 0; for (i = v->stream_offset; i < v->stream_offset + v->ctx->nb_streams; i++) { if (v->parent->streams[i]->discard < AVDISCARD_ALL) v->needed = 1; } } if (!v->needed) { av_log(v->parent, AV_LOG_INFO, "No longer receiving variant %d\n", v->index); return AVERROR_EOF; } goto restart; }
static int parse_playlist(HLSContext *c, const char *url, struct variant *var, AVIOContext *in) { int ret = 0, is_segment = 0, is_variant = 0, bandwidth = 0; int64_t duration = 0; enum KeyType key_type = KEY_NONE; uint8_t iv[16] = ""; int has_iv = 0; char key[MAX_URL_SIZE] = ""; char line[1024]; const char *ptr; int close_in = 0; uint8_t *new_url = NULL; if (!in) { ret = open_in(c, &in, url); if (ret < 0) return ret; close_in = 1; } if (av_opt_get(in, "location", AV_OPT_SEARCH_CHILDREN, &new_url) >= 0) url = new_url; read_chomp_line(in, line, sizeof(line)); if (strcmp(line, "#EXTM3U")) { ret = AVERROR_INVALIDDATA; goto fail; } if (var) { free_segment_list(var); var->finished = 0; } while (!in->eof_reached) { read_chomp_line(in, line, sizeof(line)); if (av_strstart(line, "#EXT-X-STREAM-INF:", &ptr)) { struct variant_info info = {{0}}; is_variant = 1; ff_parse_key_value(ptr, (ff_parse_key_val_cb) handle_variant_args, &info); bandwidth = atoi(info.bandwidth); } else if (av_strstart(line, "#EXT-X-KEY:", &ptr)) { struct key_info info = {{0}}; ff_parse_key_value(ptr, (ff_parse_key_val_cb) handle_key_args, &info); key_type = KEY_NONE; has_iv = 0; if (!strcmp(info.method, "AES-128")) key_type = KEY_AES_128; if (!strncmp(info.iv, "0x", 2) || !strncmp(info.iv, "0X", 2)) { ff_hex_to_data(iv, info.iv + 2); has_iv = 1; } av_strlcpy(key, info.uri, sizeof(key)); } else if (av_strstart(line, "#EXT-X-TARGETDURATION:", &ptr)) { if (!var) { var = new_variant(c, 0, url, NULL); if (!var) { ret = AVERROR(ENOMEM); goto fail; } } var->target_duration = atoi(ptr) * AV_TIME_BASE; } else if (av_strstart(line, "#EXT-X-MEDIA-SEQUENCE:", &ptr)) { if (!var) { var = new_variant(c, 0, url, NULL); if (!var) { ret = AVERROR(ENOMEM); goto fail; } } var->start_seq_no = atoi(ptr); } else if (av_strstart(line, "#EXT-X-ENDLIST", &ptr)) { if (var) var->finished = 1; } else if (av_strstart(line, "#EXTINF:", &ptr)) { is_segment = 1; duration = atof(ptr) * AV_TIME_BASE; } else if (av_strstart(line, "#", NULL)) { continue; } else if (line[0]) { if (is_variant) { if (!new_variant(c, bandwidth, line, url)) { ret = AVERROR(ENOMEM); goto fail; } is_variant = 0; bandwidth = 0; } if (is_segment) { struct segment *seg; if (!var) { var = new_variant(c, 0, url, NULL); if (!var) { ret = AVERROR(ENOMEM); goto fail; } } seg = av_malloc(sizeof(struct segment)); if (!seg) { ret = AVERROR(ENOMEM); goto fail; } seg->duration = duration; seg->key_type = key_type; if (has_iv) { memcpy(seg->iv, iv, sizeof(iv)); } else { int seq = var->start_seq_no + var->n_segments; memset(seg->iv, 0, sizeof(seg->iv)); AV_WB32(seg->iv + 12, seq); } ff_make_absolute_url(seg->key, sizeof(seg->key), url, key); ff_make_absolute_url(seg->url, sizeof(seg->url), url, line); dynarray_add(&var->segments, &var->n_segments, seg); is_segment = 0; } } } if (var) var->last_load_time = av_gettime_relative(); fail: av_free(new_url); if (close_in) avio_close(in); return ret; }
static void set_clock(Clock *c, double pts, int serial) { double time = av_gettime_relative() / 1000000.0; set_clock_at(c, pts, serial, time); }
static int rtsp_read_packet(AVFormatContext *s, AVPacket *pkt) { RTSPState *rt = s->priv_data; int ret; RTSPMessageHeader reply1, *reply = &reply1; char cmd[1024]; retry: if (rt->server_type == RTSP_SERVER_REAL) { int i; for (i = 0; i < s->nb_streams; i++) rt->real_setup[i] = s->streams[i]->discard; if (!rt->need_subscription) { if (memcmp (rt->real_setup, rt->real_setup_cache, sizeof(enum AVDiscard) * s->nb_streams)) { snprintf(cmd, sizeof(cmd), "Unsubscribe: %s\r\n", rt->last_subscription); ff_rtsp_send_cmd(s, "SET_PARAMETER", rt->control_uri, cmd, reply, NULL); if (reply->status_code != RTSP_STATUS_OK) return ff_rtsp_averror(reply->status_code, AVERROR_INVALIDDATA); rt->need_subscription = 1; } } if (rt->need_subscription) { int r, rule_nr, first = 1; memcpy(rt->real_setup_cache, rt->real_setup, sizeof(enum AVDiscard) * s->nb_streams); rt->last_subscription[0] = 0; snprintf(cmd, sizeof(cmd), "Subscribe: "); for (i = 0; i < rt->nb_rtsp_streams; i++) { rule_nr = 0; for (r = 0; r < s->nb_streams; r++) { if (s->streams[r]->id == i) { if (s->streams[r]->discard != AVDISCARD_ALL) { if (!first) av_strlcat(rt->last_subscription, ",", sizeof(rt->last_subscription)); ff_rdt_subscribe_rule( rt->last_subscription, sizeof(rt->last_subscription), i, rule_nr); first = 0; } rule_nr++; } } } av_strlcatf(cmd, sizeof(cmd), "%s\r\n", rt->last_subscription); ff_rtsp_send_cmd(s, "SET_PARAMETER", rt->control_uri, cmd, reply, NULL); if (reply->status_code != RTSP_STATUS_OK) return ff_rtsp_averror(reply->status_code, AVERROR_INVALIDDATA); rt->need_subscription = 0; if (rt->state == RTSP_STATE_STREAMING) rtsp_read_play (s); } } ret = ff_rtsp_fetch_packet(s, pkt); if (ret < 0) { if (ret == AVERROR(ETIMEDOUT) && !rt->packets) { if (rt->lower_transport == RTSP_LOWER_TRANSPORT_UDP && rt->lower_transport_mask & (1 << RTSP_LOWER_TRANSPORT_TCP)) { RTSPMessageHeader reply1, *reply = &reply1; av_log(s, AV_LOG_WARNING, "UDP timeout, retrying with TCP\n"); if (rtsp_read_pause(s) != 0) return -1; // TEARDOWN is required on Real-RTSP, but might make // other servers close the connection. if (rt->server_type == RTSP_SERVER_REAL) ff_rtsp_send_cmd(s, "TEARDOWN", rt->control_uri, NULL, reply, NULL); rt->session_id[0] = '\0'; if (resetup_tcp(s) == 0) { rt->state = RTSP_STATE_IDLE; rt->need_subscription = 1; if (rtsp_read_play(s) != 0) return -1; goto retry; } } } return ret; } rt->packets++; if (!(rt->rtsp_flags & RTSP_FLAG_LISTEN)) { /* send dummy request to keep TCP connection alive */ if ((av_gettime_relative() - rt->last_cmd_time) / 1000000 >= rt->timeout / 2 || rt->auth_state.stale) { if (rt->server_type == RTSP_SERVER_WMS || (rt->server_type != RTSP_SERVER_REAL && rt->get_parameter_supported)) { ff_rtsp_send_cmd_async(s, "GET_PARAMETER", rt->control_uri, NULL); } else { ff_rtsp_send_cmd_async(s, "OPTIONS", rt->control_uri, NULL); } /* The stale flag should be reset when creating the auth response in * ff_rtsp_send_cmd_async, but reset it here just in case we never * called the auth code (if we didn't have any credentials set). */ rt->auth_state.stale = 0; } } return 0; }
static int parse_playlist(URLContext *h, const char *url) { HLSContext *s = h->priv_data; AVIOContext *in; int ret = 0, is_segment = 0, is_variant = 0, bandwidth = 0; int64_t duration = 0; char line[1024]; const char *ptr; if ((ret = ffio_open_whitelist(&in, url, AVIO_FLAG_READ, &h->interrupt_callback, NULL, h->protocol_whitelist, h->protocol_blacklist)) < 0) return ret; ff_get_chomp_line(in, line, sizeof(line)); if (strcmp(line, "#EXTM3U")) { ret = AVERROR_INVALIDDATA; goto fail; } free_segment_list(s); s->finished = 0; while (!avio_feof(in)) { ff_get_chomp_line(in, line, sizeof(line)); if (av_strstart(line, "#EXT-X-STREAM-INF:", &ptr)) { struct variant_info info = {{0}}; is_variant = 1; ff_parse_key_value(ptr, (ff_parse_key_val_cb) handle_variant_args, &info); bandwidth = atoi(info.bandwidth); } else if (av_strstart(line, "#EXT-X-TARGETDURATION:", &ptr)) { s->target_duration = atoi(ptr) * AV_TIME_BASE; } else if (av_strstart(line, "#EXT-X-MEDIA-SEQUENCE:", &ptr)) { s->start_seq_no = atoi(ptr); } else if (av_strstart(line, "#EXT-X-ENDLIST", &ptr)) { s->finished = 1; } else if (av_strstart(line, "#EXTINF:", &ptr)) { is_segment = 1; duration = atof(ptr) * AV_TIME_BASE; } else if (av_strstart(line, "#", NULL)) { continue; } else if (line[0]) { if (is_segment) { struct segment *seg = av_malloc(sizeof(struct segment)); if (!seg) { ret = AVERROR(ENOMEM); goto fail; } seg->duration = duration; ff_make_absolute_url(seg->url, sizeof(seg->url), url, line); dynarray_add(&s->segments, &s->n_segments, seg); is_segment = 0; } else if (is_variant) { struct variant *var = av_malloc(sizeof(struct variant)); if (!var) { ret = AVERROR(ENOMEM); goto fail; } var->bandwidth = bandwidth; ff_make_absolute_url(var->url, sizeof(var->url), url, line); dynarray_add(&s->variants, &s->n_variants, var); is_variant = 0; } } } s->last_load_time = av_gettime_relative(); fail: avio_close(in); return ret; }
static int hls_read(URLContext *h, uint8_t *buf, int size) { HLSContext *s = h->priv_data; const char *url; int ret; int64_t reload_interval; start: if (s->seg_hd) { ret = ffurl_read(s->seg_hd, buf, size); if (ret > 0) return ret; } if (s->seg_hd) { ffurl_close(s->seg_hd); s->seg_hd = NULL; s->cur_seq_no++; } reload_interval = s->n_segments > 0 ? s->segments[s->n_segments - 1]->duration : s->target_duration; retry: if (!s->finished) { int64_t now = av_gettime_relative(); if (now - s->last_load_time >= reload_interval) { if ((ret = parse_playlist(h, s->playlisturl)) < 0) return ret; /* If we need to reload the playlist again below (if * there's still no more segments), switch to a reload * interval of half the target duration. */ reload_interval = s->target_duration / 2; } } if (s->cur_seq_no < s->start_seq_no) { av_log(h, AV_LOG_WARNING, "skipping %d segments ahead, expired from playlist\n", s->start_seq_no - s->cur_seq_no); s->cur_seq_no = s->start_seq_no; } if (s->cur_seq_no - s->start_seq_no >= s->n_segments) { if (s->finished) return AVERROR_EOF; while (av_gettime_relative() - s->last_load_time < reload_interval) { if (ff_check_interrupt(&h->interrupt_callback)) return AVERROR_EXIT; av_usleep(100*1000); } goto retry; } url = s->segments[s->cur_seq_no - s->start_seq_no]->url; av_log(h, AV_LOG_DEBUG, "opening %s\n", url); ret = ffurl_open_whitelist(&s->seg_hd, url, AVIO_FLAG_READ, &h->interrupt_callback, NULL, h->protocol_whitelist, h->protocol_blacklist, h); if (ret < 0) { if (ff_check_interrupt(&h->interrupt_callback)) return AVERROR_EXIT; av_log(h, AV_LOG_WARNING, "Unable to open %s\n", url); s->cur_seq_no++; goto retry; } goto start; }
int main(int argc, char **argv) { FFTComplex *tab, *tab1, *tab_ref; FFTSample *tab2; enum tf_transform transform = TRANSFORM_FFT; FFTContext m, s; #if FFT_FLOAT RDFTContext r; DCTContext d; #if CONFIG_LIBFFTW3 FFTWContext fftw; FFTWComplex *tab_fftw, *tab_fftw_copy; #endif /* CONFIG_LIBFFTW3 */ #endif /* FFT_FLOAT */ int it, i, err = 1; int do_speed = 0, do_inverse = 0; int fft_nbits = 9, fft_size; double scale = 1.0; AVLFG prng; av_lfg_init(&prng, 1); for (;;) { int c = getopt(argc, argv, "hsitmrdn:f:c:"); if (c == -1) break; switch (c) { case 'h': help(); return 1; case 's': do_speed = 1; break; case 'i': do_inverse = 1; break; #if CONFIG_LIBFFTW3 case 't': transform = TRANSFORM_FFTW; break; #endif /* CONFIG_LIBFFTW3 */ case 'm': transform = TRANSFORM_MDCT; break; case 'r': transform = TRANSFORM_RDFT; break; case 'd': transform = TRANSFORM_DCT; break; case 'n': fft_nbits = atoi(optarg); break; case 'f': scale = atof(optarg); break; case 'c': { unsigned cpuflags = av_get_cpu_flags(); if (av_parse_cpu_caps(&cpuflags, optarg) < 0) return 1; av_force_cpu_flags(cpuflags); break; } } } fft_size = 1 << fft_nbits; tab = av_malloc_array(fft_size, sizeof(FFTComplex)); tab1 = av_malloc_array(fft_size, sizeof(FFTComplex)); tab_ref = av_malloc_array(fft_size, sizeof(FFTComplex)); tab2 = av_malloc_array(fft_size, sizeof(FFTSample)); #if CONFIG_LIBFFTW3 && FFT_FLOAT tab_fftw = av_malloc_array(fft_size, sizeof(*tab_fftw)); tab_fftw_copy = av_malloc_array(fft_size, sizeof(*tab_fftw_copy)); if (!(tab_fftw && tab_fftw_copy)) goto cleanup_fftw; #endif /* CONFIG_LIBFFTW3 */ if (!(tab && tab1 && tab_ref && tab2)) goto cleanup; switch (transform) { #if CONFIG_MDCT case TRANSFORM_MDCT: av_log(NULL, AV_LOG_INFO, "Scale factor is set to %f\n", scale); if (do_inverse) av_log(NULL, AV_LOG_INFO, "IMDCT"); else av_log(NULL, AV_LOG_INFO, "MDCT"); ff_mdct_init(&m, fft_nbits, do_inverse, scale); break; #endif /* CONFIG_MDCT */ case TRANSFORM_FFT: if (do_inverse) av_log(NULL, AV_LOG_INFO, "IFFT"); else av_log(NULL, AV_LOG_INFO, "FFT"); ff_fft_init(&s, fft_nbits, do_inverse); if ((err = fft_ref_init(fft_nbits, do_inverse)) < 0) goto cleanup; break; #if CONFIG_LIBFFTW3 && FFT_FLOAT case TRANSFORM_FFTW: if (do_inverse) av_log(NULL, AV_LOG_INFO, "IFFTW"); else av_log(NULL, AV_LOG_INFO, "FFTW"); ff_fftw_init(&fftw, fft_size, do_inverse); if ((err = fft_ref_init(fft_nbits, do_inverse)) < 0) goto cleanup; break; #endif /* CONFIG_LIBFFTW3 */ #if FFT_FLOAT # if CONFIG_RDFT case TRANSFORM_RDFT: if (do_inverse) av_log(NULL, AV_LOG_INFO, "IDFT_C2R"); else av_log(NULL, AV_LOG_INFO, "DFT_R2C"); ff_rdft_init(&r, fft_nbits, do_inverse ? IDFT_C2R : DFT_R2C); if ((err = fft_ref_init(fft_nbits, do_inverse)) < 0) goto cleanup; break; # endif /* CONFIG_RDFT */ # if CONFIG_DCT case TRANSFORM_DCT: if (do_inverse) av_log(NULL, AV_LOG_INFO, "DCT_III"); else av_log(NULL, AV_LOG_INFO, "DCT_II"); ff_dct_init(&d, fft_nbits, do_inverse ? DCT_III : DCT_II); break; # endif /* CONFIG_DCT */ #endif /* FFT_FLOAT */ default: av_log(NULL, AV_LOG_ERROR, "Requested transform not supported\n"); goto cleanup; } av_log(NULL, AV_LOG_INFO, " %d test\n", fft_size); /* generate random data */ for (i = 0; i < fft_size; i++) { tab1[i].re = frandom(&prng); tab1[i].im = frandom(&prng); #if CONFIG_LIBFFTW3 && FFT_FLOAT tab_fftw[i][0] = tab1[i].re; tab_fftw[i][1] = tab1[i].im; #endif /* CONFIG_LIBFFTW3 */ } #if CONFIG_LIBFFTW3 && FFT_FLOAT memcpy(tab_fftw_copy, tab_fftw, fft_size * sizeof(*tab_fftw)); #endif /* checking result */ av_log(NULL, AV_LOG_INFO, "Checking...\n"); switch (transform) { #if CONFIG_MDCT case TRANSFORM_MDCT: if (do_inverse) { imdct_ref(&tab_ref->re, &tab1->re, fft_nbits); m.imdct_calc(&m, tab2, &tab1->re); err = check_diff(&tab_ref->re, tab2, fft_size, scale); } else { mdct_ref(&tab_ref->re, &tab1->re, fft_nbits); m.mdct_calc(&m, tab2, &tab1->re); err = check_diff(&tab_ref->re, tab2, fft_size / 2, scale); } break; #endif /* CONFIG_MDCT */ case TRANSFORM_FFT: memcpy(tab, tab1, fft_size * sizeof(FFTComplex)); s.fft_permute(&s, tab); s.fft_calc(&s, tab); fft_ref(tab_ref, tab1, fft_nbits); err = check_diff(&tab_ref->re, &tab->re, fft_size * 2, 1.0); break; #if CONFIG_LIBFFTW3 && FFT_FLOAT case TRANSFORM_FFTW: fftw.fft_calc(&fftw, tab_fftw); fft_ref(tab_ref, tab1, fft_nbits); for (i = 0; i < fft_size; i++) { tab[i].re = tab_fftw[i][0]; tab[i].im = tab_fftw[i][1]; } err = check_diff(&tab_ref->re, &tab->re, fft_size * 2, 1.0); break; #endif /* CONFIG_LIBFFTW3 */ #if FFT_FLOAT #if CONFIG_RDFT case TRANSFORM_RDFT: { int fft_size_2 = fft_size >> 1; if (do_inverse) { tab1[0].im = 0; tab1[fft_size_2].im = 0; for (i = 1; i < fft_size_2; i++) { tab1[fft_size_2 + i].re = tab1[fft_size_2 - i].re; tab1[fft_size_2 + i].im = -tab1[fft_size_2 - i].im; } memcpy(tab2, tab1, fft_size * sizeof(FFTSample)); tab2[1] = tab1[fft_size_2].re; r.rdft_calc(&r, tab2); fft_ref(tab_ref, tab1, fft_nbits); for (i = 0; i < fft_size; i++) { tab[i].re = tab2[i]; tab[i].im = 0; } err = check_diff(&tab_ref->re, &tab->re, fft_size * 2, 0.5); } else { for (i = 0; i < fft_size; i++) { tab2[i] = tab1[i].re; tab1[i].im = 0; } r.rdft_calc(&r, tab2); fft_ref(tab_ref, tab1, fft_nbits); tab_ref[0].im = tab_ref[fft_size_2].re; err = check_diff(&tab_ref->re, tab2, fft_size, 1.0); } break; } #endif /* CONFIG_RDFT */ #if CONFIG_DCT case TRANSFORM_DCT: memcpy(tab, tab1, fft_size * sizeof(FFTComplex)); d.dct_calc(&d, &tab->re); if (do_inverse) idct_ref(&tab_ref->re, &tab1->re, fft_nbits); else dct_ref(&tab_ref->re, &tab1->re, fft_nbits); err = check_diff(&tab_ref->re, &tab->re, fft_size, 1.0); break; #endif /* CONFIG_DCT */ #endif /* FFT_FLOAT */ } /* do a speed test */ if (do_speed) { int64_t time_start, duration; int nb_its; av_log(NULL, AV_LOG_INFO, "Speed test...\n"); /* we measure during about 1 seconds */ nb_its = 1; for (;;) { time_start = av_gettime_relative(); for (it = 0; it < nb_its; it++) { switch (transform) { case TRANSFORM_MDCT: if (do_inverse) m.imdct_calc(&m, &tab->re, &tab1->re); else m.mdct_calc(&m, &tab->re, &tab1->re); break; case TRANSFORM_FFT: memcpy(tab, tab1, fft_size * sizeof(FFTComplex)); s.fft_permute(&s, tab); s.fft_calc(&s, tab); break; #if CONFIG_LIBFFTW3 && FFT_FLOAT case TRANSFORM_FFTW: memcpy(tab_fftw, tab_fftw_copy, fft_size * sizeof(*tab_fftw)); fftw.fft_calc(&fftw, tab_fftw); break; #endif /* CONFIG_LIBFFTW3 */ #if FFT_FLOAT case TRANSFORM_RDFT: memcpy(tab2, tab1, fft_size * sizeof(FFTSample)); r.rdft_calc(&r, tab2); break; case TRANSFORM_DCT: memcpy(tab2, tab1, fft_size * sizeof(FFTSample)); d.dct_calc(&d, tab2); break; #endif /* FFT_FLOAT */ } } duration = av_gettime_relative() - time_start; if (duration >= 1000000) break; nb_its *= 2; } av_log(NULL, AV_LOG_INFO, "time: %0.2f us/transform [total time=%0.2f s its=%d]\n", (double) duration / nb_its, (double) duration / 1000000.0, nb_its); } switch (transform) { #if CONFIG_MDCT case TRANSFORM_MDCT: ff_mdct_end(&m); break; #endif /* CONFIG_MDCT */ case TRANSFORM_FFT: ff_fft_end(&s); break; #if CONFIG_LIBFFTW3 && FFT_FLOAT case TRANSFORM_FFTW: ff_fftw_deinit(&fftw); break; #endif /* CONFIG_LIBFFTW3 */ #if FFT_FLOAT # if CONFIG_RDFT case TRANSFORM_RDFT: ff_rdft_end(&r); break; # endif /* CONFIG_RDFT */ # if CONFIG_DCT case TRANSFORM_DCT: ff_dct_end(&d); break; # endif /* CONFIG_DCT */ #endif /* FFT_FLOAT */ } #if CONFIG_LIBFFTW3 && FFT_FLOAT cleanup_fftw: av_freep(&tab_fftw); #endif /* CONFIG_LIBFFTW3 */ cleanup: av_freep(&tab); av_freep(&tab1); av_freep(&tab2); av_freep(&tab_ref); av_freep(&exptab); if (err) printf("Error: %d.\n", err); return !!err; }
int main(int argc, char **argv) { FFTComplex *tab, *tab1, *tab_ref; FFTSample *tab2; int it, i, c; int cpuflags; int do_speed = 0; int err = 1; enum tf_transform transform = TRANSFORM_FFT; int do_inverse = 0; FFTContext s1, *s = &s1; FFTContext m1, *m = &m1; #if FFT_FLOAT RDFTContext r1, *r = &r1; DCTContext d1, *d = &d1; int fft_size_2; #endif int fft_nbits, fft_size; double scale = 1.0; AVLFG prng; av_lfg_init(&prng, 1); fft_nbits = 9; for(;;) { c = getopt(argc, argv, "hsimrdn:f:c:"); if (c == -1) break; switch(c) { case 'h': help(); return 1; case 's': do_speed = 1; break; case 'i': do_inverse = 1; break; case 'm': transform = TRANSFORM_MDCT; break; case 'r': transform = TRANSFORM_RDFT; break; case 'd': transform = TRANSFORM_DCT; break; case 'n': fft_nbits = atoi(optarg); break; case 'f': scale = atof(optarg); break; case 'c': cpuflags = av_get_cpu_flags(); if (av_parse_cpu_caps(&cpuflags, optarg) < 0) return 1; av_force_cpu_flags(cpuflags); break; } } fft_size = 1 << fft_nbits; tab = av_malloc_array(fft_size, sizeof(FFTComplex)); tab1 = av_malloc_array(fft_size, sizeof(FFTComplex)); tab_ref = av_malloc_array(fft_size, sizeof(FFTComplex)); tab2 = av_malloc_array(fft_size, sizeof(FFTSample)); switch (transform) { #if CONFIG_MDCT case TRANSFORM_MDCT: av_log(NULL, AV_LOG_INFO,"Scale factor is set to %f\n", scale); if (do_inverse) av_log(NULL, AV_LOG_INFO,"IMDCT"); else av_log(NULL, AV_LOG_INFO,"MDCT"); ff_mdct_init(m, fft_nbits, do_inverse, scale); break; #endif /* CONFIG_MDCT */ case TRANSFORM_FFT: if (do_inverse) av_log(NULL, AV_LOG_INFO,"IFFT"); else av_log(NULL, AV_LOG_INFO,"FFT"); ff_fft_init(s, fft_nbits, do_inverse); fft_ref_init(fft_nbits, do_inverse); break; #if FFT_FLOAT # if CONFIG_RDFT case TRANSFORM_RDFT: if (do_inverse) av_log(NULL, AV_LOG_INFO,"IDFT_C2R"); else av_log(NULL, AV_LOG_INFO,"DFT_R2C"); ff_rdft_init(r, fft_nbits, do_inverse ? IDFT_C2R : DFT_R2C); fft_ref_init(fft_nbits, do_inverse); break; # endif /* CONFIG_RDFT */ # if CONFIG_DCT case TRANSFORM_DCT: if (do_inverse) av_log(NULL, AV_LOG_INFO,"DCT_III"); else av_log(NULL, AV_LOG_INFO,"DCT_II"); ff_dct_init(d, fft_nbits, do_inverse ? DCT_III : DCT_II); break; # endif /* CONFIG_DCT */ #endif default: av_log(NULL, AV_LOG_ERROR, "Requested transform not supported\n"); return 1; } av_log(NULL, AV_LOG_INFO," %d test\n", fft_size); /* generate random data */ for (i = 0; i < fft_size; i++) { tab1[i].re = frandom(&prng); tab1[i].im = frandom(&prng); } /* checking result */ av_log(NULL, AV_LOG_INFO,"Checking...\n"); switch (transform) { #if CONFIG_MDCT case TRANSFORM_MDCT: if (do_inverse) { imdct_ref((FFTSample *)tab_ref, (FFTSample *)tab1, fft_nbits); m->imdct_calc(m, tab2, (FFTSample *)tab1); err = check_diff((FFTSample *)tab_ref, tab2, fft_size, scale); } else { mdct_ref((FFTSample *)tab_ref, (FFTSample *)tab1, fft_nbits); m->mdct_calc(m, tab2, (FFTSample *)tab1); err = check_diff((FFTSample *)tab_ref, tab2, fft_size / 2, scale); } break; #endif /* CONFIG_MDCT */ case TRANSFORM_FFT: memcpy(tab, tab1, fft_size * sizeof(FFTComplex)); s->fft_permute(s, tab); s->fft_calc(s, tab); fft_ref(tab_ref, tab1, fft_nbits); err = check_diff((FFTSample *)tab_ref, (FFTSample *)tab, fft_size * 2, 1.0); break; #if FFT_FLOAT #if CONFIG_RDFT case TRANSFORM_RDFT: fft_size_2 = fft_size >> 1; if (do_inverse) { tab1[ 0].im = 0; tab1[fft_size_2].im = 0; for (i = 1; i < fft_size_2; i++) { tab1[fft_size_2+i].re = tab1[fft_size_2-i].re; tab1[fft_size_2+i].im = -tab1[fft_size_2-i].im; } memcpy(tab2, tab1, fft_size * sizeof(FFTSample)); tab2[1] = tab1[fft_size_2].re; r->rdft_calc(r, tab2); fft_ref(tab_ref, tab1, fft_nbits); for (i = 0; i < fft_size; i++) { tab[i].re = tab2[i]; tab[i].im = 0; } err = check_diff((float *)tab_ref, (float *)tab, fft_size * 2, 0.5); } else { for (i = 0; i < fft_size; i++) { tab2[i] = tab1[i].re; tab1[i].im = 0; } r->rdft_calc(r, tab2); fft_ref(tab_ref, tab1, fft_nbits); tab_ref[0].im = tab_ref[fft_size_2].re; err = check_diff((float *)tab_ref, (float *)tab2, fft_size, 1.0); } break; #endif /* CONFIG_RDFT */ #if CONFIG_DCT case TRANSFORM_DCT: memcpy(tab, tab1, fft_size * sizeof(FFTComplex)); d->dct_calc(d, (FFTSample *)tab); if (do_inverse) { idct_ref((FFTSample*)tab_ref, (FFTSample *)tab1, fft_nbits); } else { dct_ref((FFTSample*)tab_ref, (FFTSample *)tab1, fft_nbits); } err = check_diff((float *)tab_ref, (float *)tab, fft_size, 1.0); break; #endif /* CONFIG_DCT */ #endif } /* do a speed test */ if (do_speed) { int64_t time_start, duration; int nb_its; av_log(NULL, AV_LOG_INFO,"Speed test...\n"); /* we measure during about 1 seconds */ nb_its = 1; for(;;) { time_start = av_gettime_relative(); for (it = 0; it < nb_its; it++) { switch (transform) { case TRANSFORM_MDCT: if (do_inverse) { m->imdct_calc(m, (FFTSample *)tab, (FFTSample *)tab1); } else { m->mdct_calc(m, (FFTSample *)tab, (FFTSample *)tab1); } break; case TRANSFORM_FFT: memcpy(tab, tab1, fft_size * sizeof(FFTComplex)); s->fft_calc(s, tab); break; #if FFT_FLOAT case TRANSFORM_RDFT: memcpy(tab2, tab1, fft_size * sizeof(FFTSample)); r->rdft_calc(r, tab2); break; case TRANSFORM_DCT: memcpy(tab2, tab1, fft_size * sizeof(FFTSample)); d->dct_calc(d, tab2); break; #endif } } duration = av_gettime_relative() - time_start; if (duration >= 1000000) break; nb_its *= 2; } av_log(NULL, AV_LOG_INFO,"time: %0.1f us/transform [total time=%0.2f s its=%d]\n", (double)duration / nb_its, (double)duration / 1000000.0, nb_its); } switch (transform) { #if CONFIG_MDCT case TRANSFORM_MDCT: ff_mdct_end(m); break; #endif /* CONFIG_MDCT */ case TRANSFORM_FFT: ff_fft_end(s); break; #if FFT_FLOAT # if CONFIG_RDFT case TRANSFORM_RDFT: ff_rdft_end(r); break; # endif /* CONFIG_RDFT */ # if CONFIG_DCT case TRANSFORM_DCT: ff_dct_end(d); break; # endif /* CONFIG_DCT */ #endif } av_free(tab); av_free(tab1); av_free(tab2); av_free(tab_ref); av_free(exptab); if (err) printf("Error: %d.\n", err); return !!err; }
HRESULT decklink_input_callback::VideoInputFrameArrived( IDeckLinkVideoInputFrame *videoFrame, IDeckLinkAudioInputPacket *audioFrame) { void *frameBytes; void *audioFrameBytes; BMDTimeValue frameTime; BMDTimeValue frameDuration; int64_t wallclock = 0; ctx->frameCount++; if (ctx->audio_pts_source == PTS_SRC_WALLCLOCK || ctx->video_pts_source == PTS_SRC_WALLCLOCK) wallclock = av_gettime_relative(); // Handle Video Frame if (videoFrame) { AVPacket pkt; av_init_packet(&pkt); if (ctx->frameCount % 25 == 0) { unsigned long long qsize = avpacket_queue_size(&ctx->queue); av_log(avctx, AV_LOG_DEBUG, "Frame received (#%lu) - Valid (%liB) - QSize %fMB\n", ctx->frameCount, videoFrame->GetRowBytes() * videoFrame->GetHeight(), (double)qsize / 1024 / 1024); } videoFrame->GetBytes(&frameBytes); videoFrame->GetStreamTime(&frameTime, &frameDuration, ctx->video_st->time_base.den); if (videoFrame->GetFlags() & bmdFrameHasNoInputSource) { if (ctx->draw_bars && videoFrame->GetPixelFormat() == bmdFormat8BitYUV) { unsigned bars[8] = { 0xEA80EA80, 0xD292D210, 0xA910A9A5, 0x90229035, 0x6ADD6ACA, 0x51EF515A, 0x286D28EF, 0x10801080 }; int width = videoFrame->GetWidth(); int height = videoFrame->GetHeight(); unsigned *p = (unsigned *)frameBytes; for (int y = 0; y < height; y++) { for (int x = 0; x < width; x += 2) *p++ = bars[(x * 8) / width]; } } if (!no_video) { av_log(avctx, AV_LOG_WARNING, "Frame received (#%lu) - No input signal detected " "- Frames dropped %u\n", ctx->frameCount, ++ctx->dropped); } no_video = 1; } else { if (no_video) { av_log(avctx, AV_LOG_WARNING, "Frame received (#%lu) - Input returned " "- Frames dropped %u\n", ctx->frameCount, ++ctx->dropped); } no_video = 0; } pkt.pts = get_pkt_pts(videoFrame, audioFrame, wallclock, ctx->video_pts_source, ctx->video_st->time_base, &initial_video_pts); pkt.dts = pkt.pts; pkt.duration = frameDuration; //To be made sure it still applies pkt.flags |= AV_PKT_FLAG_KEY; pkt.stream_index = ctx->video_st->index; pkt.data = (uint8_t *)frameBytes; pkt.size = videoFrame->GetRowBytes() * videoFrame->GetHeight(); //fprintf(stderr,"Video Frame size %d ts %d\n", pkt.size, pkt.pts); #if CONFIG_LIBZVBI if (!no_video && ctx->teletext_lines && videoFrame->GetPixelFormat() == bmdFormat8BitYUV && videoFrame->GetWidth() == 720) { IDeckLinkVideoFrameAncillary *vanc; AVPacket txt_pkt; uint8_t txt_buf0[1611]; // max 35 * 46 bytes decoded teletext lines + 1 byte data_identifier uint8_t *txt_buf = txt_buf0; if (videoFrame->GetAncillaryData(&vanc) == S_OK) { int i; int64_t line_mask = 1; txt_buf[0] = 0x10; // data_identifier - EBU_data txt_buf++; for (i = 6; i < 336; i++, line_mask <<= 1) { uint8_t *buf; if ((ctx->teletext_lines & line_mask) && vanc->GetBufferForVerticalBlankingLine(i, (void**)&buf) == S_OK) { if (teletext_data_unit_from_vbi_data(i, buf, txt_buf) >= 0) txt_buf += 46; } if (i == 22) i = 317; } vanc->Release(); if (txt_buf - txt_buf0 > 1) { int stuffing_units = (4 - ((45 + txt_buf - txt_buf0) / 46) % 4) % 4; while (stuffing_units--) { memset(txt_buf, 0xff, 46); txt_buf[1] = 0x2c; // data_unit_length txt_buf += 46; } av_init_packet(&txt_pkt); txt_pkt.pts = pkt.pts; txt_pkt.dts = pkt.dts; txt_pkt.stream_index = ctx->teletext_st->index; txt_pkt.data = txt_buf0; txt_pkt.size = txt_buf - txt_buf0; if (avpacket_queue_put(&ctx->queue, &txt_pkt) < 0) { ++ctx->dropped; } } } } #endif if (avpacket_queue_put(&ctx->queue, &pkt) < 0) { ++ctx->dropped; } } // Handle Audio Frame if (audioFrame) { AVPacket pkt; BMDTimeValue audio_pts; av_init_packet(&pkt); //hack among hacks pkt.size = audioFrame->GetSampleFrameCount() * ctx->audio_st->codecpar->channels * (16 / 8); audioFrame->GetBytes(&audioFrameBytes); audioFrame->GetPacketTime(&audio_pts, ctx->audio_st->time_base.den); pkt.pts = get_pkt_pts(videoFrame, audioFrame, wallclock, ctx->audio_pts_source, ctx->audio_st->time_base, &initial_audio_pts); pkt.dts = pkt.pts; //fprintf(stderr,"Audio Frame size %d ts %d\n", pkt.size, pkt.pts); pkt.flags |= AV_PKT_FLAG_KEY; pkt.stream_index = ctx->audio_st->index; pkt.data = (uint8_t *)audioFrameBytes; if (avpacket_queue_put(&ctx->queue, &pkt) < 0) { ++ctx->dropped; } } return S_OK; }
void VideoStateInfo::setClock(Clock *c, double pts, int serial) { double time = av_gettime_relative() / 1000000.0; setClockAt(c, pts, serial, time); }
int main(int argc, char **argv) { AVOutputFormat *ofmt = NULL; AVFormatContext *ifmt_ctx = NULL, *ofmt_ctx = NULL; AVDictionary *out_opts = NULL; AVPacket pkt; const char *fmt, *in_filename, *out_filename; int ret, i, cmp; int cnt = 0; if (argc < 4) { printf("usage: remuxing input output fmt [do_sff do_rate_emu]\n"); return 1; } if(argc >= 5){ do_sff = atoi(argv[4]); } if(argc >= 6){ do_rate_emu = atoi(argv[5]); } in_filename = argv[1]; out_filename = argv[2]; fmt = argv[3]; av_register_all(); avformat_network_init(); if ((ret = avformat_open_input(&ifmt_ctx, in_filename, 0, 0)) < 0) { fprintf(stderr, "Could not open input file '%s'", in_filename); goto end; } if ((ret = avformat_find_stream_info(ifmt_ctx, 0)) < 0) { fprintf(stderr, "Failed to retrieve input stream information"); goto end; } av_dump_format(ifmt_ctx, 0, in_filename, 0); avformat_alloc_output_context2(&ofmt_ctx, NULL, fmt, out_filename); if (!ofmt_ctx) { fprintf(stderr, "Could not create output context\n"); ret = AVERROR_UNKNOWN; goto end; } ofmt = ofmt_ctx->oformat; for (i = 0; i < ifmt_ctx->nb_streams; i++) { AVStream *in_stream = ifmt_ctx->streams[i]; AVStream *out_stream = avformat_new_stream(ofmt_ctx, in_stream->codec->codec); if (!out_stream) { fprintf(stderr, "Failed allocating output stream\n"); ret = AVERROR_UNKNOWN; goto end; } avpriv_set_pts_info(out_stream, in_stream->pts_wrap_bits, in_stream->time_base.num, in_stream->time_base.den); ret = avcodec_copy_context(out_stream->codec, in_stream->codec); if (ret < 0) { fprintf(stderr, "Failed to copy context from input to output stream codec context\n"); goto end; } out_stream->codec->codec_tag = 0; if (ofmt_ctx->oformat->flags & AVFMT_GLOBALHEADER) out_stream->codec->flags |= CODEC_FLAG_GLOBAL_HEADER; } if(out_filename && strstr(out_filename, ".m3u8")){ av_opt_set_int(ofmt_ctx, "hls_wrap", 6, AV_OPT_SEARCH_CHILDREN); av_opt_set_int(ofmt_ctx, "hls_list_size", 6, AV_OPT_SEARCH_CHILDREN); av_opt_set(ofmt_ctx, "hls_time", "1.0", AV_OPT_SEARCH_CHILDREN); } av_dump_format(ofmt_ctx, 0, out_filename, 1); if (!(ofmt->flags & AVFMT_NOFILE)) { av_dict_set(&out_opts, "chunked_post", "0", 0); ret = avio_open2(&ofmt_ctx->pb, out_filename, AVIO_FLAG_WRITE|AVIO_FLAG_NONBLOCK, NULL, &out_opts); if (ret < 0) { fprintf(stderr, "Could not open output file '%s'", out_filename); goto end; } } ret = ofmt_ctx->pb && do_sff ? sff_write_header(ofmt_ctx) : avformat_write_header(ofmt_ctx, NULL); if (ret < 0) { fprintf(stderr, "Error occurred when opening output file\n"); goto end; } if(ofmt_ctx->pb){ avio_flush(ofmt_ctx->pb); } while (1) { AVStream *in_stream, *out_stream; ret = av_read_frame(ifmt_ctx, &pkt); if (ret < 0) break; in_stream = ifmt_ctx->streams[pkt.stream_index]; out_stream = ofmt_ctx->streams[pkt.stream_index]; i = pkt.stream_index; if(curr_dts[i] == AV_NOPTS_VALUE && pkt.dts != AV_NOPTS_VALUE){ first_dts[i] = pkt.dts; start_time[i] = av_gettime_relative(); } if(pkt.dts != AV_NOPTS_VALUE){ curr_dts[i] = pkt.dts; //us } /* copy packet */ pkt.pts = av_rescale_q_rnd(pkt.pts, in_stream->time_base, out_stream->time_base, AV_ROUND_NEAR_INF|AV_ROUND_PASS_MINMAX); pkt.dts = av_rescale_q_rnd(pkt.dts, in_stream->time_base, out_stream->time_base, AV_ROUND_NEAR_INF|AV_ROUND_PASS_MINMAX); pkt.duration = av_rescale_q(pkt.duration, in_stream->time_base, out_stream->time_base); pkt.pos = -1; ret = ofmt_ctx->pb && do_sff ? sff_write_packet(ofmt_ctx, &pkt) : av_interleaved_write_frame(ofmt_ctx, &pkt); if(ofmt_ctx->pb){ avio_flush(ofmt_ctx->pb); } if (ret < 0) { fprintf(stderr, "Error muxing packet\n"); break; } av_free_packet(&pkt); ++cnt; //printf("cnt %d\t", cnt); do{ curr_time[i] = av_gettime_relative(); cmp = av_compare_ts(curr_dts[i] - first_dts[i], in_stream->time_base, curr_time[i] - start_time[i], AV_TIME_BASE_Q); if(!do_rate_emu || cmp <= 0)break; av_usleep(10000); }while(cmp > 0); } ofmt_ctx->pb && do_sff ? sff_write_packet(ofmt_ctx, NULL) : av_write_trailer(ofmt_ctx); end: avformat_close_input(&ifmt_ctx); /* close output */ if (ofmt_ctx && !(ofmt->flags & AVFMT_NOFILE) && ofmt_ctx->pb){ avio_close(ofmt_ctx->pb); av_dict_free(&out_opts); } avformat_free_context(ofmt_ctx); if (ret < 0 && ret != AVERROR_EOF) { fprintf(stderr, "Error occurred: %s\n", av_err2str(ret)); return 1; } printf("end of remux\n"); return 0; }