yuv2yuv4mpeg.c 9.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314
  1. #define _LARGEFILE_SOURCE
  2. #define _LARGEFILE64_SOURCE
  3. #define _FILE_OFFSET_BITS 64
  4. #include <stdio.h>
  5. #include <stdlib.h>
  6. #include <string.h>
  7. #include "../src/odintrin.h"
  8. /*Helper macro to validate fwrite/fread operations*/
  9. #define CHECK_IO(func,ptr,size,nmemb,stream) \
  10. if(func(ptr,size,nmemb,stream)<(size_t)nmemb){ \
  11. fprintf(stderr,#func"() error\n"); \
  12. return 1; \
  13. }
  14. /*This is a small utility used to convert many of the standard test sequences
  15. into a common format, the YUV4MPEG format used by mjpegtools.
  16. This is the format that the example encoder takes as input.
  17. The set of file name patterns/extentions it supports is intentionally very
  18. limited to keep the code simple.
  19. However, it is not too difficult to rename existing file names to fit these
  20. patterns.
  21. E.g., to add leading 0's to 1- and 2-digit frame numbers with /bin/sh,
  22. for i in tennis?.yuv ; do mv "$i" "tennis00${i##tennis}" ; done
  23. for i in tennis??.yuv ; do mv "$i" "tennis0${i##tennis}" ; done*/
  24. int main(int _argc,char *_argv[]){
  25. FILE *in_y;
  26. FILE *in_u;
  27. FILE *in_v;
  28. FILE *in_a;
  29. FILE *in_f;
  30. FILE *out_y4m;
  31. int y_w;
  32. int y_h;
  33. int c_w;
  34. int c_h;
  35. char ip;
  36. int fps_n;
  37. int fps_d;
  38. int par_n;
  39. int par_d;
  40. char *chroma;
  41. int have_chroma;
  42. int have_alpha;
  43. int frame_digits;
  44. int separate_planes;
  45. unsigned char *buf;
  46. char fname[8192];
  47. int frame_num;
  48. int argi;
  49. if(_argc<2){
  50. fprintf(stderr,
  51. "Usage: yuv2yuv4mpeg <sequence_qcif> [-p | -d<digits>] [<options>]\n"
  52. "Converts one or more raw data files in a sequence into a single\n"
  53. " YUV4MPEG file with appropriate headers to describe the video format.\n"
  54. "\n"
  55. "The type of input read is controlled by one or more of:\n"
  56. " -p Input is split by component.\n"
  57. " Opens up three files, <sequence>.y, <sequence>.u,\n"
  58. " and <sequence>.v containing raw, unpadded image\n"
  59. " data for each component, respectively.\n"
  60. " If only a Y' component is present, <sequence>.y is\n"
  61. " used.\n"
  62. " If an alpha component is present, <sequence>.a is\n"
  63. " used.\n"
  64. " Which components are present is determined from the\n"
  65. " -c flag described below.\n"
  66. " -d<digits> Input is split by frame.\n"
  67. " Opens up <sequence><ddd>.yuv for frame <ddd>\n"
  68. " containing raw, unpadded image data for all three\n"
  69. " components.\n"
  70. " <digits> specifies the number of decimal digits in\n"
  71. " the frame number <ddd>.\n"
  72. " If both of these options are be specified, the three files\n"
  73. " <sequence><ddd>.y, <sequence><ddd>.u, and <sequence><ddd>.v are\n"
  74. " opened for each frame.\n"
  75. " If neither of these options are specified, a single <sequence>.yuv\n"
  76. " file is opened, containing, the raw, unpadded image data for all\n"
  77. " components of all frames.\n"
  78. " This must be organized in a planar fashion, with each complete frame\n"
  79. " in one block, in the order Y, U (Cb), V (Cr), alpha.\n"
  80. " Which components are present is determined from the -c flag described\n"
  81. " below.\n"
  82. "\n"
  83. "The default input video format is 29.97 fps progressive QCIF.\n"
  84. "Options:\n"
  85. " -w<width>\n"
  86. " -h<height>\n"
  87. " -fn<frame rate numerator>\n"
  88. " -fd<frame rate denominator>\n"
  89. " -i<p|t|b> Progressive or Top-field first or Bottom-field first.\n"
  90. " -c<chroma> Chroma subsampling format. One of:\n"
  91. " 420jpeg\n"
  92. " 420mpeg2\n"
  93. " 420paldv\n"
  94. " 411\n"
  95. " 422\n"
  96. " 444\n"
  97. " 444alpha\n"
  98. " mono\n"
  99. " -an<pixel aspect numerator>\n"
  100. " -ad<pixel aspect denominator>\n"
  101. " Note: Most common frame sizes do not use square pixels:\n"
  102. " Name Width Height -an -ad\n"
  103. " 720 576 128 117\n"
  104. " CIF 352 288 128 117\n"
  105. " QCIF 176 144 128 117\n"
  106. " 720 480 4320 4739\n"
  107. " SIF 352 240 4320 4739\n"
  108. " The HD TV sizes (1920x1080, 1280x720) really do use square pixels.\n"
  109. " -o<offset> The first frame number to use in -d mode.\n"
  110. " If unspecified, 0 is used.\n");
  111. return -1;
  112. }
  113. frame_digits=frame_num=separate_planes=0;
  114. in_y=in_u=in_v=in_a=in_f=NULL;
  115. y_w=176;
  116. y_h=144;
  117. fps_n=30000;
  118. fps_d=1001;
  119. ip='p';
  120. par_n=128;
  121. par_d=117;
  122. chroma="420jpeg";
  123. for(argi=2;argi<_argc;argi++){
  124. if(_argv[argi][0]!='-'){
  125. fprintf(stderr,"Error parsing arguments: must start with '-'.\n");
  126. return -1;
  127. }
  128. switch(_argv[argi][1]){
  129. case 'p':separate_planes=1;break;
  130. case 'd':frame_digits=atoi(_argv[argi]+2);break;
  131. case 'w':y_w=atoi(_argv[argi]+2);break;
  132. case 'h':y_h=atoi(_argv[argi]+2);break;
  133. case 'i':ip=_argv[argi][2];break;
  134. case 'c':chroma=_argv[argi]+2;break;
  135. case 'f':{
  136. if(_argv[argi][2]=='n'){
  137. fps_n=atoi(_argv[argi]+3);
  138. break;
  139. }
  140. else if(_argv[argi][2]=='d'){
  141. fps_d=atoi(_argv[argi]+3);
  142. break;
  143. }
  144. }
  145. case 'a':{
  146. if(_argv[argi][2]=='n'){
  147. par_n=atoi(_argv[argi]+3);
  148. break;
  149. }
  150. else if(_argv[argi][2]=='d'){
  151. par_d=atoi(_argv[argi]+3);
  152. break;
  153. }
  154. }
  155. case 'o':frame_num=atoi(_argv[argi]+2);break;
  156. default:{
  157. fprintf(stderr,"Error parsing arguments: unknown switch '%c'.\n",
  158. _argv[argi][1]);
  159. return -1;
  160. }
  161. }
  162. }
  163. if(strncmp(chroma,"420",3)==0){
  164. c_w=y_w+1>>1;
  165. c_h=y_h+1>>1;
  166. have_chroma=1;
  167. }
  168. else if(strncmp(chroma,"411",3)==0){
  169. c_w=y_w+3>>2;
  170. c_h=y_h;
  171. have_chroma=1;
  172. }
  173. else if(strcmp(chroma,"422")==0){
  174. c_w=y_w+1>>1;
  175. c_h=y_h;
  176. have_chroma=1;
  177. }
  178. else if(strncmp(chroma,"444",3)==0){
  179. c_w=y_w;
  180. c_h=y_h;
  181. have_chroma=1;
  182. }
  183. else if(strncmp(chroma,"mono",4)==0){
  184. c_w=c_h=0;
  185. have_chroma=0;
  186. }
  187. else{
  188. fprintf(stderr,"Error parsing arguments: Unsupported chroma mode: %s.\n",
  189. chroma);
  190. return -1;
  191. }
  192. have_alpha=strstr(chroma,"alpha")!=NULL;
  193. frame_digits = OD_CLAMPI(0,frame_digits,8178);
  194. if(strlen(_argv[1])>(size_t)8178-frame_digits){
  195. fprintf(stderr,"File name too long.\n");
  196. return -1;
  197. }
  198. /*Open input and output files.*/
  199. if(separate_planes){
  200. if(frame_digits>0){
  201. sprintf(fname,"%s%0*d.y",_argv[1],frame_digits,frame_num);
  202. in_y=fopen(fname,"rb");
  203. if(have_chroma){
  204. sprintf(fname,"%s%0*d.u",_argv[1],frame_digits,frame_num);
  205. in_u=fopen(fname,"rb");
  206. sprintf(fname,"%s%0*d.v",_argv[1],frame_digits,frame_num);
  207. in_v=fopen(fname,"rb");
  208. }
  209. if(have_alpha){
  210. sprintf(fname,"%s%0*d.a",_argv[1],frame_digits,frame_num);
  211. in_a=fopen(fname,"rb");
  212. }
  213. }
  214. else{
  215. sprintf(fname,"%s.y",_argv[1]);
  216. in_y=fopen(fname,"rb");
  217. if(have_chroma){
  218. sprintf(fname,"%s.u",_argv[1]);
  219. in_u=fopen(fname,"rb");
  220. sprintf(fname,"%s.v",_argv[1]);
  221. in_v=fopen(fname,"rb");
  222. }
  223. if(have_alpha){
  224. sprintf(fname,"%s.a",_argv[1]);
  225. in_a=fopen(fname,"rb");
  226. }
  227. }
  228. }
  229. else{
  230. if(frame_digits>0){
  231. sprintf(fname,"%s%0*d.yuv",_argv[1],frame_digits,frame_num);
  232. in_f=fopen(fname,"rb");
  233. }
  234. else{
  235. sprintf(fname,"%s.yuv",_argv[1]);
  236. in_f=fopen(fname,"rb");
  237. }
  238. in_y=in_f;
  239. if(have_chroma)in_u=in_v=in_f;
  240. if(have_alpha)in_a=in_f;
  241. }
  242. if(in_y==NULL||have_chroma&&(in_u==NULL||in_v==NULL)||
  243. have_alpha&&in_a==NULL){
  244. fprintf(stderr,"Error opening input file(s).\n");
  245. return -1;
  246. }
  247. sprintf(fname,"%s.y4m",_argv[1]);
  248. out_y4m=fopen(fname,"wb");
  249. if(out_y4m==NULL){
  250. fprintf(stderr,"Error opening output file.\n");
  251. return -1;
  252. }
  253. /*Start output.*/
  254. fprintf(out_y4m,"YUV4MPEG2 W%i H%i F%i:%i I%c A%i:%i",
  255. y_w,y_h,fps_n,fps_d,ip,par_n,par_d);
  256. if(strcmp(chroma,"420jpeg")!=0)fprintf(out_y4m," C%s",chroma);
  257. fprintf(out_y4m,"\n");
  258. buf=(unsigned char *)malloc((size_t)(y_w*y_h));
  259. for(;;){
  260. if(fread(buf,y_w,y_h,in_y)<(size_t)y_h)break;
  261. fprintf(out_y4m,"FRAME\n");
  262. CHECK_IO(fwrite,buf,y_w,y_h,out_y4m);
  263. if(have_chroma){
  264. CHECK_IO(fread,buf,c_w,c_h,in_u);
  265. CHECK_IO(fwrite,buf,c_w,c_h,out_y4m);
  266. CHECK_IO(fread,buf,c_w,c_h,in_v);
  267. CHECK_IO(fwrite,buf,c_w,c_h,out_y4m);
  268. }
  269. if(have_alpha){
  270. CHECK_IO(fread,buf,y_w,y_h,in_a);
  271. CHECK_IO(fwrite,buf,y_w,y_h,out_y4m);
  272. }
  273. if(frame_digits>0){
  274. frame_num++;
  275. if(separate_planes){
  276. sprintf(fname,"%s%0*d.y",_argv[1],frame_digits,frame_num);
  277. fclose(in_y);
  278. in_y=fopen(fname,"rb");
  279. if(have_chroma){
  280. sprintf(fname,"%s%0*d.u",_argv[1],frame_digits,frame_num);
  281. fclose(in_u);
  282. in_u=fopen(fname,"rb");
  283. sprintf(fname,"%s%0*d.v",_argv[1],frame_digits,frame_num);
  284. fclose(in_v);
  285. in_v=fopen(fname,"rb");
  286. }
  287. if(have_alpha){
  288. sprintf(fname,"%s%0*d.a",_argv[1],frame_digits,frame_num);
  289. fclose(in_a);
  290. in_a=fopen(fname,"rb");
  291. }
  292. }
  293. else{
  294. sprintf(fname,"%s%0*d.yuv",_argv[1],frame_digits,frame_num);
  295. fclose(in_f);
  296. in_f=fopen(fname,"rb");
  297. in_y=in_f;
  298. if(have_chroma)in_u=in_v=in_f;
  299. if(have_alpha)in_a=in_f;
  300. }
  301. if(in_y==NULL||have_chroma&&(in_u==NULL||in_v==NULL)||
  302. have_alpha&&in_a==NULL){
  303. break;
  304. }
  305. }
  306. }
  307. return 0;
  308. }