田克平(94338047) 16:57:34
能自己设置某帧为关键帧吗?
抱柱者(86311414) 16:57:59
to 田克平
可以
田克平(94338047) 17:00:00
呵呵,把丢包后的下一帧设置为I帧可以吗?来处理丢帧现象
☆雪天/kf☆(279373002) 17:00:42
这个难度大了
田克平(94338047) 17:01:15
难度在哪?
抱柱者(86311414) 17:01:53
如果1to1那应该可行,但是要是传到多点那可能比较麻烦
田克平(94338047) 17:03:54
谢谢
抱柱者(86311414) 17:04:05
比如传至A、B两点,到A的丢包很少,而到B丢包较多,那A也要因为B点而经常接受关键帧
抱柱者(86311414) 17:04:29
不过你也可以现象折中的方法
抱柱者(86311414) 17:04:38
不过你也可以想想折中的方法
田克平(94338047) 17:04:48
就1to1的话、、、
田克平(94338047) 17:05:11
怎么做
抱柱者(86311414) 17:05:22
就像你说的做啊
抱柱者(86311414) 17:05:50
丢包了就通知编码端,下一帧编为关键帧
田克平(94338047) 17:06:07
好的,谢谢
☆雪天/kf☆(279373002) 17:06:16
田克平(94338047) 17:00:00
呵呵,把丢包后的下一帧设置为I帧可以吗?来处理丢帧现象
编码的时候你怎么会知道哪一帧会丢?
☆雪天/kf☆(279373002) 17:07:55
除非你有反馈通道
抱柱者(86311414) 17:08:58
肯定是反馈啊,正常可能是丢包了就通知编码端重发,现在改为通知编码端设置关键帧
傻子更聪明(120928606) 17:09:43
这样好象实时性比较差啊,也难免不会再被丢。
呵呵(369873095) 17:10:11
网络的来回时间考虑了吗(RTT)
☆雪天/kf☆(279373002) 17:10:15
这样效率很低呀
☆雪天/kf☆(279373002) 17:10:25
你编码器一直要等在那里
抱柱者(86311414) 17:11:07
他是设置下一帧为关键帧,而不是处理丢了的那一帧,所以实时性应该没有问题
田克平(94338047) 17:11:09
丢包了不通知吗
☆雪天/kf☆(279373002) 17:11:21
两次传输路径时间+解码器处理时间 编码器无法并行
☆雪天/kf☆(279373002) 17:12:25
就是说你反馈回来的时候 编码器已经编到后面去了 丢的哪一帧后面的一帧 早编完了
抱柱者(86311414) 17:12:57
编码器为什么要等?
编码器就按正常的编码,如果解码器反馈丢包了,应用程序就修改编码参数设置关键帧,与并行扯不上关系
田克平(94338047) 17:12:58
好像是这样啊
傻子更聪明(120928606) 17:14:09
网络UDP不可靠传输,多少秒来一个关键帧比较合适?
抱柱者(86311414) 17:14:16
为什么要局限于下一帧,下两帧也没关系啊
抱柱者(86311414) 17:14:35
反正只是要尽快出现一个关键帧就行了
☆雪天/kf☆(279373002) 17:15:13
你说的没错 但是一个反馈的时间编码器可能已经编码了好多帧了
☆雪天/kf☆(279373002) 17:15:56
所以只能说是一接到反馈就立即置I帧
☆雪天/kf☆(279373002) 17:22:06
可以结合周期插入I帧一起来用 周期可以大一点
田克平(94338047) 17:23:10
关键帧间隔是定好的、、、
抱柱者(86311414) 17:23:15
肯定是会有固定关键帧周期的
傻子更聪明(120928606) 17:23:48
这种方法是在关键帧间隔比较大的情况下可以用。
田克平(94338047) 17:24:42
2s间隔有什么问题
傻子更聪明(120928606) 17:25:06
而且非关键帧丢失后怎么处理?会有花屏之类的。
傻子更聪明(120928606) 17:25:39
把导致花屏的帧丢掉后,图象会有停顿。
田克平(94338047) 17:25:52
间隔很小的话当然是作用不大
☆雪天/kf☆(279373002) 17:25:58
那也没有办法 只能跳到下一个I帧
呵呵(369873095) 17:26:24
在码率大的时候,一帧的数据都是由几十个包承载的,多个包里掉一个包(几个包)是否反馈要求I帧
☆雪天/kf☆(279373002) 17:27:21
那倒不用 使用EC足够应付了
傻子更聪明(120928606) 17:27:22
网络传输应该不用I帧吧?把I帧全变为IDR帧,这样才有意义。
sunj(39310543) 17:28:42
这个问题有rfc来定义的
傻子更聪明(120928606) 17:28:42
错误掩藏,解码器不支持的话,怎么整。也需要编码器支持吧?。
sunj(39310543) 17:28:52
消息已经标准化了
☆雪天/kf☆(279373002) 17:29:34
简单的块copy就可以搞定这个了 不需要编码器做什么
傻子更聪明(120928606) 17:31:12
这样子,也是会引起连续的失真。。
☆雪天/kf☆(279373002) 17:22:06
可以结合周期插入I帧一起来用 周期可以大一点
田克平(94338047) 17:23:10
关键帧间隔是定好的、、、
抱柱者(86311414) 17:23:15
肯定是会有固定关键帧周期的
傻子更聪明(120928606) 17:23:48
这种方法是在关键帧间隔比较大的情况下可以用。
田克平(94338047) 17:24:42
2s间隔有什么问题
傻子更聪明(120928606) 17:25:06
而且非关键帧丢失后怎么处理?会有花屏之类的。
傻子更聪明(120928606) 17:25:39
把导致花屏的帧丢掉后,图象会有停顿。
田克平(94338047) 17:25:52
间隔很小的话当然是作用不大
☆雪天/kf☆(279373002) 17:25:58
那也没有办法 只能跳到下一个I帧
呵呵(369873095) 17:26:24
在码率大的时候,一帧的数据都是由几十个包承载的,多个包里掉一个包(几个包)是否反馈要求I帧
☆雪天/kf☆(279373002) 17:27:21
那倒不用 使用EC足够应付了
傻子更聪明(120928606) 17:27:22
网络传输应该不用I帧吧?把I帧全变为IDR帧,这样才有意义。
sunj(39310543) 17:28:42
这个问题有rfc来定义的
傻子更聪明(120928606) 17:28:42
错误掩藏,解码器不支持的话,怎么整。也需要编码器支持吧?。
sunj(39310543) 17:28:52
消息已经标准化了
☆雪天/kf☆(279373002) 17:29:34
简单的块copy就可以搞定这个了 不需要编码器做什么
傻子更聪明(120928606) 17:31:12
这样子,也是会引起连续的失真。。
main()
{
...
while (decode_one_frame(img, input, snr) != EOS);
...
}
然后在decode_one_frame()
{
...
currSlice->next_header = -8888;
.....
while ((currSlice->next_header != EOS && currSlice->next_header != SOP))
{
current_header = read_new_slice();
if (current_header == EOS)
{
exit_picture();
return EOS;
}
decode_slice(img, inp, current_header);
...
}
...
exit_picture();
return (SOP);
}
按照上面的代码,经过跟踪发现,currSlice->next_header 一直不变,那么decode_one_frame()中的while循环永远不会因为条件的不满足而跳出循环,只会因为current_header == EOS条件的满足而推出该函数。
因此 decode_one_frame()函数只可能返回EOS,而不会是SOP;那么main()中的while循环将只会执行一次。而且在代码跟踪的过程中发现,输入码流的所有序列是在decode_one_frame()函数中全部解出,然后才推出该函数。
请教各位,jm为什么要这样呢?还是我什么地方没注意到?谢谢了
A:再次仔细跟踪了一下代码发现,jm整个解码的结构是这样的:
1。在main中调用while (decode_one_frame(img, input, snr) != EOS);
但实际上,这个while只会循环一次,因为decode_one_frame()只可能返回EOS(下面讲为什么?)
2。在decode_one_frame()中通过调用
while ((currSlice->next_header != EOS && currSlice->next_header != SOP))
{
current_header = read_new_slice();
if (current_header == EOS)
{
exit_picture();
return EOS;
}
decode_slice(img, inp, current_header);
...
}
解码所有帧。如上所述,currSlice->next_header根本没有起到任何作用,因为没有其他地方为 其赋值,为什么呢?
因为如果要想知道next_header必须要将下一个slice码流读进来,再进行解析,既然已经读进来,不管判断的是一个新的pic,还是同一个pic中的新的slice,都必须立刻进行解码,也就没有必要再回到main()中的while循环了。
实际上起作用的是current_header,即通过read_new_slice()来获得,(sop or sos):
if(is_new_picture())
{
init_picture(img, input);
current_header = SOP;//start of pic
}
else
current_header = SOS;//start of slice
如果current_header=sop,那么将会调用init_picture(),这个函数主要实现两个功能:首先,通过exit_picture()把上一次解码的图像及相关信息进行保存等处理 然后,再为当前slice(新的一帧)的解码做好准备。如果current_header=sos,那么将不会调用init_picture(),直接利用当前pic的准备信息进行解码。如果在read_new_slice()中发现已经到码流的结尾了,那么将返回EOS.
这时在decode_one_frame()中,一旦current_header==EOS,那么将退出解码,返回到main()中来。值得注意的是,返回之前,它还是调用了exit_picture(),从而将最后一个解码帧进行保存。
大概流程应该就是这样,如果有漏掉或错误的地方还请高手补充指正。总之jm中的有些函数的内容并不一定与其函数名称相吻合,这可能也是他们开发到后期没有办法的事情。不知道x264或其他的解码器是不是如此复杂?