搜索 社区服务 统计排行 帮助
  • 2949阅读
  • 16回复

[原创][最后更新: 2008-01-02]Timecode format v2文件分析,C语言代码

楼层直达
级别: 工作组
注册时间:
2005-05-03
在线时间:
0小时
发帖:
2914
编写各种和timecode v2有关又需要分析timecode v2的时候可以用
比如v2转v1或者什么什么的,用起来还不错
当成lib用好了……VC++6和mingw32都测试通过
提供一个函数:
struct resdata * tc2analysis(char * filename)
给出要分析的timecode的文件名,返回一个结构体链表
结构体具体可以参照代码

本代码可能还存在许许多多的问题,仅供爱好者测试之用
遵循LGPL协议,可以自己编译成lib文件丢进自己程序用(由于目前稳定性和准确性以及其他各种各样错误可能存在,不推荐拿来用)



  1. /*
  2. This code is also contributed by the following ones:
  3. adamhj
  4. last change: 2008-01-02
  5. */
  6. #include
  7. #include
  8. #include
  9. #include
  10. struct resdata {
  11. long startframe;
  12. long endframe;
  13. double starttime;
  14. double endtime;
  15. double framerate;
  16. struct resdata * next;
  17. };
  18. typedef struct resdata node;
  19. extern struct resdata * tc2analysis(char* fn){
  20. /*
  21. declare variables
  22. lxxxxxx: previous one, like that ltime means the previous time
  23. sfn: source file name
  24. sfp: pointer of the file
  25. cframe: current frame in progress
  26. */
  27. char *line = (char*) malloc(1024);
  28. long cframe = -1;
  29. double delta=0, ldelta=0, ctime=0, ltime=0;
  30. char *sfn = (char*) malloc(1024);
  31. FILE *sfp;
  32. int OK = 0, first = 1;
  33. node *head, *p;
  34. /*
  35. get filenames from parameters
  36. */
  37. strcpy(sfn, fn);
  38. sfp = fopen(sfn, "r");
  39. head = (node*) malloc(sizeof(node));
  40. p = head;
  41. /* read data from file */
  42. while(!feof(sfp)){
  43. fgets(line, 1000, sfp);
  44. if(line[0] != '#' && strlen(line) != 0){
  45. cframe++;
  46. ltime = ctime;
  47. ldelta = delta;
  48. ctime = atof(line);
  49. delta = ctime - ltime;
  50. if (fabs(delta - ldelta) > 2){
  51. /* if framerate changes */
  52. if (first == 1){
  53. /* if it's the first line to output*/
  54. p->startframe = cframe - 1;
  55. p->starttime = ltime;
  56. first = 0;
  57. }else{
  58. /* normal situation */
  59. p->endframe = cframe - 2;
  60. p->endtime = ltime;
  61. p->framerate = (p->endframe - p->startframe + 1) * 1000 / (p->endtime - p->starttime);
  62. p->next = (node*) malloc(sizeof(node));
  63. p = p->next;
  64. p->startframe = cframe - 1;
  65. p->starttime = ltime;
  66. }
  67. }
  68. }
  69. }
  70. /* deal with the last output line */
  71. p->endframe = cframe;
  72. p->endtime = ctime + delta;
  73. p->framerate = (p->endframe - p->startframe + 1) * 1000 / (p->endtime - p->starttime);
  74. p->next = NULL;
  75. fclose(sfp);
  76. /* output result */
  77. return (head);
  78. }
级别: 工作组
注册时间:
2003-08-26
在线时间:
13小时
发帖:
6600
只看该作者 1楼 发表于: 2007-12-25
你看,你要把「LGPL」的版权信息嵌入到源代码里才算应用了协议哟

催片请点此处: http://bbs.popgo.org/bbs/read.php?tid=502402&displayMode=1#19103164
级别: 侠客
注册时间:
2006-10-07
在线时间:
0小时
发帖:
587
只看该作者 2楼 发表于: 2007-12-26
嗯?雷在C有突破了咯?

弱弱问下LGPL是啥...
级别: 工作组
注册时间:
2007-08-23
在线时间:
0小时
发帖:
683
只看该作者 3楼 发表于: 2007-12-26
LGPL就是Lesser GPL,与GPL最大的不同就是LGPL允许源码私有。
级别: 侠客
注册时间:
2006-10-07
在线时间:
0小时
发帖:
587
只看该作者 4楼 发表于: 2007-12-26
嗯.原来如此..程序语言小白我飘过..
级别: 精灵王
注册时间:
2005-12-24
在线时间:
45小时
发帖:
2298
只看该作者 5楼 发表于: 2007-12-27
看不懂的白白飘过

在长长地换硬件的道路上,纠结前进中
级别: 工作组
注册时间:
2003-08-26
在线时间:
13小时
发帖:
6600
只看该作者 6楼 发表于: 2007-12-27
引用
最初由 alphaa 发布
LGPL就是Lesser GPL,与GPL最大的不同就是LGPL允许源码私有。
LGPL只允许可以被二进制链接到非LGPL/GPL的程序里。GPL严禁二进制链接。

催片请点此处: http://bbs.popgo.org/bbs/read.php?tid=502402&displayMode=1#19103164
级别: 工作组
注册时间:
2005-05-03
在线时间:
0小时
发帖:
2914
只看该作者 7楼 发表于: 2007-12-27
引用
最初由 MeteorRain 发布
你看,你要把「LGPL」的版权信息嵌入到源代码里才算应用了协议哟


呜哇,找不到资料,不知写什么好……好像有的文档说按照gpl的那样写?
级别: 工作组
注册时间:
2005-10-19
在线时间:
31小时
发帖:
3613
只看该作者 8楼 发表于: 2007-12-29
我喷……你还真的放出来了

凡是未完全安装Office字体的,以下英语短语请无视~~

Knowledge is infinite.


级别: 风云使者
注册时间:
2002-09-11
在线时间:
0小时
发帖:
4791
只看该作者 9楼 发表于: 2007-12-30
=.=重点是 楼上的你喷什么出来=,=

人間五十年 下天のうちをくらぶれば 夢幻の如くなり 一度生を得て 滅せぬ者のあるべきか
服务器 ftp://txxz.share.comic.cn 用户名:txxz 密码:share 1线50K可LIST以上服务器提供TX作品下载 有需要而上面没的请PM我 感谢漫网提供服务器
本社聊天催片OX群:10042749 欢迎插入 重口味满载!
级别: 新手上路
注册时间:
2003-06-23
在线时间:
1小时
发帖:
2882
只看该作者 10楼 发表于: 2007-12-30
没考虑timecode v2文件里有空白行的情况

另外,别告诉我cframe初始值取-2是试出来的...老实说我囧了...

你取cframe=-1的时候对应的ctime是第0帧的,后面也是如此,cframe=n的时候的ctime是第n+1帧的,结果在算第一个node和最后一个node的framerate的时候却又按照ctime是第n帧的时间算的,所以第一个node和最后一个node算出来的帧率是错的

例如下面这个timcode
  1. # timecode v2
  2. 0
  3. 10
  4. 20
  5. 30
  6. 40
  7. 60
  8. 80
  9. 100
  10. 120
  11. 140
  12. 150
  13. 160
  14. 170
  15. 180
  16. 190
  17. 210
  18. 230
  19. 250
  20. 270
  21. 290
  22. 300
  23. 310
  24. 320
  25. 330
  26. 340
  27. 350
  28. 370
  29. 390
  30. 410
  31. 430
  32. 450


用你的代码算出来的timecode v1是这样
  1. # timecode v1
  2. #startframe,endframe,framerate#starttime,endtime
  3. 0,3,75 #0,40
  4. 4,8,50 #60,140
  5. 9,13,100#150,190
  6. 14,18,50#210,290
  7. 19,24,100 #300,350
  8. 25,30,16#370,450


因为大部分视频每个node动辄上千帧所以1帧的错算出来的framerate近似没错吧,实际用的时候看不出来

还有个严重错误...最后一个Node你把分子和分母放反了...[/KH]




然后,如果你写的其他程序也是用的这个库的话,恐怕你还有一个错误(虽然已经不是这个库本身的错误了..),不然就不会一直没发现上述错误,恐怕你调用这个链表的时候用的是类似
  1. while(p->next) {
  2. p=p->next;
  3. //further processing
  4. }

这样的结构吧,并且用到的timeocode v2文件最后一帧的时间后面还有个回车(就是说文件最后有一个空白行);这样读取链表的时候实际上你会漏掉最后一个Node。由于你没考虑到空白行的处理,最后那个空白行也被当作一帧读入,而atof返回了0,结果就有个时长为0的1帧(本来不存在的一帧)的node存在,正好错误的遍历链表方法把这个node忽略了,而本来是最后一个node的timecode段也因为这个不该存在的node而变成了倒数第二个node从而避开了分母分子反了的错误而算出了正确framerate;而也因为最后一个node的分母分子放反了,所以在计算最后这个0时长的node的framerate的时候也没产生除0错误....

不学无术中..

eMule ID:[eDtoon][CHN]adamhj@eMule-Official
级别: 精灵王
注册时间:
2005-12-13
在线时间:
0小时
发帖:
3859
只看该作者 11楼 发表于: 2007-12-30
你很强大 我进来测试签名

= =
级别: 工作组
注册时间:
2005-05-03
在线时间:
0小时
发帖:
2914
只看该作者 12楼 发表于: 2007-12-31
引用
最初由 绿叶之砚 发布
我喷……你还真的放出来了

既然我都这么说过了,当然就……

引用
最初由 adamhj 发布
没考虑timecode v2文件里有空白行的情况

另外,别告诉我cframe初始值取-2是试出来的...老实说我囧了...

确实是试出来的[/KH]
引用
你取cframe=-1的时候对应的ctime是第0帧的,后面也是如此,cframe=n的时候的ctime是第n+1帧的,结果在算第一个node和最后一个node的framerate的时候却又按照ctime是第n帧的时间算的,所以第一个node和最后一个node算出来的帧率是错的

例如下面这个timcode
(略)

用你的代码算出来的timecode v1是这样
  1. # timecode v1
  2. #startframe,endframe,framerate#starttime,endtime
  3. 0,3,75 #0,40
  4. 4,8,50 #60,140
  5. 9,13,100#150,190
  6. 14,18,50#210,290
  7. 19,24,100 #300,350
  8. 25,30,16#370,450


因为大部分视频每个node动辄上千帧所以1帧的错算出来的framerate近似没错吧,实际用的时候看不出来

还有个严重错误...最后一个Node你把分子和分母放反了...[/KH]

[/KH]
引用
然后,如果你写的其他程序也是用的这个库的话,恐怕你还有一个错误(虽然已经不是这个库本身的错误了..),不然就不会一直没发现上述错误,恐怕你调用这个链表的时候用的是类似
  1. while(p->next) {
  2. p=p->next;
  3. //further processing
  4. }

这样的结构吧,并且用到的timeocode v2文件最后一帧的时间后面还有个回车(就是说文件最后有一个空白行);这样读取链表的时候实际上你会漏掉最后一个Node。由于你没考虑到空白行的处理,最后那个空白行也被当作一帧读入,而atof返回了0,结果就有个时长为0的1帧(本来不存在的一帧)的node存在,正好错误的遍历链表方法把这个node忽略了,而本来是最后一个node的timecode段也因为这个不该存在的node而变成了倒数第二个node从而避开了分母分子反了的错误而算出了正确framerate;而也因为最后一个node的分母分子放反了,所以在计算最后这个0时长的node的framerate的时候也没产生除0错误....


关于这个是怎么试出来的呢……呃,我借用了一个别人写的工具去算出一个timecode v1,那个工具是自称最后一行那个总帧数可能有点不对。
其他的那些帧信息也有好一部分是用那个做对照的

感谢指点!
级别: 工作组
注册时间:
2005-05-03
在线时间:
0小时
发帖:
2914
只看该作者 13楼 发表于: 2008-01-02
改了一下思想,起始时间是这一个帧率段的第一帧的开始时间,中止时间是这一个帧率段的最后一帧播放结束的时间(也就是下一个帧率段的第一帧开始播放的时间),delta想成是上一帧的持续时间,通过侦测持续时间的变化得到帧速率变化的点。
觉得现在的代码是正确的,比如前面淘气阿丹给的那个,结果是
  1. sf ef st et fps
  2. 0 3 0.00000040.000000 100.000000
  3. 4 8 40.000000 140.000000 50.000000
  4. 9 13 140.000000 190.000000 100.000000
  5. 14 18 190.000000 290.000000 50.000000
  6. 19 24 290.000000 350.000000 100.000000
  7. 25 30 350.000000 470.000000 50.000000


这次没有通过任何其它软件的转换结果作为对照了……个人感觉上的正确而已,要批的请随便批,等什么时候我无聊了就发到其他论坛去
级别: 新手上路
注册时间:
2003-06-23
在线时间:
1小时
发帖:
2882
只看该作者 14楼 发表于: 2008-01-02
这次你代码都没贴全...囧囧囧...

不学无术中..

eMule ID:[eDtoon][CHN]adamhj@eMule-Official
快速回复

限150 字节
上一个 下一个