The task could be easily performed using the r.viewshed GRASS module available from the Processing Toolbox.
From its Documentation:
r.viewshed is a module that computes the viewshed of a point on a
raster terrain. That is, given an elevation raster, and the location
of an observer, it generates a raster output map showing which cells
are visible from the given location. The algorithm underlying
r.viewshed minimizes both the CPU operations and the transfer of data
between main memory and disk; as a result r.viewshed runs fast on very
large rasters.
For running the analysis, you only need a Digital Terrain Model and the coordinates of one point. This is an example of a possible output (the output is a raster):

If you want to programmatically perform the task for a point vector layer and using PyQGIS, you may simply use the following code as a reference, running it from the Python Console (it is available from Plugins >> Python Console
):
import processing
rasterLayer =QgsRasterLayer('C:/path/to/point/layer/raster_layer.tif', 'raster')
pointLayer=QgsVectorLayer('C:/path/to/point/layer/point_layer.shp', 'points' , 'ogr')
# Get the extent from the raster layer
extent = rasterLayer.extent()
xmin = extent.xMinimum()
xmax = extent.xMaximum()
ymin = extent.yMinimum()
ymax = extent.yMaximum()
region_extent = "%f,%f,%f,%f" %(xmin, xmax, ymin, ymax) # set the extent for the output, which is equal to the extent of the input raster
i=0
for feat in pointLayer.getFeatures():
point = feat.geometry().asPoint() # get the geometry for the current point feature
coordStr = '%d,%d' % (point.x(),point.y()) # get the coordinates and store them in a string
# set the path for the output raster
outputViewshed = 'C:/path/to/the/output/output_raster_%i.tif' %(i)
#running viewshed with observer elevation set at 20 m, target elevetion set to 0 m and a max distance of 800 m
output = processing.runalg('grass7:r.viewshed', rasterLayer, coordStr, '20', '0', '800', 0.14286, 500, False, False, False, False, region_extent, 0, outputViewshed)
i += 1
The outputs returned is a number of rasters that is equal to the number of the features from the point layer.
For knowing the syntax required by the r.viewshed module, you may simply run this code from the Python Console:
import processing
processing.alghelp('grass7:r.viewshed')
and you will obtain a brief description of each parameter (for a deeper understanding and the complete description of them, please refer to the documentation):
ALGORITHM: r.viewshed - Computes the viewshed of a point on an elevation raster map.
input <ParameterRaster>
coordinates <ParameterPoint>
observer_elevation <ParameterString>
target_elevation <ParameterString>
max_distance <ParameterString>
refraction_coeff <ParameterNumber>
memory <ParameterNumber>
-c <ParameterBoolean>
-r <ParameterBoolean>
-b <ParameterBoolean>
-e <ParameterBoolean>
GRASS_REGION_PARAMETER <ParameterExtent>
GRASS_REGION_CELLSIZE_PARAMETER <ParameterNumber>
output <OutputRaster>