📄 lavpipe.c
字号:
if (y4m_si_get_width(&(filt->out_streaminfo)) != y4m_si_get_width(&(source->streaminfo))) mjpeg_error_exit1("Stream mismatch: frame width"); if (y4m_si_get_height(&(filt->out_streaminfo)) != y4m_si_get_height(&(source->streaminfo))) mjpeg_error_exit1("Stream mismatch: frame height"); if (y4m_si_get_interlace(&(filt->out_streaminfo)) != y4m_si_get_interlace(&(source->streaminfo))) mjpeg_error_exit1("Stream mismatch: interlace"); mjpeg_debug("verified info"); } } }staticvoid setup_segment_filter(PipeSegment *seg, pipe_filter_t *filt, int frame){ mjpeg_debug("OSO: '%s'", filt->command); if (strcmp(filt->command, "-")) { /* ...via a filter command: * o spawn filter process * o write source stream info to filter * o read filter's result stream info * o alloc yuv buffers for source->filter transfers */ /* ... why does the 'count' matter, if lavpipe controls the frame * flow anyway???????? */ spawn_pipe_filter(filt, frame, (seg->frame_count - frame)); y4m_write_stream_header(filt->out_fd, &(filt->out_streaminfo)); y4m_read_stream_header(filt->in_fd, &(filt->in_streaminfo)); mjpeg_debug("SSF: read filter result stream header"); y4m_log_stream_info(LOG_DEBUG, "result: ", &(filt->in_streaminfo)); alloc_yuv_buffers(filt->yuv, y4m_si_get_width(&(filt->out_streaminfo)), y4m_si_get_height(&(filt->out_streaminfo))); } else { /* ...no filter; direct output: * o result stream info is just a copy of the source stream info */ filt->out_fd = filt->in_fd = -1; y4m_copy_stream_info(&(filt->in_streaminfo), &(filt->out_streaminfo)); mjpeg_debug("SSF: copied source header"); }}staticvoid process_segment_frames(pipe_sequence_t *ps, int segnum, int *frame, int *total_frames){ pipe_source_t *sources = ps->sources; pipe_filter_t *the_output = &(ps->output); PipeList *pl = &(ps->pl); commandline_params_t *cl = &(ps->cl); PipeSegment *seg = ps->pl.segments[segnum]; pipe_filter_t *filt = &(ps->filters[segnum]); mjpeg_debug("PSF: segment %d, initial frame = %d", segnum, *frame); while (*frame < seg->frame_count) { int i; for (i = 0; i < seg->input_count; i++) { int in_index = seg->input_index[i]; pipe_source_t *source = &(sources[in_index]); unsigned char **yuv; if (filt->out_fd >= 0) /* filter present; write/read through filter's buffer first */ yuv = filt->yuv; else /* no filter present; source -> direct to output buffer */ yuv = the_output->yuv; mjpeg_debug("read frame %03d > input %d, src %d fd = %d", *frame, i, in_index, source->fd); if (y4m_read_frame(source->fd, &(source->streaminfo), &(source->frameinfo), yuv) != Y4M_OK) { int err = errno; mjpeg_error("ERRNO says: %s", strerror(err)); mjpeg_error_exit1("lavpipe: input stream error in stream %d," "sequence %d, frame %d", i, segnum, *frame); } source->frame_num += 1; if (filt->out_fd >= 0) y4m_write_frame(filt->out_fd, &(filt->out_streaminfo), &(filt->frameinfo), yuv); } if (filt->in_fd >= 0) { if (y4m_read_frame(filt->in_fd, &(filt->in_streaminfo), &(filt->frameinfo), the_output->yuv) != Y4M_OK) { mjpeg_error_exit1( "lavpipe: filter stream error in sequence %d," "frame %d", segnum, *frame); } } /* output result */ y4m_write_frame(the_output->out_fd, &(the_output->out_streaminfo), &(the_output->frameinfo), the_output->yuv); (*frame)++; if (++(*total_frames) == cl->frames) { segnum = pl->segment_count - 1; /* = close all input files below */ break; } }}/* * this is just being picky, but... * * Close all sources used by current segment, but only if they will * cannot be used in current state by upcoming segments. * */staticvoid close_segment_inputs(pipe_sequence_t *ps, int segnum, int frame){ PipeList *pl = &(ps->pl); pipe_source_t *sources = ps->sources; PipeSegment *seg = pl->segments[segnum]; int i; for (i = 0; i < seg->input_count; i++) { int current_index = seg->input_index[i]; pipe_source_t *source = &(sources[current_index]); if (source->fd >= 0) { /* if it's still alive... * ...iterate over remaining segments, and see if they can * use this source. */ int s; for (s = segnum + 1; s < pl->segment_count; s++) { int j; PipeSegment *next_seg = pl->segments[s]; for (j = 0; j < next_seg->input_count; j++) { int index = next_seg->input_index[j]; int offset = next_seg->input_offset[j]; if ( (index == current_index) && (offset == source->frame_num) ) { /* A segment input offset matches the current frame... * ...this source can still be used. */ mjpeg_info("allowing input %d (source %d) to live", i, current_index); goto KEEP_SOURCE; } } } mjpeg_info( "closing input %d (source %d)", i, current_index); decommission_pipe_source(source);KEEP_SOURCE: ; } }}staticvoid parse_command_line(int argc, char *argv[], commandline_params_t *cl){ char c; int err; cl->verbose = 1; cl->offset = 0; cl->frames = 0; cl->listfile = NULL; err = 0; while ((c = getopt(argc, argv, "o:n:v:")) != EOF) { switch (c) { case 'o': cl->offset = atoi(optarg); break; case 'n': cl->frames = atoi(optarg); break; case 'v': cl->verbose = atoi(optarg); if ( (cl->verbose < 0) || (cl->verbose > 2) ) { usage(); exit(1); } break; default: err++; } } if ((optind >= argc) || (err)) { usage(); exit(1); } cl->listfile = strdup(argv[optind]);}staticvoid initialize_pipe_sequence(pipe_sequence_t *ps, int argc, char **argv){ int i; commandline_params_t *cl = &(ps->cl); PipeList *pl = &(ps->pl); init_pipe_filter(&(ps->output), ""); ps->output.out_fd = 1; /* parse command-line arguments */ parse_command_line(argc, argv, cl); /* set-up logging */ (void)mjpeg_default_handler_verbosity(cl->verbose); /* read pipe 'recipe' */ if (read_pipe_list(cl->listfile, pl) < 0) { mjpeg_error_exit1( "lavpipe: couldn't open \"%s\"", cl->listfile); } /* a negative offset means "from the end" */ if (cl->offset < 0) { cl->offset = pl->frame_count + cl->offset; } if ((cl->offset >= pl->frame_count) || (cl->offset < 0)) { mjpeg_error_exit1( "error: offset greater than # of frames in input"); } /* zero frame count means "all frames" */ if (cl->frames == 0) { cl->frames = pl->frame_count - cl->offset; } if ((cl->offset + cl->frames) > pl->frame_count) { mjpeg_warn( "input too short for -n %d", cl->frames); cl->frames = pl->frame_count - cl->offset; } /* initialize pipe sources */ ps->sources = malloc(pl->source_count * sizeof(ps->sources[0])); for (i = 0; i < pl->source_count; i++) init_pipe_source(&(ps->sources[i]), pl->source_cmd[i]); /* initialize pipe filters */ ps->filters = malloc(pl->segment_count * sizeof(ps->filters[0])); for (i = 0; i < pl->segment_count; i++) init_pipe_filter(&(ps->filters[i]), pl->segments[i]->output_cmd); }staticvoid process_pipe_sequence(pipe_sequence_t *ps){ int segm_num; /* current segment number */ int segm_frame; /* frame number, within a segment */ int sequ_frame; /* cumulative/total frame number */ int first_iteration; /* find start segment/frame, given overall lavpipe offset ("-o") */ segm_frame = ps->cl.offset; for (segm_num = 0; segm_frame >= ps->pl.segments[segm_num]->frame_count; segm_num++) { segm_frame -= ps->pl.segments[segm_num]->frame_count; } /* process the segments */ first_iteration = 1; sequ_frame = 0; while ( (segm_num < ps->pl.segment_count) && (sequ_frame < ps->cl.frames) ) { PipeSegment *seg = ps->pl.segments[segm_num]; pipe_filter_t *filt = &(ps->filters[segm_num]); mjpeg_debug("starting segment %d, frame %d", segm_num, segm_frame); open_segment_inputs(seg, filt, segm_frame, segm_num, sequ_frame, &ps->pl, &ps->cl, ps->sources); setup_segment_filter(seg, filt, segm_frame); if (first_iteration) { /* Initialize the final output stream, just once */ /* The final output stream parameters are taken from the output * parameters of the first segment's output filter. * (If there is no filter (i.e. "-", direct output), then the * parameters will end up coming from the first segment's source * stream.) */ y4m_copy_stream_info(&(ps->output.out_streaminfo), &(filt->in_streaminfo)); y4m_write_stream_header(ps->output.out_fd, &(ps->output.out_streaminfo)); alloc_yuv_buffers(ps->output.yuv, y4m_si_get_width(&(ps->output.out_streaminfo)), y4m_si_get_height(&(ps->output.out_streaminfo))); mjpeg_debug("output stream initialized"); first_iteration = 0; } else { /* For succeeding segments, make sure that the new filter's stream is * consistent with the final output stream. */ if (y4m_si_get_width(&(filt->in_streaminfo)) != y4m_si_get_width(&(ps->output.out_streaminfo))) mjpeg_error_exit1("Stream mismatch: frame width"); if (y4m_si_get_height(&(filt->in_streaminfo)) != y4m_si_get_height(&(ps->output.out_streaminfo))) mjpeg_error_exit1("Stream mismatch: frame height"); if (y4m_si_get_interlace(&(filt->in_streaminfo)) != y4m_si_get_interlace(&(ps->output.out_streaminfo))) mjpeg_error_exit1("Stream mismatch: interlace"); mjpeg_debug("filter stream verified"); } process_segment_frames(ps, segm_num, &segm_frame, &sequ_frame); decommission_pipe_filter(filt); close_segment_inputs(ps, segm_num, segm_frame); /* prepare for next sequence */ segm_num++; segm_frame = 0; }}staticvoid cleanup_pipe_sequence(pipe_sequence_t *ps){ int i; PipeList *pl = &(ps->pl); /* free/fini everything */ fini_pipe_filter(&ps->output); for (i = 0; i < pl->source_count; i++) fini_pipe_source(&(ps->sources[i])); free(ps->sources); for (i = 0; i < pl->segment_count; i++) fini_pipe_filter(&(ps->filters[i])); free(ps->filters);}int main (int argc, char *argv[]) { pipe_sequence_t ps; initialize_pipe_sequence(&ps, argc, argv); process_pipe_sequence(&ps); cleanup_pipe_sequence(&ps); return 0;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -