History

Relax constraints on Y4M header parsing

Previous parser assumed that the header would not exceed 80 characters. However, with latest FFMPEG changes, the header of Y4M files can exceed this limit. New parser can parse an arbitrarily long header, as long each tag is 255 or less characters. BUG=aomedia:2876

Elliott Karpilovsky committed 5 years ago

Commit 61edec11 parent ebb5ffc1 file · +54 −24Browse files

Unified · Split

y4minput.c+54−24
@@ -100,11 +100,50 @@ static int y4m_parse_tags(y4m_input *_y4m, char *_tags) { · 99 unmodified lines
100 return 0;100 return 0;
101}101}
102 102
103// Copy a single tag into the buffer, along with a null character.
104// Returns 0 if any file IO errors occur.
105static int copy_tag(char *buf, size_t buf_len, char *end_tag, FILE *file) {
106 size_t i;
107 assert(buf_len >= 1);
108 // Skip leading space characters.
109 do {
110 if (!file_read(buf, 1, file)) {
111 return 0;
112 }
113 } while (buf[0] == ' ');
114
115 // If we hit the newline, treat this as the "empty" tag.
116 if (buf[0] == '\n') {
117 buf[0] = '\0';
118 *end_tag = '\n';
119 return 1;
120 }
121
122 // Copy over characters until a space is hit, or the buffer is exhausted.
123 for (i = 1; i < buf_len; ++i) {
124 if (!file_read(buf + i, 1, file)) {
125 return 0;
126 }
127 if (buf[i] == ' ' || buf[i] == '\n') {
128 break;
129 }
130 }
131 if (i == buf_len) {
132 fprintf(stderr, "Error: Y4M header tags must be less than %lu characters\n",
133 (unsigned long)i);
134 return 0;
135 }
136 *end_tag = buf[i];
137 buf[i] = '\0';
138 return 1;
139}
140
103/* Returns 1 if tags were parsed successfully, 0 otherwise. */141/* Returns 1 if tags were parsed successfully, 0 otherwise. */
104static int parse_tags(y4m_input *y4m_ctx, char *buffer) {142static int parse_tags(y4m_input *y4m_ctx, FILE *file) {
143 char tag[256];
144 char end; /* Character denoting the end of the tag, ' ' or '\n'. */
105 /* Set Y4M tags to defaults, updating them as processing occurs. Mandatory145 /* Set Y4M tags to defaults, updating them as processing occurs. Mandatory
106 fields are marked with -1 and will be checked after the tags are parsed. */146 fields are marked with -1 and will be checked after the tags are parsed. */
107 int ret;
108 y4m_ctx->pic_w = -1;147 y4m_ctx->pic_w = -1;
109 y4m_ctx->pic_h = -1;148 y4m_ctx->pic_h = -1;
110 y4m_ctx->fps_n = -1; /* Also serves as marker for fps_d */149 y4m_ctx->fps_n = -1; /* Also serves as marker for fps_d */
@@ -113,10 +152,16 @@ static int parse_tags(y4m_input *y4m_ctx, char *buffer) { · 2 unmodified lines
113 y4m_ctx->interlace = '?';152 y4m_ctx->interlace = '?';
114 snprintf(y4m_ctx->chroma_type, sizeof(y4m_ctx->chroma_type), "420");153 snprintf(y4m_ctx->chroma_type, sizeof(y4m_ctx->chroma_type), "420");
115 154
116 ret = y4m_parse_tags(y4m_ctx, buffer);155 /* Find one tag at a time. */
117 if (ret < 0) {156 do {
118 return 0;157 if (!copy_tag(tag, sizeof(tag), &end, file)) {
119 }158 return 0;
159 }
160 /* y4m_parse_tags returns 0 on success. */
161 if (y4m_parse_tags(y4m_ctx, tag)) {
162 return 0;
163 }
164 } while (end != '\n');
120 165
121 /* Check the mandatory fields. */166 /* Check the mandatory fields. */
122 if (y4m_ctx->pic_w == -1) {167 if (y4m_ctx->pic_w == -1) {
@@ -801,15 +846,11 @@ static void y4m_convert_null(y4m_input *_y4m, unsigned char *_dst, · 678 unmodified lines
801}846}
802 847
803static const char TAG[] = "YUV4MPEG2";848static const char TAG[] = "YUV4MPEG2";
804/* Temporary until arbitrary header parsing submitted. */
805#define Y4M_HEADER_BUF_SIZE 200
806 849
807int y4m_input_open(y4m_input *y4m_ctx, FILE *file, char *skip_buffer,850int y4m_input_open(y4m_input *y4m_ctx, FILE *file, char *skip_buffer,
808 int num_skip, int only_420) {851 int num_skip, int only_420) {
809 // File must start with |TAG|.852 // File must start with |TAG|.
810 char tag_buffer[9]; // 9 == strlen(TAG)853 char tag_buffer[9]; // 9 == strlen(TAG)
811 char buffer[Y4M_HEADER_BUF_SIZE] = { 0 }; // Rest of header.
812 int i;
813 // Read as much as possible from |skip_buffer|, which were characters854 // Read as much as possible from |skip_buffer|, which were characters
814 // that were previously read from the file to do input-type detection.855 // that were previously read from the file to do input-type detection.
815 assert(num_skip >= 0 && num_skip <= 8);856 assert(num_skip >= 0 && num_skip <= 8);
@@ -825,23 +866,12 @@ int y4m_input_open(y4m_input *y4m_ctx, FILE *file, char *skip_buffer, · 9 unmodified lines
825 return -1;866 return -1;
826 }867 }
827 // Next character must be a space.868 // Next character must be a space.
828 if (!file_read(buffer, 1, file) || buffer[0] != ' ') {869 if (!file_read(tag_buffer, 1, file) || tag_buffer[0] != ' ') {
829 fprintf(stderr, "Error parsing header: space must follow %s\n", TAG);870 fprintf(stderr, "Error parsing header: space must follow %s\n", TAG);
830 return -1;871 return -1;
831 }872 }
832 /*Read until newline, or Y4M_HEADER_BUF_SIZE cols, whichever happens first.*/873 if (!parse_tags(y4m_ctx, file)) {
833 for (i = 0; i < Y4M_HEADER_BUF_SIZE - 1; i++) {
834 if (!file_read(buffer + i, 1, file)) return -1;
835 if (buffer[i] == '\n') break;
836 }
837 if (i == Y4M_HEADER_BUF_SIZE - 1) {
838 fprintf(stderr, "Error parsing header; not a %s file?\n", TAG);
839 return -1;
840 }
841 buffer[i] = '\0';
842 if (!parse_tags(y4m_ctx, buffer)) {
843 fprintf(stderr, "Error parsing %s header.\n", TAG);874 fprintf(stderr, "Error parsing %s header.\n", TAG);
844 return -1;
845 }875 }
846 if (y4m_ctx->interlace == '?') {876 if (y4m_ctx->interlace == '?') {
847 fprintf(stderr,877 fprintf(stderr,

Keyboard shortcuts

General

Show keyboard shortcuts
?
Focus the current search
/

Issues and pull requests

Open filters
f

Issues, pull requests and Inbox

Select next item
j↓
Select previous item
k↑
Open selected item
Enter
Dismiss filters or clear selection
Esc

Repository code

Go to file
t