Получение артефактов при попытке чтения видеопотока с YouTube
Я пытаюсь прочитать видеофрагменты из потока RTSP, которые я получаю с YouTube. Вот ссылка для моего тестового видео:
RTSP://v8.cache5.c.youtube.com/CiILENy73wIaGQkJlrXMiAG8BxMYDSANFEgGUgZ2aWRlb3MM/0/0/0/video.3gp
Если я читаю фреймы из локального файла - все в порядке, но, читая их из потока, я получаю только множество артефактов. Я googled вокруг и узнал, что может быть проблема с 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
... и т.д.
edit: это 99.9% проблема UDP-TCP. Я нашел эту ссылку:
RTSP://195.200.199.8/mpeg4/media.amp
Это тестовая камера, доступная онлайн. Он струится с артефактами. Однако, если он получил параметр tcp, и если я использую этот
RTSP://195.200.199.8/mpeg4/media.amp ТСР
все работает без артефактов.
Итак, чтобы исправить мой вопрос: есть ли способ заставить YouTube или ffmpeg использовать TCP?
Ответы
Ответ 1
транспортный протокол является свойством запрашиваемого IP-сокета. как таковой, вы можете иметь один и тот же url (и ip: port) как на транспорте TCP, так и на UDP. Это означает, что клиент может открыть порт TCP, а не порт UDP.
Это выбирается при создании вашего сокета.
sock = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP)
или
sock = socket(PF_INET, SOCK_STREAM, IPPROTO_UDP)
Теперь у меня нет подсказки, где ffmpeg делает это, но, несомненно, вышеописанное может дать вам понять, как это выяснить.
Ответ 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. Я не знаю, помогает ли это.