从YouTube读取视频流时出现工件问题

13
我正在尝试从我从YouTube获得的RTSP流中读取视频帧。这是我的测试视频链接:

rtsp://v8.cache5.c.youtube.com/CiILENy73wIaGQkJlrXMiAG8BxMYDSANFEgGUgZ2aWRlb3MM/0/0/0/video.3gp

如果我从本地文件中读取帧-一切都很好,但是当我从流中读取它们时,除了大量伪像之外什么都没有。我在谷歌上搜索并发现可能存在UDP数据包问题,转换为TCP可以帮助解决,但我真的无法找到更改此设置的位置。
以下是读取帧的函数:
bool nextFrame(AVFormatContext *pFormatCtx, AVCodecContext *pCodecCtx, int videoStream, AVFrame *pFrame) {  AVPacket packet;
    int frameFinished = 0;

    while( !frameFinished && av_read_frame(pFormatCtx, &packet) >= 0 ) {
        // Is this a packet from the video stream?
        if( packet.stream_index == videoStream ) {
            // Decode video frame
            avcodec_decode_video2(pCodecCtx, pFrame, &frameFinished, &packet);
        }

        // Free the packet that was allocated by av_read_frame
        av_free_packet(&packet);    
       }    
       return frameFinished!=0;  
}

我的日志中也有大量的错误消息:

[h263 @ 0x7804c00] warning: first frame is no keyframe
[h263 @ 0x7804c00] illegal ac vlc code at 6x1
[h263 @ 0x7804c00] Error at MB: 18
[h263 @ 0x7804c00] concealing 99 DC, 99 AC, 99 MV errors
[h263 @ 0x7804c00] I cbpy damaged at 10 4
[h263 @ 0x7804c00] Error at MB: 58
[h263 @ 0x7804c00] concealing 99 DC, 99 AC, 99 MV errors
[h263 @ 0x7804c00] I cbpy damaged at 6 6
[h263 @ 0x7804c00] Error at MB: 78
[h263 @ 0x7804c00] concealing 76 DC, 76 AC, 76 MV errors
[h263 @ 0x7804c00] I cbpy damaged at 5 5
[h263 @ 0x7804c00] Error at MB: 65
[h263 @ 0x7804c00] concealing 88 DC, 88 AC, 88 MV errors
[h263 @ 0x7804c00] illegal ac vlc code at 7x5
[h263 @ 0x7804c00] Error at MB: 67
[h263 @ 0x7804c00] concealing 86 DC, 86 AC, 86 MV errors

编辑:问题99.9%是UDP-TCP问题。我找到了这个链接:

rtsp://195.200.199.8/mpeg4/media.amp

这是一个在线可用的测试摄像头。它会带有伪影的流。但是,如果它有“tcp”参数并且我使用以下内容

rtsp://195.200.199.8/mpeg4/media.amp?tcp

所有内容都可以正常运行,不带伪影。

因此,为了纠正我的问题:是否有任何方法强制YouTube或ffmpeg使用TCP?


你正在使用哪个函数来打开与URL的连接?你是否编写了自己的URLContext? - JConway
@JConway 我只是使用标准的avformat_open_input函数,URL作为路径。 - givi
3个回答

3
传输协议是您请求的IP套接字的属性。因此,您可以在TCP和UDP传输上具有相同的URL(和IP:端口)。这意味着客户端需要打开TCP端口而不是UDP端口。这是在创建套接字时选择的。
sock = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP)

或者

sock = socket(PF_INET, SOCK_STREAM, IPPROTO_UDP)

现在,我不知道ffmpeg在哪里执行此操作,但上面的内容肯定可以给你一个提示,让你知道如何找到它。


不,这不是客户端的问题。如果服务器不通过TCP发送数据,客户端会怎么做呢?如果YouTube仅通过UDP发送RTSP流数据,则客户端无法从TCP端口接收数据;该TCP端口上将没有任何内容。因此,只有当服务器通过TCP发送数据时,客户端才能够通过TCP接收数据。 - Muhammad Razib
5
问题是“如何强制建立TCP连接”...答案是请求它。客户端选择传输方式,这完全独立于服务器是否提供TCP或UDP传输。现在,YouTube是否有TCP的rtsp://接口?那实际上是一个不同的问题。 - moliad

1
AVDictionary *format_opts = NULL;
av_dict_set(&format_opts,"rtsp_transport","tcp",0); 

if(avformat_open_input(&context, url,NULL, **&format_opts**) != 0)
{ 
av_dict_free(&format_opts);
return; //error
} 

//if you want more info about RTSP session, you can use RTSPState
//(#include "libavformat\rtsp.h") :
RTSPState *pRTSPState = (RTSPState*)context->priv_data;

//.....

av_dict_free(&format_opts);

//...

0

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接