Форум: "Начинающим";
Текущий архив: 2012.05.20;
Скачать: [xml.tar.bz2];
ВнизПередача видео и звука с помощью Indy Найти похожие ветки
← →
3asys © (2011-11-26 15:48) [0]На клиенте получаю видео и звук с web-камеры (с встроенным микрофоном) с помощью DirectShow.
Нужно передать их серверу для рассылки другим клиентам.
Видео и звук с Web-камеры получаю стандартным способом, описанным в примерах к DSPack, - примерно так:
var
multiplexer: IBaseFilter;
Writer: IFileSinkFilter;
PinList: TPinList;
i: integer;
begin
with MainForm do
begin
CaptureGraph.Active := true;
if AudioSourceFilter.FilterGraph <> nil then
begin
PinList := TPinList.Create(AudioSourceFilter as IBaseFilter);
i := 0;
while i < PinList.Count do
if PinList.PinInfo[i].dir = PINDIR_OUTPUT then
begin
if AudioFormats.ItemIndex <> -1 then
with (PinList.Items[i] as IAMStreamConfig) do
SetFormat(AudioMediaTypes.Items[AudioFormats.ItemIndex].AMMediaType^);
PinList.Delete(i);
end else inc(i);
if InputLines.ItemIndex <> -1 then
with (PinList.Items[InputLines.ItemIndex] as IAMAudioInputMixer) do
put_Enable(true);
PinList.Free;
end;
if VideoSourceFilter.FilterGraph <> nil then
begin
PinList := TPinList.Create(VideoSourceFilter as IBaseFilter);
if VideoFormats.ItemIndex <> -1 then
with (PinList.First as IAMStreamConfig) do
SetFormat(VideoMediaTypes.Items[VideoFormats.ItemIndex].AMMediaType^);
PinList.Free;
end;
with CaptureGraph as IcaptureGraphBuilder2 do
begin
// set the output filename
SetOutputFileName(MEDIASUBTYPE_Avi, PWideChar(CapFile), multiplexer, Writer);
if VideoSourceFilter.BaseFilter.DataLength > 0 then
RenderStream(@PIN_CATEGORY_PREVIEW, nil, VideoSourceFilter as IBaseFilter,
nil , form1.VideoWindow as IBaseFilter);
if VideoSourceFilter.FilterGraph <> nil then
RenderStream(@PIN_CATEGORY_CAPTURE, nil, VideoSourceFilter as IBaseFilter,
nil, multiplexer as IBaseFilter);
if AudioSourceFilter.FilterGraph <> nil then
begin
RenderStream(nil, nil, AudioSourceFilter as IBaseFilter,
nil, multiplexer as IBaseFilter);
end;
end;
CaptureGraph.Play;
В RenderStream получаем потоки, но как их передать через IdTCPClient, IdTCPServer я сообразить не могу.
Как это сделать?
← →
Плохиш © (2011-11-26 17:07) [1]Для начала надо изучить имеющиеся у используемого компонента методы.
← →
3asys © (2011-11-26 23:29) [2]> Плохиш ©
я научился передавать в потоке через связку TIdTCPClient - TIdTCPServer отдельные картинки из TImage (по таймеру), но мне не ясно, как загрузить видео и звук в поток из TFilterGraph (DSPack).
Или нужно желать как-то по другому?
← →
3asys © (2011-11-27 12:51) [3]Делать картинки с TVideoWindow не хотелось бы. Хочется передавать видео и звук в поток. А как это сделать в DSPack - никак не пойму. Может кто-нибудь это уже делал?
← →
3asys © (2011-11-27 22:55) [4]МОЖЕТ КОМУ-НИБУДЬ ПРИГОДИТСЯ:
Нашел, как можно транслировать получаемое с помощью DSPack видео в потоке между TIdTCPClient и TIdTCPServer:
На Клиенте, при запущенном процессе получения видео с web-камеры (как получить видео с web-камеры - есть в примерах для Delphi, прилагаемых к библиотеке DSPack), выполняем в таймере (TTimer):
procedure TForm1.Timer1Timer(Sender: TObject);
begin
bm:=TBitmap.Create; //Это у меня происходит в Form1.OnCreate
stream:=TMemoryStream.Create;
SampleGrabber.GetBitmap(bm);
bm.SaveToStream(stream);
stream.Position:=0;
IdTCPClient1.WriteStream(stream, true, true,0);
end;
На Сервере в событии Execute компонента TIdTCPServer пишем:
procedure TForm1.IdTCPServer1Execute(AThread: TIdPeerThread);
var
stream : TStream;
begin
try
stream:=TMemoryStream.Create;
AThread.Connection.ReadStream(stream,-1,False);
stream.Position:=0;
Image1.Picture.Bitmap.LoadFromStream(stream);
finally
stream.Free;
end;
end;
Запускаем Сервер, затем запускаем Клиента и видим в TImage размещенном на Сервере видео с TVideoWindow находящегося на Клиенте.
← →
Сергей М. © (2011-11-28 12:53) [5]А теперь разнеси своих клиента и сервера по разным углам Тырнета и полюбуйся тормозами транслируемого тобой видео.
Со звуком картина будет еще печальней.
← →
Dennis I. Komarov © (2011-11-28 13:35) [6]
> Со звуком картина будет еще печальней.
О каком звуке может идти речь, если передается простой Bitmap по таймеру?
Да и на клиенте "Out of memory" обеспечено...
← →
3asys © (2011-11-28 14:10) [7]> Сергей М.
> Dennis I. Komarov
Как было бы правильно передавать видео и звук (для избежания тормозов, которые есть конечно)?
← →
Сергей М. © (2011-11-28 14:10) [8]
> Dennis I. Komarov © (28.11.11 13:35) [6]
> передается простой Bitmap по таймеру
Ну это у ТС пока в планах, ибо
> Нужно передать их серверу для рассылки другим клиентам
Я о том что ТС изначально движется неверной дорогой, стремясь передать медиаданные вот таким незамысловатым макаром)
← →
Сергей М. © (2011-11-28 14:14) [9]
> 3asys © (28.11.11 14:10) [7]
Кодировать передаваемые данные в соответствии с протоколами передачи медиа в режиме реального времени - RTP, RTSP и иже с ними.
Но они подразумевают UDP на трансп.уровне.
← →
3asys © (2011-11-28 14:28) [10]> Сергей М.
Не могли бы вы привести пример такой реализации (или ее элементов) или ссылки на описание таких решений, если возможно, для delphi
← →
Dennis I. Komarov © (2011-11-28 14:57) [11]http://www.google.ru/#hl=ru&cp=23&gs_id=6&xhr=t&q=%D0%BF%D1%80%D0%BE%D1%82%D0%BE%D0%BA%D0%BE%D0%BB+%D0%BF%D0%B5%D1%80%D0%B5%D0%B4%D0%B0%D1%87%D0%B8+%D0%B2%D0%B8%D0%B4%D0%B5%D0%BE&pf=p&sclient=psy-ab&newwindow=1&site=&source=hp&pbx=1&oq=%D0%BF%D1%80%D0%BE%D1%82%D0%BE%D0%BA%D0%BE%D0%BB+%D0%BF%D0%B5%D1%80%D0%B5%D0%B4%D0%B0%D1%87%D0%B8+%D0%B2%D0%B8%D0%B4%D0%B5%D0%BE&aq=0&aqi=g1g-v2&aql=&gs_sm=&gs_upl=&bav=on.2,or.r_gc.r_pw.r_cp.,cf.osb&fp=6b74bf870ecf0e8a&bi w=1280&bih=915
← →
3asys © (2011-11-28 15:35) [12]> Dennis I. Komarov
Спасибо большое.
В виду того, что задача срочная, к сожалению, нет возможности сильно углубляться в изучение протокола, а способа ПРАКТИЧЕСКОЙ реализации я в интернете не нашел.
Хотел бы либо увидеть исходники полной или частичной реализации,
либо обсудить условия реализации соответствующего функционала (см. e-mail).
← →
Anatoly Podgoretsky © (2011-11-28 15:57) [13]> 3asys (28.11.2011 15:35:12) [12]
Ты что в Интернете есть куча реализаций, от бесплатных до очень дорогих
← →
Dennis I. Komarov © (2011-11-28 16:06) [14][Form + ] WebBrowser + Flash = уже почти клиент
← →
DVM © (2011-11-28 16:10) [15]
> 3asys ©
Проще всего передавать видео и аудио по HTTP. Не самый быстрый и производительный способ, но самый простой.
Вот посмотри как это делают IP камеры, передавая MJPEG и аудио:
http://www.axis.com/files/manuals/VAPIX_3_HTTP_API_3_00.pdf
← →
DVM © (2011-11-28 16:13) [16]
> Anatoly Podgoretsky ©
> Ты что в Интернете есть куча реализаций, от бесплатных до
> очень дорогих
Все на C++
> 3asys ©
Из бесплатных достойных не очень много, точнее мне известна лишь одна реализация RTSP/RTP сервера и клиента - библиотека live555. И разумеется она на C++. Из нее вероятно можно попробовать сделать dll и использовать в Delphi (может кто-то уже и сделал dll) но трудоемко. И начинать надо с изучения RFC соответствующих. С HTTP проще на порядок все.
← →
Anatoly Podgoretsky © (2011-11-28 16:34) [17]> DVM (28.11.2011 16:13:16) [16]
> Все на C++
Неправда есть в виде готовых программ. Кроме того чем С++ плох. Ты его не
любишь/Не занешь - твое горе
← →
DVM © (2011-11-28 16:46) [18]
> Anatoly Podgoretsky © (28.11.11 16:34) [17]
> Неправда есть в виде готовых программ.
Ему же надо в свою программу встраивать. То, что есть готовые программы никто не отрицает. Их немало. VLC например.
> Кроме того чем С++ плох. Ты его не
> любишь/Не занешь - твое горе
Я здесь причем? Автор программу на Delphi пишет.
← →
3asys © (2011-11-28 16:52) [19]> All
Спасибо :)
Что реализовать можно - знаю, имел к практической реализации таких систем (не публичных) некоторое отношение. Но сейчас нужно сделать свою и "вчера".
Стал делать на Delphi просто потому, что работал на нем (не с мультимедиа) и какое-то кол-во граблей представляю.
Пробовал ActionScript, но в проекте есть компоненты, реализовать которые на нем мне показалось сложнее, чем на Delphi (для меня) - эти комопненты реализовал.
С предложенными здесь рекомендациями 100% согласен, но проблема на самом деле простая - отсутствие времени (нет пары месяцев чтобы во всем спокойно разобраться), поэтому и пытаюсь найти готовые фрагменты, дописывая только швы.
Если бы кто-то имеющий опыт практической реализации систем видеоконференцсвязи согласился бы поучаствовать в реализации, надеюсь смогли бы договориться.
← →
Gu (2011-11-28 17:14) [20]http://lakeofsoft.com/vc/
интересные компоненты, там похоже то что вам надо. в сети есть enterprise 2010 (последняя 2011) версия с исходниками.
← →
3asys © (2011-11-28 17:30) [21]> Gu
Спасибо, очень интересно - попробую для работы со звуком
← →
DVM © (2011-11-28 18:22) [22]
> 3asys ©
Еще раз советую HTTP юзать, передача звукового потока и кадров реализуется элементарно, буквально 100 строк, прием тоже столько же примерно. Если решишь делать, задавай тут вопросы объясню как. По RTSP/RTP в принципе тоже мог бы объяснить, но эта тема очееень обширная.
← →
3asys © (2011-11-28 18:36) [23]> DVM
Спасибо, с удовольствием. Поскольку времени практически нет - то чем быстрее реализация тем лучше.
Что нужно для реализации через http?
← →
Dennis I. Komarov © (2011-11-28 18:56) [24]http-сервер, который будет получать поток с камеры и раздавать клиентам
← →
DVM © (2011-11-28 19:02) [25]Первое что тебе понадобится - это сделать потокобезопасный кадровый буфер. Для начала сойдет буфер на один кадр. Потокобезопасность можно организовать через защиту буфера критической секцией. С одной стороны этот буфер будет обновляться источником кадров (твоей камерой ), с другой стороны оттуда вебсервер из клиентского потока будет забирать очередной кадр для передачи клиенту. Такая схема позволяет клиенту автоматически подстраиваться под ширину канала.
← →
DVM © (2011-11-28 19:12) [26]Второё , что понадобится - это сервер TIDHttpServer, он у нас будет передавать клиенту бесконечный поток данных с особым типом контента multipart/x-mixed-relace. Этот тип контента позволяет передавать практически сколько угодно параллельных потоков чего угодно. То есть можно передавать видео звук субтитры и прочее вместе. Но можно сделать отдельные потоки для звука и видео, что. Проще при приеме.
← →
Dennis I. Komarov © (2011-11-28 19:13) [27]
> DVM © (28.11.11 19:02) [25]
А не накладно будет покадрово передавать, тем более с камеры?
← →
DVM © (2011-11-28 19:18) [28]Как показывает практика не накладно. Мы же не будем для каждого кадра делать запрос, запрос будет сделан 1 раз.Остальное позже напишу - с телефона неудобно.
← →
3asys © (2011-11-28 19:22) [29]В качестве http сервера IdHTTPServer подойдет?
Если буфер обмена создается на клиенте, как данные от клиента попадут на сервер? или каждый клиент одновременно и сервер?
← →
3asys © (2011-11-28 19:25) [30]:) про IdHTTPServer понятно (написал не посмотрев сообшения)
← →
DVM © (2011-11-28 19:53) [31]Если нужна двусторонняя передача видео, то для http каждый клиент должен быть одновременно сервером и клиентом для сервера другого клиента так как в http данные всегда передаются в основном канале в отличие от RTSP или SIP в котором RTP данные могут передаваться как поверх основного канала так и в независимых и в обоих направлениях.
← →
3asys © (2011-11-28 21:24) [32]это видеоконференция и в ней каждый клиент передает другим видео и звук со своей web-камеры/микрофона.
я полагал, что должно быть N клиентов, каждый из которых передает свои видео и звук серверу, а сервер транслирует их всем остальным. Это не так?
← →
DVM © (2011-11-28 22:09) [33]
> я полагал, что должно быть N клиентов, каждый из которых
> передает свои видео и звук серверу, а сервер транслирует
> их всем остальным. Это не так?
Это может быть и так, а можно и по другому. Если все будет проходить через сервер, то нагрузка на него будет большая при большом числе клиентов, если видео не будет идти через сервер, то нагрузка на него будет минимальная, но будет меньше контроля. Вообще все это - это вопрос коммутации, это отдельный разговор. Вот SIP или RTSP и есть протоколы, которые предназначены для коммутации. У тебя задача пока хотя бы передать данные между 2-мя пользователями. А там дальше будешь думать.
← →
3asys © (2011-11-28 22:10) [34]согласен
← →
DVM © (2011-11-28 22:18) [35]Короче у тебя 3 пути:
1) Использовать самописный протокол для коммутации и передачи медиаданных.
2) Использовать HTTP и для передачи и для коммутации.
3) Использовать SIP для коммутации и RTP для передачи (вот этот вариант самый правильный, и вобщем то повсеместно используется в IP телефонии)
4) Использовать что-то типа http://ru.wikipedia.org/wiki/XMPP
Что выбираешь?
← →
3asys © (2011-11-28 22:25) [36]мне необходимо реализовать конференцию в минимальные сроки и чтобы она работала с приемлемым качеством человек на 50. Как я понял, самый быстрый способ - http - поэтому HTTP
← →
DVM © (2011-11-28 22:30) [37]
> 3asys © (28.11.11 22:25) [36]
Ну HTTP так HTTP. Щас набросаю тебе пример.
← →
DVM © (2011-11-28 23:10) [38]
unit uMain;
interface
uses
Winapi.Windows, Winapi.Messages, System.SysUtils, System.Variants, System.Classes, Vcl.Graphics,
Vcl.Controls, Vcl.Forms, Vcl.Dialogs, System.SyncObjs, Vcl.Imaging.jpeg,
Vcl.ExtCtrls,
IdBaseComponent, IdComponent, IdTCPServer, IdCustomHTTPServer, IdGlobal,
IdHTTPServer, IdCustomTCPServer, IdContext, IdSchedulerOfThread, IdGlobalProtocols;
type
TSafeBuffer = class(TMemoryStream)
strict private
FLock: TCriticalSection;
public
constructor Create;
destructor Destroy; override;
procedure Lock;
procedure Unlock;
end;
TfrmMin = class(TForm)
tmrUpdateFrame: TTimer;
idhtpsrvrMain: TIdHTTPServer;
procedure tmrUpdateFrameTimer(Sender: TObject);
procedure FormCreate(Sender: TObject);
procedure FormDestroy(Sender: TObject);
procedure idhtpsrvrMainCommandGet(AContext: TIdContext;
ARequestInfo: TIdHTTPRequestInfo; AResponseInfo: TIdHTTPResponseInfo);
private
{ Private declarations }
public
Buffer: TSafeBuffer;
end;
var
frmMin: TfrmMin;
implementation
{$R *.dfm}
constructor TSafeBuffer.Create;
begin
FLock := TCriticalSection.Create;
inherited Create;
end;
destructor TSafeBuffer.Destroy;
begin
inherited Destroy;
FLock.Free;
end;
procedure TSafeBuffer.Lock;
begin
FLock.Enter;
end;
procedure TSafeBuffer.Unlock;
begin
FLock.Leave;
end;
procedure TfrmMin.FormCreate(Sender: TObject);
begin
Buffer := TSafeBuffer.Create;
end;
procedure TfrmMin.FormDestroy(Sender: TObject);
begin
Buffer.Free;
end;
procedure TfrmMin.idhtpsrvrMainCommandGet(AContext: TIdContext;
ARequestInfo: TIdHTTPRequestInfo; AResponseInfo: TIdHTTPResponseInfo);
const
Boundary = "--myboundary";
CRLF = #13#10;
var
Stream: TMemoryStream;
SubHeader: AnsiString;
begin
Stream := TMemoryStream.Create;
try
AResponseInfo.FreeContentStream := false;
AResponseInfo.Server := "StreamServer";
AResponseInfo.CacheControl := "no-cache";
AResponseInfo.Pragma := "no-cache";
AResponseInfo.Expires := Now;
AResponseInfo.CharSet :="";
AResponseInfo.Connection := "close";
AResponseInfo.ContentType := "multipart/x-mixed-replace; boundary=" + Boundary;
AResponseInfo.ContentLength := 1000000;
AResponseInfo.WriteHeader;
while ((not (AContext.Yarn as TIdYarnOfThread).Thread.Terminated) and (AContext.Connection.Connected)) do
begin
Buffer.Lock;
try
AResponseInfo.ContentLength := Buffer.Size;
SubHeader := AnsiString(Boundary + CRLF +
"Content-Type: image/jpeg" + CRLF +
"Content-Length: " + IntToStr(AResponseInfo.ContentLength) + CRLF + CRLF);
Stream.Size := 0;
Stream.Write(SubHeader[1], length(SubHeader));
Stream.Write(Buffer.Memory^, Buffer.Size);
finally
Buffer.Unlock;
end;
Stream.Position := 0;
AResponseInfo.ContentStream := Stream;
AResponseInfo.WriteContent;
Sleep(100);
end;
finally
Stream.Free;
end;
end;
procedure TfrmMin.tmrUpdateFrameTimer(Sender: TObject);
var
Bmp: TBitmap;
JPG: TJPEGImage;
begin
Bmp := TBitmap.Create;
try
Bmp.Width := 320;
Bmp.Height := 240;
Bmp.PixelFormat :=pf24bit;
Bmp.Canvas.TextOut(50, 50, FormatDateTime("hh:nn:ss.zzz", Now));
JPG := TJPEGImage.Create;
try
JPG.Assign(Bmp);
Buffer.Lock;
try
Buffer.Size := 0;
JPG.SaveToStream(Buffer);
Buffer.Position :=0;
finally
Buffer.Unlock;
end;
finally
JPG.Free;
end;
finally
Bmp.Free;
end;
end;
end.
← →
DVM © (2011-11-28 23:15) [39]Итак, что тут к чему. Во-первых, это лишь пример, иллюстрирующий принцип. Не надо отсюда слепо копировать.
На форму кинуть таймер и TIdHTTPServer. Таймер нужен лишь для генерации картинок (типа кадры), интервал у таймера стоит 100.
TidHTTPServer слушает порт 8081.
Запускаем все это дело, берем Firefox (и только его, другие браузеры не понимают этот формат) и обращаемся в нем по адресу http://127.0.0.1:8081
Видим в окне браузера сменяющие друг друга картинки, фактически видео.
← →
DVM © (2011-11-28 23:19) [40]Особые моменты в коде.
AResponseInfo.ContentLength := 1000000;
Indy всегда пытается всунуть в заголовок ответа сервера ContentLength, идеально было бы вообще без него, но от него не избавиться, поэтому ставим заведомо большое число, оно мало на что влияет, но 0 ставить нельзя.
Sleep(100);
Костыль. Ограничивает частоту кадров на клиенте. Частоту кадров стоит вычислять более умно. Хотя можно просто ограничить скажем величиной 25. Но все равно надо рассчитать тогда паузу между кадрами, чтоб получалось 25 кадров в секунду.
Страницы: 1 2 3 4 5 вся ветка
Форум: "Начинающим";
Текущий архив: 2012.05.20;
Скачать: [xml.tar.bz2];
Память: 0.59 MB
Время: 0.005 c