diff --git a/tv/tuner/aidl/vts/functional/utils/IpStreamer.cpp b/tv/tuner/aidl/vts/functional/utils/IpStreamer.cpp new file mode 100644 index 0000000000..02b2633256 --- /dev/null +++ b/tv/tuner/aidl/vts/functional/utils/IpStreamer.cpp @@ -0,0 +1,57 @@ +#include "IpStreamer.h" + +IpStreamer::IpStreamer() {} + +IpStreamer::~IpStreamer() {} + +void IpStreamer::startIpStream() { + ALOGI("Starting IP Stream thread"); + mFp = fopen(mFilePath.c_str(), "rb"); + if (mFp == nullptr) { + ALOGE("Failed to open file at path: %s", mFilePath.c_str()); + return; + } + mIpStreamerThread = std::thread(&IpStreamer::ipStreamThreadLoop, this, mFp); +} + +void IpStreamer::stopIpStream() { + ALOGI("Stopping IP Stream thread"); + close(mSockfd); + if (mFp != nullptr) fclose(mFp); + if (mIpStreamerThread.joinable()) { + mIpStreamerThread.join(); + } +} + +void IpStreamer::ipStreamThreadLoop(FILE* fp) { + mSockfd = socket(AF_INET, SOCK_DGRAM, 0); + if (mSockfd < 0) { + ALOGE("IpStreamer::ipStreamThreadLoop: Socket creation failed (%s)", strerror(errno)); + exit(1); + } + + if (mFp == NULL) { + ALOGE("IpStreamer::ipStreamThreadLoop: Cannot open file %s: (%s)", mFilePath.c_str(), + strerror(errno)); + exit(1); + } + + struct sockaddr_in destaddr; + memset(&destaddr, 0, sizeof(destaddr)); + destaddr.sin_family = mIsIpV4 ? AF_INET : AF_INET6; + destaddr.sin_port = htons(mPort); + destaddr.sin_addr.s_addr = inet_addr(mIpAddress.c_str()); + + char buf[mBufferSize]; + int n; + while (1) { + if (fp == nullptr) break; + n = fread(buf, 1, mBufferSize, fp); + ALOGI("IpStreamer::ipStreamThreadLoop: Bytes read from fread(): %d\n", n); + if (n <= 0) { + break; + } + sendto(mSockfd, buf, n, 0, (struct sockaddr*)&destaddr, sizeof(destaddr)); + sleep(mSleepTime); + } +} diff --git a/tv/tuner/aidl/vts/functional/utils/IpStreamer.h b/tv/tuner/aidl/vts/functional/utils/IpStreamer.h new file mode 100644 index 0000000000..d073003c98 --- /dev/null +++ b/tv/tuner/aidl/vts/functional/utils/IpStreamer.h @@ -0,0 +1,48 @@ +#pragma once + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/** + * IP Streamer class to send TS data to a specified socket for testing IPTV frontend functions + * e.g. tuning and playback. + */ + +class IpStreamer { + public: + // Constructor for IP Streamer object + IpStreamer(); + + // Destructor for IP Streamer object + ~IpStreamer(); + + // Starts a thread to read data from a socket + void startIpStream(); + + // Stops the reading thread started by startIpStream + void stopIpStream(); + + // Thread function that consumes data from a socket + void ipStreamThreadLoop(FILE* fp); + + std::string getFilePath() { return mFilePath; }; + + private: + int mSockfd = -1; + FILE* mFp; + bool mIsIpV4 = true; // By default, set to IPV4 + int mPort = 12345; // default port + int mBufferSize = 188; // bytes + int mSleepTime = 1; // second + std::string mIpAddress = "127.0.0.1"; // default IP address + std::string mFilePath = "/data/local/tmp/segment000000.ts"; // default path for TS file + std::thread mIpStreamerThread; +}; \ No newline at end of file