📄 yuv4mpeg.c
字号:
/* non-zero on error */ return y4m_parse_frame_tags(line, si, fi);}int y4m_write_frame_header(int fd, const y4m_stream_info_t *si, const y4m_frame_info_t *fi){ char s[Y4M_LINE_MAX+1]; int n, err; if (si->interlace == Y4M_ILACE_MIXED) { if (_y4mparam_feature_level < 1) return Y4M_ERR_FEATURE; n = snprintf(s, sizeof(s), "%s I%c%c%c", Y4M_FRAME_MAGIC, (fi->presentation == Y4M_PRESENT_TOP_FIRST) ? 't' : (fi->presentation == Y4M_PRESENT_TOP_FIRST_RPT) ? 'T' : (fi->presentation == Y4M_PRESENT_BOTTOM_FIRST) ? 'b' : (fi->presentation == Y4M_PRESENT_BOTTOM_FIRST_RPT) ? 'B' : (fi->presentation == Y4M_PRESENT_PROG_SINGLE) ? '1' : (fi->presentation == Y4M_PRESENT_PROG_DOUBLE) ? '2' : (fi->presentation == Y4M_PRESENT_PROG_TRIPLE) ? '3' : '?', (fi->temporal == Y4M_SAMPLING_PROGRESSIVE) ? 'p' : (fi->temporal == Y4M_SAMPLING_INTERLACED) ? 'i' : '?', (fi->spatial == Y4M_SAMPLING_PROGRESSIVE) ? 'p' : (fi->spatial == Y4M_SAMPLING_INTERLACED) ? 'i' : '?' ); } else { n = snprintf(s, sizeof(s), "%s", Y4M_FRAME_MAGIC); } if ((n < 0) || (n > Y4M_LINE_MAX)) return Y4M_ERR_HEADER; if ((err = y4m_snprint_xtags(s + n, sizeof(s) - n - 1, &(fi->x_tags))) != Y4M_OK) return err; /* non-zero on error */ return (y4m_write(fd, s, strlen(s)) ? Y4M_ERR_SYSTEM : Y4M_OK);}/************************************************************************* * * Read/Write entire frame * *************************************************************************/int y4m_read_frame_data(int fd, const y4m_stream_info_t *si, y4m_frame_info_t *fi, uint8_t * const *frame){ int planes = y4m_si_get_plane_count(si); int p; /* Read each plane */ for (p = 0; p < planes; p++) { int w = y4m_si_get_plane_width(si, p); int h = y4m_si_get_plane_height(si, p); if (y4m_read(fd, frame[p], w*h)) return Y4M_ERR_SYSTEM; } return Y4M_OK;}int y4m_read_frame(int fd, const y4m_stream_info_t *si, y4m_frame_info_t *fi, uint8_t * const *frame){ int err; /* Read frame header */ if ((err = y4m_read_frame_header(fd, si, fi)) != Y4M_OK) return err; /* Read date */ return y4m_read_frame_data(fd, si, fi, frame);}int y4m_write_frame(int fd, const y4m_stream_info_t *si, const y4m_frame_info_t *fi, uint8_t * const *frame){ int planes = y4m_si_get_plane_count(si); int err, p; /* Write frame header */ if ((err = y4m_write_frame_header(fd, si, fi)) != Y4M_OK) return err; /* Write each plane */ for (p = 0; p < planes; p++) { int w = y4m_si_get_plane_width(si, p); int h = y4m_si_get_plane_height(si, p); if (y4m_write(fd, frame[p], w*h)) return Y4M_ERR_SYSTEM; } return Y4M_OK;}/************************************************************************* * * Read/Write entire frame, (de)interleaved (to)from two separate fields * *************************************************************************/int y4m_read_fields_data(int fd, const y4m_stream_info_t *si, y4m_frame_info_t *fi, uint8_t * const *upper_field, uint8_t * const *lower_field){ int p; int planes = y4m_si_get_plane_count(si); const int maxrbuf=32*1024; uint8_t *rbuf=_y4m_alloc(maxrbuf); int rbufpos=0,rbuflen=0; /* Read each plane */ for (p = 0; p < planes; p++) { uint8_t *dsttop = upper_field[p]; uint8_t *dstbot = lower_field[p]; int height = y4m_si_get_plane_height(si, p); int width = y4m_si_get_plane_width(si, p); int y; /* alternately read one line into each field */ for (y = 0; y < height; y += 2) { if( width*2 >= maxrbuf ) { if (y4m_read(fd, dsttop, width)) goto y4merr; if (y4m_read(fd, dstbot, width)) goto y4merr; } else { if( rbufpos==rbuflen ) { rbuflen=(height-y)*width; if( rbuflen>maxrbuf ) rbuflen=maxrbuf-maxrbuf%(2*width); if( y4m_read(fd,rbuf,rbuflen) ) goto y4merr; rbufpos=0; } memcpy(dsttop,rbuf+rbufpos,width); rbufpos+=width; memcpy(dstbot,rbuf+rbufpos,width); rbufpos+=width; } dsttop+=width; dstbot+=width; } } _y4m_free(rbuf); return Y4M_OK; y4merr: _y4m_free(rbuf); return Y4M_ERR_SYSTEM;}int y4m_read_fields(int fd, const y4m_stream_info_t *si, y4m_frame_info_t *fi, uint8_t * const *upper_field, uint8_t * const *lower_field){ int err; /* Read frame header */ if ((err = y4m_read_frame_header(fd, si, fi)) != Y4M_OK) return err; /* Read data */ return y4m_read_fields_data(fd, si, fi, upper_field, lower_field);}int y4m_write_fields(int fd, const y4m_stream_info_t *si, const y4m_frame_info_t *fi, uint8_t * const *upper_field, uint8_t * const *lower_field){ int p, err; int planes = y4m_si_get_plane_count(si); int numwbuf=0; const int maxwbuf=32*1024; uint8_t *wbuf; /* Write frame header */ if ((err = y4m_write_frame_header(fd, si, fi)) != Y4M_OK) return err; /* Write each plane */ wbuf=_y4m_alloc(maxwbuf); for (p = 0; p < planes; p++) { uint8_t *srctop = upper_field[p]; uint8_t *srcbot = lower_field[p]; int height = y4m_si_get_plane_height(si, p); int width = y4m_si_get_plane_width(si, p); int y; /* alternately write one line from each field */ for (y = 0; y < height; y += 2) { if( width*2 >= maxwbuf ) { if (y4m_write(fd, srctop, width)) goto y4merr; if (y4m_write(fd, srcbot, width)) goto y4merr; } else { if (numwbuf + 2 * width > maxwbuf) { if(y4m_write(fd, wbuf, numwbuf)) goto y4merr; numwbuf=0; } memcpy(wbuf+numwbuf,srctop,width); numwbuf += width; memcpy(wbuf+numwbuf,srcbot,width); numwbuf += width; } srctop += width; srcbot += width; } } if( numwbuf ) if( y4m_write(fd, wbuf, numwbuf) ) goto y4merr; _y4m_free(wbuf); return Y4M_OK; y4merr: _y4m_free(wbuf); return Y4M_ERR_SYSTEM;}/************************************************************************* * * Handy logging of stream info * *************************************************************************/void y4m_log_stream_info(log_level_t level, const char *prefix, const y4m_stream_info_t *i){ char s[256]; snprintf(s, sizeof(s), " frame size: "); if (i->width == Y4M_UNKNOWN) snprintf(s+strlen(s), sizeof(s)-strlen(s), "(?)x"); else snprintf(s+strlen(s), sizeof(s)-strlen(s), "%dx", i->width); if (i->height == Y4M_UNKNOWN) snprintf(s+strlen(s), sizeof(s)-strlen(s), "(?) pixels "); else snprintf(s+strlen(s), sizeof(s)-strlen(s), "%d pixels ", i->height); { int framelength = y4m_si_get_framelength(i); if (framelength == Y4M_UNKNOWN) snprintf(s+strlen(s), sizeof(s)-strlen(s), "(? bytes)"); else snprintf(s+strlen(s), sizeof(s)-strlen(s), "(%d bytes)", framelength); mjpeg_log(level, "%s%s", prefix, s); } { const char *desc = y4m_chroma_description(i->chroma); if (desc == NULL) desc = "unknown!"; mjpeg_log(level, "%s chroma: %s", prefix, desc); } if ((i->framerate.n == 0) && (i->framerate.d == 0)) mjpeg_log(level, "%s frame rate: ??? fps", prefix); else mjpeg_log(level, "%s frame rate: %d/%d fps (~%f)", prefix, i->framerate.n, i->framerate.d, (double) i->framerate.n / (double) i->framerate.d); mjpeg_log(level, "%s interlace: %s", prefix, (i->interlace == Y4M_ILACE_NONE) ? "none/progressive" : (i->interlace == Y4M_ILACE_TOP_FIRST) ? "top-field-first" : (i->interlace == Y4M_ILACE_BOTTOM_FIRST) ? "bottom-field-first" : (i->interlace == Y4M_ILACE_MIXED) ? "mixed-mode" : "anyone's guess"); if ((i->sampleaspect.n == 0) && (i->sampleaspect.d == 0)) mjpeg_log(level, "%ssample aspect ratio: ?:?", prefix); else mjpeg_log(level, "%ssample aspect ratio: %d:%d", prefix, i->sampleaspect.n, i->sampleaspect.d);}/************************************************************************* * * Convert error code to string * *************************************************************************/const char *y4m_strerr(int err){ switch (err) { case Y4M_OK: return "no error"; case Y4M_ERR_RANGE: return "parameter out of range"; case Y4M_ERR_SYSTEM: return "system error (failed read/write)"; case Y4M_ERR_HEADER: return "bad stream or frame header"; case Y4M_ERR_BADTAG: return "unknown header tag"; case Y4M_ERR_MAGIC: return "bad header magic"; case Y4M_ERR_XXTAGS: return "too many xtags"; case Y4M_ERR_EOF: return "end-of-file"; case Y4M_ERR_BADEOF: return "stream ended unexpectedly (EOF)"; case Y4M_ERR_FEATURE: return "stream requires unsupported features"; default: return "unknown error code"; }}/************************************************************************* * * Chroma subsampling stuff * *************************************************************************/y4m_ratio_t y4m_chroma_ss_x_ratio(int chroma_mode){ y4m_ratio_t r; switch (chroma_mode) { case Y4M_CHROMA_444ALPHA: case Y4M_CHROMA_444: case Y4M_CHROMA_MONO: r.n = 1; r.d = 1; break; case Y4M_CHROMA_420JPEG: case Y4M_CHROMA_420MPEG2: case Y4M_CHROMA_420PALDV: case Y4M_CHROMA_422: r.n = 1; r.d = 2; break; case Y4M_CHROMA_411: r.n = 1; r.d = 4; break; default: r.n = 0; r.d = 0; } return r;}y4m_ratio_t y4m_chroma_ss_y_ratio(int chroma_mode){ y4m_ratio_t r; switch (chroma_mode) { case Y4M_CHROMA_444ALPHA: case Y4M_CHROMA_444: case Y4M_CHROMA_MONO: case Y4M_CHROMA_422: case Y4M_CHROMA_411: r.n = 1; r.d = 1; break; case Y4M_CHROMA_420JPEG: case Y4M_CHROMA_420MPEG2: case Y4M_CHROMA_420PALDV: r.n = 1; r.d = 2; break; default: r.n = 0; r.d = 0; } return r;}#if 0 /* unfinished work here */y4m_ratio_t y4m_chroma_ss_x_offset(int chroma_mode, int field, int plane){ y4m_ratio_t r; switch (chroma_mode) { case Y4M_CHROMA_444ALPHA: case Y4M_CHROMA_444: case Y4M_CHROMA_MONO: case Y4M_CHROMA_422: case Y4M_CHROMA_411: r.n = 0; r.d = 1; break; case Y4M_CHROMA_420JPEG: case Y4M_CHROMA_420MPEG2: case Y4M_CHROMA_420PALDV: r.n = 1; r.d = 2; break; default: r.n = 0; r.d = 0; } return r;}y4m_ratio_t y4m_chroma_ss_y_offset(int chroma_mode, int field, int plane);{ y4m_ratio_t r; switch (chroma_mode) { case Y4M_CHROMA_444ALPHA: case Y4M_CHROMA_444: case Y4M_CHROMA_MONO: case Y4M_CHROMA_422: case Y4M_CHROMA_411: r.n = 0; r.d = 1; break; case Y4M_CHROMA_420JPEG: case Y4M_CHROMA_420MPEG2: case Y4M_CHROMA_420PALDV: r.n = 1; r.d = 2; break; default: r.n = 0; r.d = 0; } return r;}#endifint y4m_chroma_parse_keyword(const char *s){ if (!strcasecmp("420jpeg", s)) return Y4M_CHROMA_420JPEG; else if (!strcasecmp("420mpeg2", s)) return Y4M_CHROMA_420MPEG2; else if (!strcasecmp("420paldv", s)) return Y4M_CHROMA_420PALDV; else if (!strcasecmp("444", s)) return Y4M_CHROMA_444; else if (!strcasecmp("422", s)) return Y4M_CHROMA_422; else if (!strcasecmp("411", s)) return Y4M_CHROMA_411; else if (!strcasecmp("mono", s)) return Y4M_CHROMA_MONO; else if (!strcasecmp("444alpha", s)) return Y4M_CHROMA_444ALPHA; else return Y4M_UNKNOWN;}const char *y4m_chroma_keyword(int chroma_mode){ switch (chroma_mode) { case Y4M_CHROMA_420JPEG: return "420jpeg"; case Y4M_CHROMA_420MPEG2: return "420mpeg2"; case Y4M_CHROMA_420PALDV: return "420paldv"; case Y4M_CHROMA_444: return "444"; case Y4M_CHROMA_422: return "422"; case Y4M_CHROMA_411: return "411"; case Y4M_CHROMA_MONO: return "mono"; case Y4M_CHROMA_444ALPHA: return "444alpha"; default: return NULL; }} const char *y4m_chroma_description(int chroma_mode){ switch (chroma_mode) { case Y4M_CHROMA_420JPEG: return "4:2:0 JPEG/MPEG-1 (interstitial)"; case Y4M_CHROMA_420MPEG2: return "4:2:0 MPEG-2 (horiz. cositing)"; case Y4M_CHROMA_420PALDV: return "4:2:0 PAL-DV (altern. siting)"; case Y4M_CHROMA_444: return "4:4:4 (no subsampling)"; case Y4M_CHROMA_422: return "4:2:2 (horiz. cositing)"; case Y4M_CHROMA_411: return "4:1:1 (horiz. cositing)"; case Y4M_CHROMA_MONO: return "luma plane only"; case Y4M_CHROMA_444ALPHA: return "4:4:4 with alpha channel"; default: return NULL; }}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -