Mercurial > libavformat.hg
comparison nut.c @ 418:41da3366d341 libavformat
checksuming for nut & nice checksum API for libavformat
author | michael |
---|---|
date | Mon, 05 Apr 2004 12:02:10 +0000 |
parents | e26aacf263be |
children | 51c25922a543 |
comparison
equal
deleted
inserted
replaced
417:5a89e49ff688 | 418:41da3366d341 |
---|---|
23 * | 23 * |
24 */ | 24 */ |
25 | 25 |
26 /* | 26 /* |
27 * TODO: | 27 * TODO: |
28 * - checksumming | |
29 * - seeking | 28 * - seeking |
30 * - index writing | 29 * - index writing |
31 * - index packet reading support | 30 * - index packet reading support |
32 * - startcode searching for broken streams | 31 * - startcode searching for broken streams |
33 */ | 32 */ |
282 return -1; | 281 return -1; |
283 else | 282 else |
284 return 0; | 283 return 0; |
285 } | 284 } |
286 | 285 |
287 static int get_packetheader(NUTContext *nut, ByteIOContext *bc, int prefix_length) | 286 static int get_packetheader(NUTContext *nut, ByteIOContext *bc, int prefix_length, int calculate_checksum) |
288 { | 287 { |
289 int64_t start, size, last_size; | 288 int64_t start, size, last_size; |
290 start= url_ftell(bc) - prefix_length; | 289 start= url_ftell(bc) - prefix_length; |
291 | 290 |
292 if(start != nut->packet_start + nut->written_packet_size){ | 291 if(start != nut->packet_start + nut->written_packet_size){ |
293 av_log(nut->avf, AV_LOG_ERROR, "get_packetheader called at weird position\n"); | 292 av_log(nut->avf, AV_LOG_ERROR, "get_packetheader called at weird position\n"); |
294 return -1; | 293 return -1; |
295 } | 294 } |
295 | |
296 if(calculate_checksum) | |
297 init_checksum(bc, update_adler32, 0); | |
296 | 298 |
297 size= get_v(bc); | 299 size= get_v(bc); |
298 last_size= get_v(bc); | 300 last_size= get_v(bc); |
299 if(nut->written_packet_size != last_size){ | 301 if(nut->written_packet_size != last_size){ |
300 av_log(nut->avf, AV_LOG_ERROR, "packet size missmatch %d != %lld at %lld\n", nut->written_packet_size, last_size, start); | 302 av_log(nut->avf, AV_LOG_ERROR, "packet size missmatch %d != %lld at %lld\n", nut->written_packet_size, last_size, start); |
306 nut->written_packet_size= size; | 308 nut->written_packet_size= size; |
307 | 309 |
308 return size; | 310 return size; |
309 } | 311 } |
310 | 312 |
313 static int check_checksum(ByteIOContext *bc){ | |
314 unsigned long checksum= get_checksum(bc); | |
315 return checksum != get_be32(bc); | |
316 } | |
317 | |
311 /** | 318 /** |
312 * | 319 * |
313 */ | 320 */ |
314 static int get_length(uint64_t val){ | 321 static int get_length(uint64_t val){ |
315 int i; | 322 int i; |
350 put_buffer(bc, string, len); | 357 put_buffer(bc, string, len); |
351 | 358 |
352 return 0; | 359 return 0; |
353 } | 360 } |
354 | 361 |
355 static int put_packetheader(NUTContext *nut, ByteIOContext *bc, int max_size) | 362 static int put_packetheader(NUTContext *nut, ByteIOContext *bc, int max_size, int calculate_checksum) |
356 { | 363 { |
357 put_flush_packet(bc); | 364 put_flush_packet(bc); |
358 nut->last_packet_start= nut->packet_start; | 365 nut->last_packet_start= nut->packet_start; |
359 nut->packet_start+= nut->written_packet_size; | 366 nut->packet_start+= nut->written_packet_size; |
360 nut->packet_size_pos = url_ftell(bc); | 367 nut->packet_size_pos = url_ftell(bc); |
361 nut->written_packet_size = max_size; | 368 nut->written_packet_size = max_size; |
369 | |
370 if(calculate_checksum) | |
371 init_checksum(bc, update_adler32, 0); | |
362 | 372 |
363 /* packet header */ | 373 /* packet header */ |
364 put_v(bc, nut->written_packet_size); /* forward ptr */ | 374 put_v(bc, nut->written_packet_size); /* forward ptr */ |
365 put_v(bc, nut->packet_start - nut->last_packet_start); /* backward ptr */ | 375 put_v(bc, nut->packet_start - nut->last_packet_start); /* backward ptr */ |
366 | 376 |
367 return 0; | 377 return 0; |
368 } | 378 } |
369 | 379 |
370 static int update_packetheader(NUTContext *nut, ByteIOContext *bc, int additional_size){ | 380 static int update_packetheader(NUTContext *nut, ByteIOContext *bc, int additional_size, int calculate_checksum){ |
371 int64_t start= nut->packet_start; | 381 int64_t start= nut->packet_start; |
372 int64_t cur= url_ftell(bc); | 382 int64_t cur= url_ftell(bc); |
373 int size= cur - start + additional_size; | 383 int size= cur - start + additional_size; |
384 | |
385 if(calculate_checksum) | |
386 size += 4; | |
374 | 387 |
375 if(size != nut->written_packet_size){ | 388 if(size != nut->written_packet_size){ |
376 int i; | 389 int i; |
377 | 390 |
378 assert( size <= nut->written_packet_size ); | 391 assert( size <= nut->written_packet_size ); |
382 put_byte(bc, 0x80); | 395 put_byte(bc, 0x80); |
383 put_v(bc, size); | 396 put_v(bc, size); |
384 | 397 |
385 url_fseek(bc, cur, SEEK_SET); | 398 url_fseek(bc, cur, SEEK_SET); |
386 nut->written_packet_size= size; //FIXME may fail if multiple updates with differing sizes, as get_length may differ | 399 nut->written_packet_size= size; //FIXME may fail if multiple updates with differing sizes, as get_length may differ |
400 | |
401 if(calculate_checksum) | |
402 put_be32(bc, get_checksum(bc)); | |
387 } | 403 } |
388 | 404 |
389 return 0; | 405 return 0; |
390 } | 406 } |
391 | 407 |
403 | 419 |
404 av_set_pts_info(s, 60, 1, AV_TIME_BASE); | 420 av_set_pts_info(s, 60, 1, AV_TIME_BASE); |
405 | 421 |
406 /* main header */ | 422 /* main header */ |
407 put_be64(bc, MAIN_STARTCODE); | 423 put_be64(bc, MAIN_STARTCODE); |
408 put_packetheader(nut, bc, 120+5*256); | 424 put_packetheader(nut, bc, 120+5*256, 1); |
409 put_v(bc, 1); /* version */ | 425 put_v(bc, 1); /* version */ |
410 put_v(bc, s->nb_streams); | 426 put_v(bc, s->nb_streams); |
411 put_v(bc, 3); /* checksum threshold */ | 427 put_v(bc, 3); |
412 | 428 |
413 build_frame_code(s); | 429 build_frame_code(s); |
414 assert(nut->frame_code['N'].flags == 1); | 430 assert(nut->frame_code['N'].flags == 1); |
415 for(i=0; i<256;){ | 431 for(i=0; i<256;){ |
416 int tmp_flags = nut->frame_code[i].flags; | 432 int tmp_flags = nut->frame_code[i].flags; |
433 } | 449 } |
434 } | 450 } |
435 put_v(bc, j); | 451 put_v(bc, j); |
436 } | 452 } |
437 | 453 |
438 put_be32(bc, 0); /* FIXME: checksum */ | 454 update_packetheader(nut, bc, 0, 1); |
439 | |
440 update_packetheader(nut, bc, 0); | |
441 | 455 |
442 /* stream headers */ | 456 /* stream headers */ |
443 for (i = 0; i < s->nb_streams; i++) | 457 for (i = 0; i < s->nb_streams; i++) |
444 { | 458 { |
445 int nom, denom, gcd; | 459 int nom, denom, gcd; |
446 | 460 |
447 codec = &s->streams[i]->codec; | 461 codec = &s->streams[i]->codec; |
448 | 462 |
449 put_be64(bc, STREAM_STARTCODE); | 463 put_be64(bc, STREAM_STARTCODE); |
450 put_packetheader(nut, bc, 120 + codec->extradata_size); | 464 put_packetheader(nut, bc, 120 + codec->extradata_size, 1); |
451 put_v(bc, i /*s->streams[i]->index*/); | 465 put_v(bc, i /*s->streams[i]->index*/); |
452 put_v(bc, (codec->codec_type == CODEC_TYPE_AUDIO) ? 32 : 0); | 466 put_v(bc, (codec->codec_type == CODEC_TYPE_AUDIO) ? 32 : 0); |
453 if (codec->codec_tag) | 467 if (codec->codec_tag) |
454 put_v(bc, codec->codec_tag); | 468 put_v(bc, codec->codec_tag); |
455 else if (codec->codec_type == CODEC_TYPE_VIDEO) | 469 else if (codec->codec_type == CODEC_TYPE_VIDEO) |
518 put_v(bc, 0); /* csp type -- unknown */ | 532 put_v(bc, 0); /* csp type -- unknown */ |
519 break; | 533 break; |
520 default: | 534 default: |
521 break; | 535 break; |
522 } | 536 } |
523 put_be32(bc, 0); /* FIXME: checksum */ | 537 update_packetheader(nut, bc, 0, 1); |
524 update_packetheader(nut, bc, 0); | |
525 } | 538 } |
526 | 539 |
527 /* info header */ | 540 /* info header */ |
528 put_be64(bc, INFO_STARTCODE); | 541 put_be64(bc, INFO_STARTCODE); |
529 put_packetheader(nut, bc, 30+strlen(s->author)+strlen(s->title)+ | 542 put_packetheader(nut, bc, 30+strlen(s->author)+strlen(s->title)+ |
530 strlen(s->comment)+strlen(s->copyright)+strlen(LIBAVFORMAT_IDENT)); | 543 strlen(s->comment)+strlen(s->copyright)+strlen(LIBAVFORMAT_IDENT), 1); |
531 if (s->author[0]) | 544 if (s->author[0]) |
532 { | 545 { |
533 put_v(bc, 9); /* type */ | 546 put_v(bc, 9); /* type */ |
534 put_str(bc, s->author); | 547 put_str(bc, s->author); |
535 } | 548 } |
551 /* encoder */ | 564 /* encoder */ |
552 put_v(bc, 13); /* type */ | 565 put_v(bc, 13); /* type */ |
553 put_str(bc, LIBAVFORMAT_IDENT); | 566 put_str(bc, LIBAVFORMAT_IDENT); |
554 | 567 |
555 put_v(bc, 0); /* eof info */ | 568 put_v(bc, 0); /* eof info */ |
556 | 569 update_packetheader(nut, bc, 0, 1); |
557 put_be32(bc, 0); /* FIXME: checksum */ | |
558 update_packetheader(nut, bc, 0); | |
559 | 570 |
560 put_flush_packet(bc); | 571 put_flush_packet(bc); |
561 | 572 |
562 return 0; | 573 return 0; |
563 } | 574 } |
592 if(!stream->last_key_frame) | 603 if(!stream->last_key_frame) |
593 frame_type=2; | 604 frame_type=2; |
594 } | 605 } |
595 | 606 |
596 if(frame_type>0){ | 607 if(frame_type>0){ |
597 update_packetheader(nut, bc, 0); | 608 update_packetheader(nut, bc, 0, 0); |
598 reset(s); | 609 reset(s); |
599 full_pts=1; | 610 full_pts=1; |
600 } | 611 } |
601 //FIXME ensure that the timestamp can be represented by either delta or lsb or full_pts=1 | 612 //FIXME ensure that the timestamp can be represented by either delta or lsb or full_pts=1 |
602 | 613 |
682 if (frame_type==2) | 693 if (frame_type==2) |
683 put_be64(bc, KEYFRAME_STARTCODE); | 694 put_be64(bc, KEYFRAME_STARTCODE); |
684 put_byte(bc, frame_code); | 695 put_byte(bc, frame_code); |
685 | 696 |
686 if(frame_type>0) | 697 if(frame_type>0) |
687 put_packetheader(nut, bc, FFMAX(size+20, MAX_TYPE1_DISTANCE)); | 698 put_packetheader(nut, bc, FFMAX(size+20, MAX_TYPE1_DISTANCE), 0); |
688 if(nut->frame_code[frame_code].stream_id_plus1 == 0) | 699 if(nut->frame_code[frame_code].stream_id_plus1 == 0) |
689 put_v(bc, stream_index); | 700 put_v(bc, stream_index); |
690 if (flags & FLAG_PTS){ | 701 if (flags & FLAG_PTS){ |
691 if (flags & FLAG_FULL_PTS) | 702 if (flags & FLAG_FULL_PTS) |
692 put_v(bc, pts); | 703 put_v(bc, pts); |
695 } | 706 } |
696 if(flags & FLAG_DATA_SIZE) | 707 if(flags & FLAG_DATA_SIZE) |
697 put_v(bc, size / size_mul); | 708 put_v(bc, size / size_mul); |
698 if(size > MAX_TYPE1_DISTANCE){ | 709 if(size > MAX_TYPE1_DISTANCE){ |
699 assert(frame_type > 0); | 710 assert(frame_type > 0); |
700 update_packetheader(nut, bc, size); | 711 update_packetheader(nut, bc, size, 0); |
701 } | 712 } |
702 | 713 |
703 put_buffer(bc, buf, size); | 714 put_buffer(bc, buf, size); |
704 | 715 |
705 update(nut, stream_index, frame_start, frame_type, frame_code, key_frame, size, pts); | 716 update(nut, stream_index, frame_start, frame_type, frame_code, key_frame, size, pts); |
710 static int nut_write_trailer(AVFormatContext *s) | 721 static int nut_write_trailer(AVFormatContext *s) |
711 { | 722 { |
712 NUTContext *nut = s->priv_data; | 723 NUTContext *nut = s->priv_data; |
713 ByteIOContext *bc = &s->pb; | 724 ByteIOContext *bc = &s->pb; |
714 | 725 |
715 update_packetheader(nut, bc, 0); | 726 update_packetheader(nut, bc, 0, 0); |
716 | 727 |
717 #if 0 | 728 #if 0 |
718 int i; | 729 int i; |
719 | 730 |
720 /* WRITE INDEX */ | 731 /* WRITE INDEX */ |
721 | 732 |
722 for (i = 0; s->nb_streams; i++) | 733 for (i = 0; s->nb_streams; i++) |
723 { | 734 { |
724 put_be64(bc, INDEX_STARTCODE); | 735 put_be64(bc, INDEX_STARTCODE); |
725 put_packetheader(nut, bc, 64); | 736 put_packetheader(nut, bc, 64, 1); |
726 put_v(bc, s->streams[i]->id); | 737 put_v(bc, s->streams[i]->id); |
727 put_v(bc, ...); | 738 put_v(bc, ...); |
728 put_be32(bc, 0); /* FIXME: checksum */ | 739 update_packetheader(nut, bc, 0, 1); |
729 update_packetheader(nut, bc, 0); | |
730 } | 740 } |
731 #endif | 741 #endif |
732 | 742 |
733 put_flush_packet(bc); | 743 put_flush_packet(bc); |
734 | 744 |
766 | 776 |
767 /* main header */ | 777 /* main header */ |
768 tmp = get_be64(bc); | 778 tmp = get_be64(bc); |
769 if (tmp != MAIN_STARTCODE) | 779 if (tmp != MAIN_STARTCODE) |
770 av_log(s, AV_LOG_ERROR, "damaged? startcode!=1 (%Ld)\n", tmp); | 780 av_log(s, AV_LOG_ERROR, "damaged? startcode!=1 (%Ld)\n", tmp); |
771 get_packetheader(nut, bc, 8); | 781 get_packetheader(nut, bc, 8, 1); |
772 | 782 |
773 tmp = get_v(bc); | 783 tmp = get_v(bc); |
774 if (tmp != 1) | 784 if (tmp != 1) |
775 av_log(s, AV_LOG_ERROR, "bad version (%Ld)\n", tmp); | 785 av_log(s, AV_LOG_ERROR, "bad version (%Ld)\n", tmp); |
776 | 786 |
819 if(nut->frame_code['N'].flags != 1){ | 829 if(nut->frame_code['N'].flags != 1){ |
820 av_log(s, AV_LOG_ERROR, "illegal frame_code table\n"); | 830 av_log(s, AV_LOG_ERROR, "illegal frame_code table\n"); |
821 return -1; | 831 return -1; |
822 } | 832 } |
823 | 833 |
824 get_be32(bc); /* checkusm */ | 834 if(check_checksum(bc)){ |
835 av_log(s, AV_LOG_ERROR, "Main header checksum missmatch\n"); | |
836 return -1; | |
837 } | |
825 | 838 |
826 s->bit_rate = 0; | 839 s->bit_rate = 0; |
827 | 840 |
828 nut->stream = av_malloc(sizeof(StreamContext)*nb_streams); | 841 nut->stream = av_malloc(sizeof(StreamContext)*nb_streams); |
829 | 842 |
834 AVStream *st; | 847 AVStream *st; |
835 | 848 |
836 tmp = get_be64(bc); | 849 tmp = get_be64(bc); |
837 if (tmp != STREAM_STARTCODE) | 850 if (tmp != STREAM_STARTCODE) |
838 av_log(s, AV_LOG_ERROR, "damaged? startcode!=1 (%Ld)\n", tmp); | 851 av_log(s, AV_LOG_ERROR, "damaged? startcode!=1 (%Ld)\n", tmp); |
839 get_packetheader(nut, bc, 8); | 852 get_packetheader(nut, bc, 8, 1); |
840 st = av_new_stream(s, get_v(bc)); | 853 st = av_new_stream(s, get_v(bc)); |
841 if (!st) | 854 if (!st) |
842 return AVERROR_NOMEM; | 855 return AVERROR_NOMEM; |
843 class = get_v(bc); | 856 class = get_v(bc); |
844 tmp = get_v(bc); | 857 tmp = get_v(bc); |
893 if (class == 32) /* AUDIO */ | 906 if (class == 32) /* AUDIO */ |
894 { | 907 { |
895 st->codec.sample_rate = (get_v(bc) * nom) / denom; | 908 st->codec.sample_rate = (get_v(bc) * nom) / denom; |
896 st->codec.channels = get_v(bc); | 909 st->codec.channels = get_v(bc); |
897 } | 910 } |
898 get_be32(bc); /* checksum */ | 911 if(check_checksum(bc)){ |
912 av_log(s, AV_LOG_ERROR, "Stream header %d checksum missmatch\n", cur_stream); | |
913 return -1; | |
914 } | |
899 nut->stream[cur_stream].rate_num= nom; | 915 nut->stream[cur_stream].rate_num= nom; |
900 nut->stream[cur_stream].rate_den= denom; | 916 nut->stream[cur_stream].rate_den= denom; |
901 } | 917 } |
902 | 918 |
903 tmp = get_be64(bc); | 919 tmp = get_be64(bc); |
904 if (tmp == INFO_STARTCODE){ | 920 if (tmp == INFO_STARTCODE){ |
905 get_packetheader(nut, bc, 8); | 921 get_packetheader(nut, bc, 8, 1); |
906 | 922 |
907 for(;;){ | 923 for(;;){ |
908 int id= get_v(bc); | 924 int id= get_v(bc); |
909 char *name, *type, custom_name[256], custom_type[256]; | 925 char *name, *type, custom_name[256], custom_type[256]; |
910 | 926 |
941 get_str(bc, s->comment, sizeof(s->comment)); | 957 get_str(bc, s->comment, sizeof(s->comment)); |
942 else | 958 else |
943 get_str(bc, NULL, 0); | 959 get_str(bc, NULL, 0); |
944 } | 960 } |
945 } | 961 } |
946 get_be32(bc); /* checksum */ | 962 if(check_checksum(bc)){ |
963 av_log(s, AV_LOG_ERROR, "Info header checksum missmatch\n"); | |
964 } | |
947 }else | 965 }else |
948 url_fseek(bc, -8, SEEK_CUR); | 966 url_fseek(bc, -8, SEEK_CUR); |
949 | 967 |
950 return 0; | 968 return 0; |
951 } | 969 } |
984 stream_id= nut->frame_code[frame_code].stream_id_plus1 - 1; | 1002 stream_id= nut->frame_code[frame_code].stream_id_plus1 - 1; |
985 | 1003 |
986 if(flags & FLAG_FRAME_TYPE){ | 1004 if(flags & FLAG_FRAME_TYPE){ |
987 reset(s); | 1005 reset(s); |
988 if(frame_type==2){ | 1006 if(frame_type==2){ |
989 get_packetheader(nut, bc, 8+1); | 1007 get_packetheader(nut, bc, 8+1, 0); |
990 }else{ | 1008 }else{ |
991 get_packetheader(nut, bc, 1); | 1009 get_packetheader(nut, bc, 1, 0); |
992 frame_type= 1; | 1010 frame_type= 1; |
993 } | 1011 } |
994 } | 1012 } |
995 | 1013 |
996 if(stream_id==-1) | 1014 if(stream_id==-1) |