00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00035 #include "libavutil/crc.h"
00036 #include "libavutil/fifo.h"
00037 #include "bytestream.h"
00038 #include "parser.h"
00039 #include "flac.h"
00040
00042 #define FLAC_MAX_SEQUENTIAL_HEADERS 3
00043
00044 #define FLAC_MIN_HEADERS 10
00045
00046 #define FLAC_AVG_FRAME_SIZE 8192
00047
00049 #define FLAC_HEADER_BASE_SCORE 10
00050 #define FLAC_HEADER_CHANGED_PENALTY 7
00051 #define FLAC_HEADER_CRC_FAIL_PENALTY 50
00052 #define FLAC_HEADER_NOT_PENALIZED_YET 100000
00053 #define FLAC_HEADER_NOT_SCORED_YET -100000
00054
00056 #define MAX_FRAME_HEADER_SIZE 16
00057
00058 typedef struct FLACHeaderMarker {
00059 int offset;
00060 int *link_penalty;
00062 int max_score;
00064 FLACFrameInfo fi;
00065 struct FLACHeaderMarker *next;
00068 struct FLACHeaderMarker *best_child;
00071 } FLACHeaderMarker;
00072
00073 typedef struct FLACParseContext {
00074 AVCodecContext *avctx;
00075 FLACHeaderMarker *headers;
00077 FLACHeaderMarker *best_header;
00078 int nb_headers_found;
00080 int nb_headers_buffered;
00081 int best_header_valid;
00083 AVFifoBuffer *fifo_buf;
00085 int end_padded;
00086 uint8_t *wrap_buf;
00087 int wrap_buf_allocated_size;
00088 } FLACParseContext;
00089
00090 static int frame_header_is_valid(AVCodecContext *avctx, const uint8_t *buf,
00091 FLACFrameInfo *fi)
00092 {
00093 GetBitContext gb;
00094 init_get_bits(&gb, buf, MAX_FRAME_HEADER_SIZE * 8);
00095 return !ff_flac_decode_frame_header(avctx, &gb, fi, 127);
00096 }
00097
00111 static uint8_t* flac_fifo_read_wrap(FLACParseContext *fpc, int offset, int len,
00112 uint8_t** wrap_buf, int* allocated_size)
00113 {
00114 AVFifoBuffer *f = fpc->fifo_buf;
00115 uint8_t *start = f->rptr + offset;
00116 uint8_t *tmp_buf;
00117
00118 if (start >= f->end)
00119 start -= f->end - f->buffer;
00120 if (f->end - start >= len)
00121 return start;
00122
00123 tmp_buf = av_fast_realloc(*wrap_buf, allocated_size, len);
00124
00125 if (!tmp_buf) {
00126 av_log(fpc->avctx, AV_LOG_ERROR,
00127 "couldn't reallocate wrap buffer of size %d", len);
00128 return NULL;
00129 }
00130 *wrap_buf = tmp_buf;
00131 do {
00132 int seg_len = FFMIN(f->end - start, len);
00133 memcpy(tmp_buf, start, seg_len);
00134 tmp_buf = (uint8_t*)tmp_buf + seg_len;
00135
00136
00137 start += seg_len - (f->end - f->buffer);
00138 len -= seg_len;
00139 } while (len > 0);
00140
00141 return *wrap_buf;
00142 }
00143
00151 static uint8_t* flac_fifo_read(FLACParseContext *fpc, int offset, int *len)
00152 {
00153 AVFifoBuffer *f = fpc->fifo_buf;
00154 uint8_t *start = f->rptr + offset;
00155
00156 if (start >= f->end)
00157 start -= f->end - f->buffer;
00158 *len = FFMIN(*len, f->end - start);
00159 return start;
00160 }
00161
00162 static int find_headers_search_validate(FLACParseContext *fpc, int offset)
00163 {
00164 FLACFrameInfo fi;
00165 uint8_t *header_buf;
00166 int size = 0;
00167 header_buf = flac_fifo_read_wrap(fpc, offset,
00168 MAX_FRAME_HEADER_SIZE,
00169 &fpc->wrap_buf,
00170 &fpc->wrap_buf_allocated_size);
00171 if (frame_header_is_valid(fpc->avctx, header_buf, &fi)) {
00172 FLACHeaderMarker **end_handle = &fpc->headers;
00173 int i;
00174
00175 size = 0;
00176 while (*end_handle) {
00177 end_handle = &(*end_handle)->next;
00178 size++;
00179 }
00180
00181 *end_handle = av_mallocz(sizeof(FLACHeaderMarker));
00182 if (!*end_handle) {
00183 av_log(fpc->avctx, AV_LOG_ERROR,
00184 "couldn't allocate FLACHeaderMarker\n");
00185 return AVERROR(ENOMEM);
00186 }
00187 (*end_handle)->fi = fi;
00188 (*end_handle)->offset = offset;
00189 (*end_handle)->link_penalty = av_malloc(sizeof(int) *
00190 FLAC_MAX_SEQUENTIAL_HEADERS);
00191 for (i = 0; i < FLAC_MAX_SEQUENTIAL_HEADERS; i++)
00192 (*end_handle)->link_penalty[i] = FLAC_HEADER_NOT_PENALIZED_YET;
00193
00194 fpc->nb_headers_found++;
00195 size++;
00196 }
00197 return size;
00198 }
00199
00200 static int find_headers_search(FLACParseContext *fpc, uint8_t *buf, int buf_size,
00201 int search_start)
00202
00203 {
00204 int size = 0, mod_offset = (buf_size - 1) % 4, i, j;
00205 uint32_t x;
00206
00207 for (i = 0; i < mod_offset; i++) {
00208 if ((AV_RB16(buf + i) & 0xFFFE) == 0xFFF8)
00209 size = find_headers_search_validate(fpc, search_start + i);
00210 }
00211
00212 for (; i < buf_size - 1; i += 4) {
00213 x = AV_RB32(buf + i);
00214 if (((x & ~(x + 0x01010101)) & 0x80808080)) {
00215 for (j = 0; j < 4; j++) {
00216 if ((AV_RB16(buf + i + j) & 0xFFFE) == 0xFFF8)
00217 size = find_headers_search_validate(fpc, search_start + i + j);
00218 }
00219 }
00220 }
00221 return size;
00222 }
00223
00224 static int find_new_headers(FLACParseContext *fpc, int search_start)
00225 {
00226 FLACHeaderMarker *end;
00227 int search_end, size = 0, read_len, temp;
00228 uint8_t *buf;
00229 fpc->nb_headers_found = 0;
00230
00231
00232 search_end = av_fifo_size(fpc->fifo_buf) - (MAX_FRAME_HEADER_SIZE - 1);
00233 read_len = search_end - search_start + 1;
00234 buf = flac_fifo_read(fpc, search_start, &read_len);
00235 size = find_headers_search(fpc, buf, read_len, search_start);
00236 search_start += read_len - 1;
00237
00238
00239 if (search_start != search_end) {
00240 uint8_t wrap[2];
00241
00242 wrap[0] = buf[read_len - 1];
00243 read_len = search_end - search_start + 1;
00244
00245
00246 buf = flac_fifo_read(fpc, search_start + 1, &read_len);
00247 wrap[1] = buf[0];
00248
00249 if ((AV_RB16(wrap) & 0xFFFE) == 0xFFF8) {
00250 temp = find_headers_search_validate(fpc, search_start);
00251 size = FFMAX(size, temp);
00252 }
00253 search_start++;
00254
00255
00256 temp = find_headers_search(fpc, buf, read_len, search_start);
00257 size = FFMAX(size, temp);
00258 search_start += read_len - 1;
00259 }
00260
00261
00262 if (!size && fpc->headers)
00263 for (end = fpc->headers; end; end = end->next)
00264 size++;
00265 return size;
00266 }
00267
00268 static int check_header_mismatch(FLACParseContext *fpc,
00269 FLACHeaderMarker *header,
00270 FLACHeaderMarker *child,
00271 int log_level_offset)
00272 {
00273 FLACFrameInfo *header_fi = &header->fi, *child_fi = &child->fi;
00274 int deduction = 0, deduction_expected = 0, i;
00275 if (child_fi->samplerate != header_fi->samplerate) {
00276 deduction += FLAC_HEADER_CHANGED_PENALTY;
00277 av_log(fpc->avctx, AV_LOG_WARNING + log_level_offset,
00278 "sample rate change detected in adjacent frames\n");
00279 }
00280 if (child_fi->bps != header_fi->bps) {
00281 deduction += FLAC_HEADER_CHANGED_PENALTY;
00282 av_log(fpc->avctx, AV_LOG_WARNING + log_level_offset,
00283 "bits per sample change detected in adjacent frames\n");
00284 }
00285 if (child_fi->is_var_size != header_fi->is_var_size) {
00286
00287 deduction += FLAC_HEADER_BASE_SCORE;
00288 av_log(fpc->avctx, AV_LOG_WARNING + log_level_offset,
00289 "blocking strategy change detected in adjacent frames\n");
00290 }
00291 if (child_fi->channels != header_fi->channels) {
00292 deduction += FLAC_HEADER_CHANGED_PENALTY;
00293 av_log(fpc->avctx, AV_LOG_WARNING + log_level_offset,
00294 "number of channels change detected in adjacent frames\n");
00295 }
00296
00297 if ((child_fi->frame_or_sample_num - header_fi->frame_or_sample_num
00298 != header_fi->blocksize) &&
00299 (child_fi->frame_or_sample_num
00300 != header_fi->frame_or_sample_num + 1)) {
00301 FLACHeaderMarker *curr;
00302 int expected_frame_num, expected_sample_num;
00303
00304
00305
00306 expected_frame_num = expected_sample_num = header_fi->frame_or_sample_num;
00307 curr = header;
00308 while (curr != child) {
00309
00310 for (i = 0; i < FLAC_MAX_SEQUENTIAL_HEADERS; i++) {
00311 if (curr->link_penalty[i] < FLAC_HEADER_CRC_FAIL_PENALTY) {
00312 expected_frame_num++;
00313 expected_sample_num += curr->fi.blocksize;
00314 break;
00315 }
00316 }
00317 curr = curr->next;
00318 }
00319
00320 if (expected_frame_num == child_fi->frame_or_sample_num ||
00321 expected_sample_num == child_fi->frame_or_sample_num)
00322 deduction_expected = deduction ? 0 : 1;
00323
00324 deduction += FLAC_HEADER_CHANGED_PENALTY;
00325 av_log(fpc->avctx, AV_LOG_WARNING + log_level_offset,
00326 "sample/frame number mismatch in adjacent frames\n");
00327 }
00328
00329
00330 if (deduction && !deduction_expected) {
00331 FLACHeaderMarker *curr;
00332 int read_len;
00333 uint8_t *buf;
00334 uint32_t crc = 1;
00335 int inverted_test = 0;
00336
00337
00338
00339 curr = header->next;
00340 for (i = 0; i < FLAC_MAX_SEQUENTIAL_HEADERS && curr != child; i++)
00341 curr = curr->next;
00342
00343 if (header->link_penalty[i] < FLAC_HEADER_CRC_FAIL_PENALTY ||
00344 header->link_penalty[i] == FLAC_HEADER_NOT_PENALIZED_YET) {
00345 FLACHeaderMarker *start, *end;
00346
00347
00348
00349 start = header;
00350 end = child;
00351 if (i > 0 &&
00352 header->link_penalty[i - 1] >= FLAC_HEADER_CRC_FAIL_PENALTY) {
00353 while (start->next != child)
00354 start = start->next;
00355 inverted_test = 1;
00356 } else if (i > 0 &&
00357 header->next->link_penalty[i-1] >=
00358 FLAC_HEADER_CRC_FAIL_PENALTY ) {
00359 end = header->next;
00360 inverted_test = 1;
00361 }
00362
00363 read_len = end->offset - start->offset;
00364 buf = flac_fifo_read(fpc, start->offset, &read_len);
00365 crc = av_crc(av_crc_get_table(AV_CRC_16_ANSI), 0, buf, read_len);
00366 read_len = (end->offset - start->offset) - read_len;
00367
00368 if (read_len) {
00369 buf = flac_fifo_read(fpc, end->offset - read_len, &read_len);
00370 crc = av_crc(av_crc_get_table(AV_CRC_16_ANSI), crc, buf, read_len);
00371 }
00372 }
00373
00374 if (!crc ^ !inverted_test) {
00375 deduction += FLAC_HEADER_CRC_FAIL_PENALTY;
00376 av_log(fpc->avctx, AV_LOG_WARNING + log_level_offset,
00377 "crc check failed from offset %i (frame %"PRId64") to %i (frame %"PRId64")\n",
00378 header->offset, header_fi->frame_or_sample_num,
00379 child->offset, child_fi->frame_or_sample_num);
00380 }
00381 }
00382 return deduction;
00383 }
00384
00395 static int score_header(FLACParseContext *fpc, FLACHeaderMarker *header)
00396 {
00397 FLACHeaderMarker *child;
00398 int dist = 0;
00399 int child_score;
00400
00401 if (header->max_score != FLAC_HEADER_NOT_SCORED_YET)
00402 return header->max_score;
00403
00404 header->max_score = FLAC_HEADER_BASE_SCORE;
00405
00406
00407 child = header->next;
00408 for (dist = 0; dist < FLAC_MAX_SEQUENTIAL_HEADERS && child; dist++) {
00409
00410
00411 if (header->link_penalty[dist] == FLAC_HEADER_NOT_PENALIZED_YET) {
00412 header->link_penalty[dist] = check_header_mismatch(fpc, header,
00413 child, AV_LOG_DEBUG);
00414 }
00415 child_score = score_header(fpc, child) - header->link_penalty[dist];
00416
00417 if (FLAC_HEADER_BASE_SCORE + child_score > header->max_score) {
00418
00419 header->best_child = child;
00420 header->max_score = FLAC_HEADER_BASE_SCORE + child_score;
00421 }
00422 child = child->next;
00423 }
00424
00425 return header->max_score;
00426 }
00427
00428 static void score_sequences(FLACParseContext *fpc)
00429 {
00430 FLACHeaderMarker *curr;
00431 int best_score = FLAC_HEADER_NOT_SCORED_YET;
00432
00433 for (curr = fpc->headers; curr; curr = curr->next)
00434 curr->max_score = FLAC_HEADER_NOT_SCORED_YET;
00435
00436
00437 for (curr = fpc->headers; curr; curr = curr->next) {
00438 if (score_header(fpc, curr) > best_score) {
00439 fpc->best_header = curr;
00440 best_score = curr->max_score;
00441 }
00442 }
00443 }
00444
00445 static int get_best_header(FLACParseContext* fpc, const uint8_t **poutbuf,
00446 int *poutbuf_size)
00447 {
00448 FLACHeaderMarker *header = fpc->best_header;
00449 FLACHeaderMarker *child = header->best_child;
00450 if (!child) {
00451 *poutbuf_size = av_fifo_size(fpc->fifo_buf) - header->offset;
00452 } else {
00453 *poutbuf_size = child->offset - header->offset;
00454
00455
00456 check_header_mismatch(fpc, header, child, 0);
00457 }
00458
00459 fpc->avctx->sample_rate = header->fi.samplerate;
00460 fpc->avctx->channels = header->fi.channels;
00461 fpc->avctx->frame_size = header->fi.blocksize;
00462 *poutbuf = flac_fifo_read_wrap(fpc, header->offset, *poutbuf_size,
00463 &fpc->wrap_buf,
00464 &fpc->wrap_buf_allocated_size);
00465
00466 fpc->best_header_valid = 0;
00467
00468
00469 if (child)
00470 return child->offset - av_fifo_size(fpc->fifo_buf);
00471 return 0;
00472 }
00473
00474 static int flac_parse(AVCodecParserContext *s, AVCodecContext *avctx,
00475 const uint8_t **poutbuf, int *poutbuf_size,
00476 const uint8_t *buf, int buf_size)
00477 {
00478 FLACParseContext *fpc = s->priv_data;
00479 FLACHeaderMarker *curr;
00480 int nb_headers;
00481 const uint8_t *read_end = buf;
00482 const uint8_t *read_start = buf;
00483
00484 if (s->flags & PARSER_FLAG_COMPLETE_FRAMES) {
00485 FLACFrameInfo fi;
00486 if (frame_header_is_valid(avctx, buf, &fi))
00487 avctx->frame_size = fi.blocksize;
00488 *poutbuf = buf;
00489 *poutbuf_size = buf_size;
00490 return buf_size;
00491 }
00492
00493 fpc->avctx = avctx;
00494 if (fpc->best_header_valid)
00495 return get_best_header(fpc, poutbuf, poutbuf_size);
00496
00497
00498 if (fpc->best_header && fpc->best_header->best_child) {
00499 FLACHeaderMarker *temp;
00500 FLACHeaderMarker *best_child = fpc->best_header->best_child;
00501
00502
00503 for (curr = fpc->headers; curr != best_child; curr = temp) {
00504 if (curr != fpc->best_header) {
00505 av_log(avctx, AV_LOG_DEBUG,
00506 "dropping low score %i frame header from offset %i to %i\n",
00507 curr->max_score, curr->offset, curr->next->offset);
00508 }
00509 temp = curr->next;
00510 av_freep(&curr->link_penalty);
00511 av_free(curr);
00512 fpc->nb_headers_buffered--;
00513 }
00514
00515 av_fifo_drain(fpc->fifo_buf, best_child->offset);
00516
00517
00518 for (curr = best_child->next; curr; curr = curr->next)
00519 curr->offset -= best_child->offset;
00520
00521 fpc->nb_headers_buffered--;
00522 best_child->offset = 0;
00523 fpc->headers = best_child;
00524 if (fpc->nb_headers_buffered >= FLAC_MIN_HEADERS) {
00525 fpc->best_header = best_child;
00526 return get_best_header(fpc, poutbuf, poutbuf_size);
00527 }
00528 fpc->best_header = NULL;
00529 } else if (fpc->best_header) {
00530
00531 FLACHeaderMarker *temp;
00532
00533 for (curr = fpc->headers; curr != fpc->best_header; curr = temp) {
00534 temp = curr->next;
00535 av_freep(&curr->link_penalty);
00536 av_free(curr);
00537 }
00538 fpc->headers = fpc->best_header->next;
00539 av_freep(&fpc->best_header->link_penalty);
00540 av_freep(&fpc->best_header);
00541 }
00542
00543
00544 while ((buf && read_end < buf + buf_size &&
00545 fpc->nb_headers_buffered < FLAC_MIN_HEADERS)
00546 || (!buf && !fpc->end_padded)) {
00547 int start_offset;
00548
00549
00550 if (!buf) {
00551 fpc->end_padded = 1;
00552 buf_size = MAX_FRAME_HEADER_SIZE;
00553 read_end = read_start + MAX_FRAME_HEADER_SIZE;
00554 } else {
00555
00556
00557 int nb_desired = FLAC_MIN_HEADERS - fpc->nb_headers_buffered + 1;
00558 read_end = read_end + FFMIN(buf + buf_size - read_end,
00559 nb_desired * FLAC_AVG_FRAME_SIZE);
00560 }
00561
00562
00563 if (av_fifo_realloc2(fpc->fifo_buf,
00564 (read_end - read_start) + av_fifo_size(fpc->fifo_buf)) < 0) {
00565 av_log(avctx, AV_LOG_ERROR,
00566 "couldn't reallocate buffer of size %td\n",
00567 (read_end - read_start) + av_fifo_size(fpc->fifo_buf));
00568 goto handle_error;
00569 }
00570
00571 if (buf) {
00572 av_fifo_generic_write(fpc->fifo_buf, (void*) read_start,
00573 read_end - read_start, NULL);
00574 } else {
00575 int8_t pad[MAX_FRAME_HEADER_SIZE];
00576 memset(pad, 0, sizeof(pad));
00577 av_fifo_generic_write(fpc->fifo_buf, (void*) pad, sizeof(pad), NULL);
00578 }
00579
00580
00581 start_offset = av_fifo_size(fpc->fifo_buf) -
00582 ((read_end - read_start) + (MAX_FRAME_HEADER_SIZE - 1));
00583 start_offset = FFMAX(0, start_offset);
00584 nb_headers = find_new_headers(fpc, start_offset);
00585
00586 if (nb_headers < 0) {
00587 av_log(avctx, AV_LOG_ERROR,
00588 "find_new_headers couldn't allocate FLAC header\n");
00589 goto handle_error;
00590 }
00591
00592 fpc->nb_headers_buffered = nb_headers;
00593
00594 if (!fpc->end_padded && fpc->nb_headers_buffered < FLAC_MIN_HEADERS) {
00595 if (buf && read_end < buf + buf_size) {
00596 read_start = read_end;
00597 continue;
00598 } else {
00599 goto handle_error;
00600 }
00601 }
00602
00603
00604 if (fpc->end_padded || fpc->nb_headers_found)
00605 score_sequences(fpc);
00606
00607
00608 if (fpc->end_padded) {
00609
00610 fpc->fifo_buf->wptr -= MAX_FRAME_HEADER_SIZE;
00611 fpc->fifo_buf->wndx -= MAX_FRAME_HEADER_SIZE;
00612 if (fpc->fifo_buf->wptr < 0) {
00613 fpc->fifo_buf->wptr += fpc->fifo_buf->end -
00614 fpc->fifo_buf->buffer;
00615 }
00616 buf_size = 0;
00617 read_start = read_end = NULL;
00618 }
00619 }
00620
00621 curr = fpc->headers;
00622 for (curr = fpc->headers; curr; curr = curr->next)
00623 if (!fpc->best_header || curr->max_score > fpc->best_header->max_score)
00624 fpc->best_header = curr;
00625
00626 if (fpc->best_header) {
00627 fpc->best_header_valid = 1;
00628 if (fpc->best_header->offset > 0) {
00629
00630 av_log(avctx, AV_LOG_DEBUG, "Junk frame till offset %i\n",
00631 fpc->best_header->offset);
00632
00633
00634 avctx->frame_size = 0;
00635 *poutbuf_size = fpc->best_header->offset;
00636 *poutbuf = flac_fifo_read_wrap(fpc, 0, *poutbuf_size,
00637 &fpc->wrap_buf,
00638 &fpc->wrap_buf_allocated_size);
00639 return buf_size ? (read_end - buf) : (fpc->best_header->offset -
00640 av_fifo_size(fpc->fifo_buf));
00641 }
00642 if (!buf_size)
00643 return get_best_header(fpc, poutbuf, poutbuf_size);
00644 }
00645
00646 handle_error:
00647 *poutbuf = NULL;
00648 *poutbuf_size = 0;
00649 return read_end - buf;
00650 }
00651
00652 static int flac_parse_init(AVCodecParserContext *c)
00653 {
00654 FLACParseContext *fpc = c->priv_data;
00655
00656
00657 fpc->fifo_buf = av_fifo_alloc(FLAC_AVG_FRAME_SIZE * (FLAC_MIN_HEADERS + 3));
00658 return 0;
00659 }
00660
00661 static void flac_parse_close(AVCodecParserContext *c)
00662 {
00663 FLACParseContext *fpc = c->priv_data;
00664 FLACHeaderMarker *curr = fpc->headers, *temp;
00665
00666 while (curr) {
00667 temp = curr->next;
00668 av_freep(&curr->link_penalty);
00669 av_free(curr);
00670 curr = temp;
00671 }
00672 av_fifo_free(fpc->fifo_buf);
00673 av_free(fpc->wrap_buf);
00674 }
00675
00676 AVCodecParser ff_flac_parser = {
00677 .codec_ids = { CODEC_ID_FLAC },
00678 .priv_data_size = sizeof(FLACParseContext),
00679 .parser_init = flac_parse_init,
00680 .parser_parse = flac_parse,
00681 .parser_close = flac_parse_close,
00682 };