📄 yuv4mpeg.c
字号:
if ((err = y4m_xtag_add(&(i->x_tags), token)) != Y4M_OK) return err; break; default: /* possible error on unknown options */ if (_y4mparam_allow_unknown_tags) { /* unknown tags ok: store in xtag list and warn... */ if ((err = y4m_xtag_add(&(i->x_tags), token)) != Y4M_OK) return err; mp_msg(MSGT_DEMUX, MSGL_WARN, "Unknown stream tag encountered: '%s'\n", token); } else { /* unknown tags are *not* ok */ return Y4M_ERR_BADTAG; } break; } } /* Error checking... width and height must be known since we can't * parse without them */ if( i->width == Y4M_UNKNOWN || i->height == Y4M_UNKNOWN ) return Y4M_ERR_HEADER; /* ta da! done. */ return Y4M_OK;}static int y4m_parse_frame_tags(char *s, y4m_frame_info_t *i){ char *token, *value; char tag; int err; /* parse fields */ for (token = strtok(s, Y4M_DELIM); token != NULL; token = strtok(NULL, Y4M_DELIM)) { if (token[0] == '\0') continue; /* skip empty strings */ tag = token[0]; value = token + 1; switch (tag) { case 'X': /* 'X' meta-tag */ if ((err = y4m_xtag_add(&(i->x_tags), token)) != Y4M_OK) return err; break; default: /* possible error on unknown options */ if (_y4mparam_allow_unknown_tags) { /* unknown tags ok: store in xtag list and warn... */ if ((err = y4m_xtag_add(&(i->x_tags), token)) != Y4M_OK) return err; mp_msg(MSGT_DEMUX, MSGL_WARN, "Unknown frame tag encountered: '%s'\n", token); } else { /* unknown tags are *not* ok */ return Y4M_ERR_BADTAG; } break; } } /* ta da! done. */ return Y4M_OK;}/************************************************************************* * * Read/Write stream header * *************************************************************************/int y4m_read_stream_header(stream_t *s, y4m_stream_info_t *i){ char line[Y4M_LINE_MAX]; char *p; int n; int err; /* read the header line */ for (n = 0, p = line; n < Y4M_LINE_MAX; n++, p++) { if (y4m_read(s, p, 1)) return Y4M_ERR_SYSTEM; if (*p == '\n') { *p = '\0'; /* Replace linefeed by end of string */ break; } } if (n >= Y4M_LINE_MAX) return Y4M_ERR_HEADER; /* look for keyword in header */ if (strncmp(line, Y4M_MAGIC, strlen(Y4M_MAGIC))) return Y4M_ERR_MAGIC; if ((err = y4m_parse_stream_tags(line + strlen(Y4M_MAGIC), i)) != Y4M_OK) return err; i->framelength = (i->height * i->width) * 3 / 2; return Y4M_OK;}#if 0int y4m_write_stream_header(int fd, y4m_stream_info_t *i){ char s[Y4M_LINE_MAX+1]; int n; int err; y4m_ratio_reduce(&(i->framerate)); y4m_ratio_reduce(&(i->sampleaspect)); n = snprintf(s, sizeof(s), "%s W%d H%d F%d:%d I%s A%d:%d", Y4M_MAGIC, i->width, i->height, i->framerate.n, i->framerate.d, (i->interlace == Y4M_ILACE_NONE) ? "p" : (i->interlace == Y4M_ILACE_TOP_FIRST) ? "t" : (i->interlace == Y4M_ILACE_BOTTOM_FIRST) ? "b" : "?", i->sampleaspect.n, i->sampleaspect.d); if ((n < 0) || (n > Y4M_LINE_MAX)) return Y4M_ERR_HEADER; if ((err = y4m_snprint_xtags(s + n, sizeof(s) - n - 1, &(i->x_tags))) != Y4M_OK) return err; /* non-zero on error */ return (y4m_write(fd, s, strlen(s)) ? Y4M_ERR_SYSTEM : Y4M_OK);}#endif/************************************************************************* * * Read/Write frame header * *************************************************************************/int y4m_read_frame_header(stream_t *s, y4m_frame_info_t *i){ char line[Y4M_LINE_MAX]; char *p; int n; ssize_t remain; /* This is more clever than read_stream_header... Try to read "FRAME\n" all at once, and don't try to parse if nothing else is there... */ remain = y4m_read(s, line, sizeof(Y4M_FRAME_MAGIC)); if (remain != 0) { /* A clean EOF should end exactly at a frame-boundary */ if( remain == sizeof(Y4M_FRAME_MAGIC) ) return Y4M_ERR_EOF; else return Y4M_ERR_SYSTEM; } if (strncmp(line, Y4M_FRAME_MAGIC, sizeof(Y4M_FRAME_MAGIC)-1)) return Y4M_ERR_MAGIC; if (line[sizeof(Y4M_FRAME_MAGIC)-1] == '\n') return Y4M_OK; /* done -- no tags: that was the end-of-line. */ if (line[sizeof(Y4M_FRAME_MAGIC)-1] != Y4M_DELIM[0]) { return Y4M_ERR_MAGIC; /* wasn't a space -- what was it? */ } /* proceed to get the tags... (overwrite the magic) */ for (n = 0, p = line; n < Y4M_LINE_MAX; n++, p++) { if (y4m_read(s, p, 1)) return Y4M_ERR_SYSTEM; if (*p == '\n') { *p = '\0'; /* Replace linefeed by end of string */ break; } } if (n >= Y4M_LINE_MAX) return Y4M_ERR_HEADER; /* non-zero on error */ return y4m_parse_frame_tags(line, i);}#if 0int y4m_write_frame_header(int fd, y4m_frame_info_t *i){ char s[Y4M_LINE_MAX+1]; int n; int err; 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, &(i->x_tags))) != Y4M_OK) return err; /* non-zero on error */ return (y4m_write(fd, s, strlen(s)) ? Y4M_ERR_SYSTEM : Y4M_OK);}#endif/************************************************************************* * * Read/Write entire frame * *************************************************************************/int y4m_read_frame(stream_t *s, y4m_stream_info_t *si, y4m_frame_info_t *fi, unsigned char *yuv[3]){ int err; int w = si->width; int h = si->height; /* Read frame header */ if ((err = y4m_read_frame_header(s, fi)) != Y4M_OK) return err; /* Read luminance scanlines */ if (y4m_read(s, yuv[0], w*h)) return Y4M_ERR_SYSTEM; /* Read chrominance scanlines */ if (y4m_read(s, yuv[1], w*h/4)) return Y4M_ERR_SYSTEM; if (y4m_read(s, yuv[2], w*h/4)) return Y4M_ERR_SYSTEM; return Y4M_OK;}#if 0int y4m_write_frame(int fd, y4m_stream_info_t *si, y4m_frame_info_t *fi, unsigned char *yuv[3]){ int err; int w = si->width; int h = si->height; /* Write frame header */ if ((err = y4m_write_frame_header(fd, fi)) != Y4M_OK) return err; /* Write luminance,chrominance scanlines */ if (y4m_write(fd, yuv[0], w*h) || y4m_write(fd, yuv[1], w*h/4) || y4m_write(fd, yuv[2], w*h/4)) return Y4M_ERR_SYSTEM; return Y4M_OK;}#endif/************************************************************************* * * Read/Write entire frame, (de)interleaved (to)from two separate fields * *************************************************************************/#if 0int y4m_read_fields(int fd, y4m_stream_info_t *si, y4m_frame_info_t *fi, unsigned char *upper_field[3], unsigned char *lower_field[3]){ int i, y, err; int width = si->width; int height = si->height; /* Read frame header */ if ((err = y4m_read_frame_header(fd, fi)) != Y4M_OK) return err; /* Read Y', Cb, and Cr planes */ for (i = 0; i < 3; i++) { unsigned char *srctop = upper_field[i]; unsigned char *srcbot = lower_field[i]; /* alternately write one line from each */ for (y = 0; y < height; y += 2) { if (y4m_read(fd, srctop, width)) return Y4M_ERR_SYSTEM; srctop += width; if (y4m_read(fd, srcbot, width)) return Y4M_ERR_SYSTEM; srcbot += width; } /* for chroma, width/height are half as big */ if (i == 0) { width /= 2; height /= 2; } } return Y4M_OK;}int y4m_write_fields(int fd, y4m_stream_info_t *si, y4m_frame_info_t *fi, unsigned char *upper_field[3], unsigned char *lower_field[3]){ int i, y, err; int width = si->width; int height = si->height; /* Write frame header */ if ((err = y4m_write_frame_header(fd, fi)) != Y4M_OK) return err; /* Write Y', Cb, and Cr planes */ for (i = 0; i < 3; i++) { unsigned char *srctop = upper_field[i]; unsigned char *srcbot = lower_field[i]; /* alternately write one line from each */ for (y = 0; y < height; y += 2) { if (y4m_write(fd, srctop, width)) return Y4M_ERR_SYSTEM; srctop += width; if (y4m_write(fd, srcbot, width)) return Y4M_ERR_SYSTEM; srcbot += width; } /* for chroma, width/height are half as big */ if (i == 0) { width /= 2; height /= 2; } } return Y4M_OK;}#endif/************************************************************************* * * Handy logging of stream info * *************************************************************************/void y4m_log_stream_info(const char *prefix, 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); if (i->framelength == Y4M_UNKNOWN) snprintf(s+strlen(s), sizeof(s)-strlen(s), "(? bytes)"); else snprintf(s+strlen(s), sizeof(s)-strlen(s), "(%d bytes)", i->framelength); mp_msg(MSGT_DEMUX, MSGL_V, "%s%s\n", prefix, s); if ((i->framerate.n == 0) && (i->framerate.d == 0)) mp_msg(MSGT_DEMUX, MSGL_V, "%s frame rate: ??? fps\n", prefix); else mp_msg(MSGT_DEMUX, MSGL_V, "%s frame rate: %d/%d fps (~%f)\n", prefix, i->framerate.n, i->framerate.d, (double) i->framerate.n / (double) i->framerate.d); mp_msg(MSGT_DEMUX, MSGL_V, "%s interlace: %s\n", 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" : "anyone's guess"); if ((i->sampleaspect.n == 0) && (i->sampleaspect.d == 0)) mp_msg(MSGT_DEMUX, MSGL_V, "%ssample aspect ratio: ?:?\n", prefix); else mp_msg(MSGT_DEMUX, MSGL_V, "%ssample aspect ratio: %d:%d\n", 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 "stream ended unexpectedly (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"; default: return "unknown error code"; }}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -