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
100100 return 0;
101101 }
102102
103+// Copy a single tag into the buffer, along with a null character.
104+// Returns 0 if any file IO errors occur.
105+static 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+
103141 /* Returns 1 if tags were parsed successfully, 0 otherwise. */
104−static int parse_tags(y4m_input *y4m_ctx, char *buffer) {
142+static 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'. */
105145 /* Set Y4M tags to defaults, updating them as processing occurs. Mandatory
106146 fields are marked with -1 and will be checked after the tags are parsed. */
107− int ret;
108147 y4m_ctx->pic_w = -1;
109148 y4m_ctx->pic_h = -1;
110149 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
113152 y4m_ctx->interlace = '?';
114153 snprintf(y4m_ctx->chroma_type, sizeof(y4m_ctx->chroma_type), "420");
115154
116− ret = y4m_parse_tags(y4m_ctx, buffer);
117− if (ret < 0) {
118− return 0;
119− }
155+ /* Find one tag at a time. */
156+ do {
157+ if (!copy_tag(tag, sizeof(tag), &end, file)) {
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');
120165
121166 /* Check the mandatory fields. */
122167 if (y4m_ctx->pic_w == -1) {
@@ -801,15 +846,11 @@ static void y4m_convert_null(y4m_input *_y4m, unsigned char *_dst, · 678 unmodified lines
801846 }
802847
803848 static const char TAG[] = "YUV4MPEG2";
804−/* Temporary until arbitrary header parsing submitted. */
805−#define Y4M_HEADER_BUF_SIZE 200
806849
807850 int y4m_input_open(y4m_input *y4m_ctx, FILE *file, char *skip_buffer,
808851 int num_skip, int only_420) {
809852 // File must start with |TAG|.
810− char tag_buffer[9]; // 9 == strlen(TAG)
811− char buffer[Y4M_HEADER_BUF_SIZE] = { 0 }; // Rest of header.
812− int i;
853+ char tag_buffer[9]; // 9 == strlen(TAG)
813854 // Read as much as possible from |skip_buffer|, which were characters
814855 // that were previously read from the file to do input-type detection.
815856 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
825866 return -1;
826867 }
827868 // 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] != ' ') {
829870 fprintf(stderr, "Error parsing header: space must follow %s\n", TAG);
830871 return -1;
831872 }
832− /*Read until newline, or Y4M_HEADER_BUF_SIZE cols, whichever happens first.*/
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)) {
873+ if (!parse_tags(y4m_ctx, file)) {
843874 fprintf(stderr, "Error parsing %s header.\n", TAG);
844− return -1;
845875 }
846876 if (y4m_ctx->interlace == '?') {
847877 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