尝试从 YouTube 读取视频流时出现伪像

Posted

技术标签:

【中文标题】尝试从 YouTube 读取视频流时出现伪像【英文标题】:Getting artifacts when trying to read video stream from YouTube 【发布时间】:2011-10-09 20:34:44 【问题描述】:

我正在尝试从我从 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 我只是使用标准的 avformat_open_input 和 URL 作为路径 【参考方案1】:

传输协议是您请求的 IP 套接字的属性。因此,您可以在 TCP 和 UDP 传输上使用相同的 url(和 ip:port)。这意味着由客户端打开 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 接收数据。 问题是“我怎样才能强制建立 TCP 连接”......答案是要求它。客户端选择传输,这完全独立于是否提供 tcp 或 udp 传输的服务器。现在,是否 youtube 有 TCP rtsp:// 接口?这实际上是一个不同的问题。【参考方案2】:
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);

//...

【讨论】:

【参考方案3】:

RTSP RFC (http://www.ietf.org/rfc/rfc2326.txt) 似乎建议您可以在第 12.39 节的请求中指定您的首选传输方式。我不知道这是否有帮助。

【讨论】:

以上是关于尝试从 YouTube 读取视频流时出现伪像的主要内容,如果未能解决你的问题,请参考以下文章

Youtube 数据 api v3 视频上传错误

使用delphi在Android下的TWebbrowser中全屏观看youtube或其他视频时出现问题

如何读取从 Youtube API Kotlin/Java 返回的视频的持续时间

更改 YouTube 视频嵌入的背景颜色

OpenCV Python,从命名管道中读取视频

从画布读取时出现 IE9 安全错误(非跨域)