Advertisement
Guest User

Unrotate MP4 from some smartphone

a guest
Sep 28th, 2012
70
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C 3.48 KB | None | 0 0
  1. /*
  2.  * $ gcc -Wall -O3 -o unrotate unrotate.c
  3.  * $ ./unrotate input.mp4 output.mp4
  4.  */
  5.  
  6. #include <stdio.h>
  7. #include <inttypes.h>
  8.  
  9. #include <sys/mman.h>
  10. #include <sys/stat.h>
  11. #include <fcntl.h>
  12. #include <unistd.h>
  13.  
  14. #include <string.h>
  15.  
  16. static int fd_in  = -1;
  17. static int fd_out = -1;
  18. static struct stat st;
  19. static const uint8_t *buf_in  = NULL;
  20. static uint8_t *buf_out = NULL;
  21.  
  22. static void mmap_close(void)
  23. {
  24.     if (buf_out     ) munmap(buf_out, st.st_size);
  25.     if (buf_in      ) munmap((void*)buf_in, st.st_size);
  26.     if (fd_out != -1) close(fd_out);
  27.     if (fd_in  != -1) close(fd_in);
  28. }
  29.  
  30. static int mmap_open(char *fname_in, char *fname_out)
  31. {
  32.     int offset;
  33.  
  34.     /* Open and mmap input file */
  35.     fd_in = open(fname_in, O_RDONLY);
  36.     if (fd_in == -1) {
  37.         fprintf(stderr, "could not open input file '%s'\n", fname_in);
  38.         goto end;
  39.     }
  40.     if (fstat(fd_in, &st) == -1) {
  41.         fprintf(stderr, "could not stat input file '%s'\n", fname_in);
  42.         goto end;
  43.     }
  44.     buf_in = mmap(NULL, st.st_size, PROT_READ, MAP_PRIVATE, fd_in, 0);
  45.     if (buf_in == MAP_FAILED) {
  46.         fprintf(stderr, "could not map input file '%s'\n", fname_in);
  47.         goto end;
  48.     }
  49.     /* Open and mmap output file, with same size as input file */
  50.     fd_out = open(fname_out, O_RDWR | O_CREAT | O_TRUNC, 0666);
  51.     if (fd_out == -1) {
  52.         fprintf(stderr, "could not open output file '%s'\n", fname_out);
  53.         goto end;
  54.     }
  55.     lseek(fd_out, st.st_size-1, SEEK_SET);
  56.     offset = write(fd_out, "", 1);
  57.     lseek(fd_out, 0, SEEK_SET);
  58.     buf_out = mmap(NULL, st.st_size, PROT_READ | PROT_WRITE, MAP_SHARED, fd_out, 0);
  59.     if (buf_out == MAP_FAILED) {
  60.         fprintf(stderr, "could not map output file '%s'\n", fname_out);
  61.         goto end;
  62.     }
  63.  
  64.     return st.st_size;
  65.  
  66. end:
  67.     mmap_close();
  68.     return 0;
  69. }
  70.  
  71. static uint32_t read_be32(const uint8_t *p)
  72. {
  73.     return (p[0] << 24) | (p[1] << 16) | (p[2] << 8) | (p[3]);
  74. }
  75.  
  76. static void write_be16(uint8_t *p, uint32_t val)
  77. {
  78.     p[0] = (val >> 8) & 0xff;
  79.     p[1] = (val >> 0) & 0xff;
  80. }
  81.  
  82. int main(int argc, char *argv[])
  83. {
  84.     unsigned int file_size;
  85.     unsigned int i;
  86.     int ok = 0;
  87.  
  88.     if (argc < 3) {
  89.         fprintf(stderr, "usage: %s <input> <output>\n", argv[0]);
  90.         return -1;
  91.     }
  92.  
  93.     file_size = mmap_open(argv[1], argv[2]);
  94.     if (!file_size)
  95.         return -1;
  96.  
  97.     for (i = 0; i < 4; i++)
  98.         buf_out[i] = buf_in[i];
  99.     for (     ; !ok && i < file_size-(4+104); i++) {
  100.         if ((*(uint32_t *)&buf_in[i]) == 0x64686b74) {
  101.             uint32_t tkhd_size = read_be32(&buf_in[i-4]);
  102.             uint8_t version = buf_in[i+4];
  103.             uint8_t offset = (version ? 14 : 11) << 2;
  104.  
  105.             memcpy(&buf_out[i], &buf_in[i], tkhd_size);
  106.  
  107.             if (read_be32(&buf_in[i+offset+36]) && read_be32(&buf_in[i+offset+40])) {
  108.                 write_be16(&buf_out[i+offset   ], 1);
  109.                 write_be16(&buf_out[i+offset+ 4], 0);
  110.                 write_be16(&buf_out[i+offset+ 8], 0);
  111.                 write_be16(&buf_out[i+offset+12], 0);
  112.                 write_be16(&buf_out[i+offset+16], 1);
  113.                 write_be16(&buf_out[i+offset+20], 0);
  114.                 fprintf(stderr, "video tkhd found and matrix changed\n");
  115.                 ok = 1;
  116.             }
  117.  
  118.             i += tkhd_size-1;
  119.         } else {
  120.             buf_out[i] = buf_in[i];
  121.         }
  122.     }
  123.     memcpy(&buf_out[i], &buf_in[i], file_size - i);
  124.  
  125.     mmap_close();
  126.  
  127.     return 0;
  128. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement