📄 ppmtoy4m.c
字号:
uint8_t *buffers[], uint8_t *buffers2[], uint8_t *rowbuffer, int width, int height, int bgr){ int x, y; uint8_t *pixels; uint8_t *R = buffers[0]; uint8_t *G = buffers[1]; uint8_t *B = buffers[2]; uint8_t *R2 = buffers2[0]; uint8_t *G2 = buffers2[1]; uint8_t *B2 = buffers2[2]; mjpeg_debug("read into two buffers, %dx%d", width, height); height /= 2; for (y = 0; y < height; y++) { pixels = rowbuffer; if (y4m_read(fd, pixels, width * 3)) mjpeg_error_exit1("read error A y=%d", y); if (bgr) { for (x = 0; x < width; x++) { *(B++) = *(pixels++); *(G++) = *(pixels++); *(R++) = *(pixels++); } } else { for (x = 0; x < width; x++) { *(R++) = *(pixels++); *(G++) = *(pixels++); *(B++) = *(pixels++); } } pixels = rowbuffer; if (y4m_read(fd, pixels, width * 3)) mjpeg_error_exit1("read error B y=%d", y); if (bgr) { for (x = 0; x < width; x++) { *(B2++) = *(pixels++); *(G2++) = *(pixels++); *(R2++) = *(pixels++); } } else { for (x = 0; x < width; x++) { *(R2++) = *(pixels++); *(G2++) = *(pixels++); *(B2++) = *(pixels++); } } }}staticvoid read_ppm_into_one_buffer(int fd, uint8_t *buffers[], uint8_t *rowbuffer, int width, int height, int bgr) { int x, y; uint8_t *pixels; uint8_t *R = buffers[0]; uint8_t *G = buffers[1]; uint8_t *B = buffers[2]; for (y = 0; y < height; y++) { pixels = rowbuffer; y4m_read(fd, pixels, width * 3); if (bgr) { for (x = 0; x < width; x++) { *(B++) = *(pixels++); *(G++) = *(pixels++); *(R++) = *(pixels++); } } else { for (x = 0; x < width; x++) { *(R++) = *(pixels++); *(G++) = *(pixels++); *(B++) = *(pixels++); } } }}/* * read one whole frame * if field-sequential interlaced, this requires reading two PPM images * * if interlaced, fields are written into separate buffers * * ppm.width/height refer to image dimensions */staticint read_ppm_frame(int fd, ppm_info_t *ppm, uint8_t *buffers[], uint8_t *buffers2[], int ilace, int ileave, int bgr){ int width, height; static uint8_t *rowbuffer = NULL; int err; err = read_ppm_header(fd, &width, &height); if (err > 0) return 1; /* EOF */ if (err < 0) return -1; /* error */ mjpeg_debug("Got PPM header: %dx%d", width, height); if (ppm->width == 0) { /* first time */ mjpeg_debug("Initializing PPM read_frame"); ppm->width = width; ppm->height = height; rowbuffer = malloc(width * 3 * sizeof(rowbuffer[0])); } else { /* make sure everything matches */ if ( (ppm->width != width) || (ppm->height != height) ) mjpeg_error_exit1("One of these frames is not like the others!"); } if (buffers[0] == NULL) alloc_buffers(buffers, width, height); if ((buffers2[0] == NULL) && (ilace != Y4M_ILACE_NONE)) alloc_buffers(buffers2, width, height); mjpeg_debug("Reading rows"); if ((ilace != Y4M_ILACE_NONE) && (ileave)) { /* Interlaced and Interleaved: --> read image and deinterleave fields at same time */ if (ilace == Y4M_ILACE_TOP_FIRST) { /* 1st buff arg == top field == temporally first == "buffers" */ read_ppm_into_two_buffers(fd, buffers, buffers2, rowbuffer, width, height, bgr); } else { /* bottom-field-first */ /* 1st buff art == top field == temporally second == "buffers2" */ read_ppm_into_two_buffers(fd, buffers2, buffers, rowbuffer, width, height, bgr); } } else if ((ilace == Y4M_ILACE_NONE) || (!ileave)) { /* Not Interlaced, or Not Interleaved: --> read image into first buffer... */ read_ppm_into_one_buffer(fd, buffers, rowbuffer, width, height, bgr); if ((ilace != Y4M_ILACE_NONE) && (!ileave)) { /* ...Actually Interlaced: --> read the second image/field into second buffer */ err = read_ppm_header(fd, &width, &height); if (err > 0) return 1; /* EOF */ if (err < 0) return -1; /* error */ mjpeg_debug("Got PPM header: %dx%d", width, height); /* make sure everything matches */ if ( (ppm->width != width) || (ppm->height != height) ) mjpeg_error_exit1("One of these frames is not like the others!"); read_ppm_into_one_buffer(fd, buffers2, rowbuffer, width, height, bgr); } } return 0;}staticvoid setup_output_stream(int fdout, cl_info_t *cl, y4m_stream_info_t *sinfo, ppm_info_t *ppm, int *field_height) { int err; int x_alignment = y4m_chroma_ss_x_ratio(cl->ss_mode).d; int y_alignment = y4m_chroma_ss_y_ratio(cl->ss_mode).d; if (cl->interlace != Y4M_ILACE_NONE) y_alignment *= 2; if ((ppm->width % x_alignment) != 0) { mjpeg_error_exit1("PPM width (%d) is not a multiple of %d!", ppm->width, x_alignment); } if ((ppm->height % y_alignment) != 0) { mjpeg_error_exit1("PPM height (%d) is not a multiple of %d!", ppm->height, y_alignment); } y4m_si_set_width(sinfo, ppm->width); if (cl->interlace == Y4M_ILACE_NONE) { y4m_si_set_height(sinfo, ppm->height); *field_height = ppm->height; } else if (cl->interleave) { y4m_si_set_height(sinfo, ppm->height); *field_height = ppm->height / 2; } else { y4m_si_set_height(sinfo, ppm->height * 2); *field_height = ppm->height; } y4m_si_set_sampleaspect(sinfo, cl->aspect); y4m_si_set_interlace(sinfo, cl->interlace); y4m_si_set_framerate(sinfo, cl->framerate); y4m_si_set_chroma(sinfo, cl->ss_mode); if ((err = y4m_write_stream_header(fdout, sinfo)) != Y4M_OK) mjpeg_error_exit1("Write header failed: %s", y4m_strerr(err)); mjpeg_info("Output Stream parameters:"); y4m_log_stream_info(LOG_INFO, " ", sinfo);}int main(int argc, char **argv){ cl_info_t cl; y4m_stream_info_t sinfo; y4m_frame_info_t finfo; uint8_t *buffers[Y4M_MAX_NUM_PLANES]; /* R'G'B' or Y'CbCr */ uint8_t *buffers2[Y4M_MAX_NUM_PLANES]; /* R'G'B' or Y'CbCr */ ppm_info_t ppm; int field_height; int fdout = 1; int err, i, count, repeating_last; y4m_accept_extensions(1); y4m_init_stream_info(&sinfo); y4m_init_frame_info(&finfo); parse_args(&cl, argc, argv); ppm.width = 0; ppm.height = 0; for (i = 0; i < 3; i++) { buffers[i] = NULL; buffers2[i] = NULL; } /* Read first PPM frame/field-pair, to get dimensions */ if (read_ppm_frame(cl.fdin, &ppm, buffers, buffers2, cl.interlace, cl.interleave, cl.bgr)) mjpeg_error_exit1("Failed to read first frame."); /* Setup streaminfo and write output header */ setup_output_stream(fdout, &cl, &sinfo, &ppm, &field_height); /* Loop 'framecount' times, or possibly forever... */ for (count = 0, repeating_last = 0; (count < (cl.offset + cl.framecount)) || (cl.framecount == 0); count++) { if (repeating_last) goto WRITE_FRAME; /* Read PPM frame/field */ /* ...but skip reading very first frame, already read prior to loop */ if (count > 0) { err = read_ppm_frame(cl.fdin, &ppm, buffers, buffers2, cl.interlace, cl.interleave, cl.bgr); if (err == 1) { /* clean input EOF */ if (cl.repeatlast) { repeating_last = 1; goto WRITE_FRAME; } else if (cl.framecount != 0) { mjpeg_error_exit1("Input frame shortfall (only %d converted).", count - cl.offset); } else { break; /* input is exhausted; we are done! time to go home! */ } } else if (err) mjpeg_error_exit1("Error reading ppm frame"); } /* ...skip transforms if we are just going to skip this frame anyway. BUT, if 'cl.repeatlast' is on, we must process/buffer every frame, because we don't know when we will see the last one. */ if ((count >= cl.offset) || (cl.repeatlast)) { /* Transform colorspace, then subsample (in place) */ convert_RGB_to_YCbCr(buffers, ppm.width * field_height); chroma_subsample(cl.ss_mode, buffers, ppm.width, field_height); if (cl.interlace != Y4M_ILACE_NONE) { convert_RGB_to_YCbCr(buffers2, ppm.width * field_height); chroma_subsample(cl.ss_mode, buffers2, ppm.width, field_height); } } WRITE_FRAME: /* Write converted frame to output */ if (count >= cl.offset) { switch (cl.interlace) { case Y4M_ILACE_NONE: if ((err = y4m_write_frame(fdout, &sinfo, &finfo, buffers)) != Y4M_OK) mjpeg_error_exit1("Write frame failed: %s", y4m_strerr(err)); break; case Y4M_ILACE_TOP_FIRST: if ((err = y4m_write_fields(fdout, &sinfo, &finfo, buffers, buffers2)) != Y4M_OK) mjpeg_error_exit1("Write fields failed: %s", y4m_strerr(err)); break; case Y4M_ILACE_BOTTOM_FIRST: if ((err = y4m_write_fields(fdout, &sinfo, &finfo, buffers2, buffers)) != Y4M_OK) mjpeg_error_exit1("Write fields failed: %s", y4m_strerr(err)); break; default: mjpeg_error_exit1("Unknown ilace type! %d", cl.interlace); break; } } } for (i = 0; i < 3; i++) { free(buffers[i]); free(buffers2[i]); } y4m_fini_stream_info(&sinfo); y4m_fini_frame_info(&finfo); mjpeg_debug("Done."); return 0;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -